Skip to content

Commit

Permalink
Add a summary, that can be used as a comment in a PR.
Browse files Browse the repository at this point in the history
  • Loading branch information
uhafner committed Dec 1, 2023
1 parent b2003c6 commit 5c89929
Show file tree
Hide file tree
Showing 6 changed files with 182 additions and 14 deletions.
36 changes: 35 additions & 1 deletion src/main/java/edu/hm/hafner/grading/AnalysisMarkdown.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public AnalysisMarkdown() {
public String create(final AggregatedScore aggregation) {
var scores = aggregation.getAnalysisScores();
if (scores.isEmpty()) {
return getTitle(": not enabled");
return createNotEnabled();
}

var comment = new StringBuilder(MESSAGE_INITIAL_CAPACITY);
Expand Down Expand Up @@ -68,4 +68,38 @@ public String create(final AggregatedScore aggregation) {
private int sum(final AggregatedScore score, final Function<AnalysisScore, Integer> property) {
return score.getAnalysisScores().stream().map(property).reduce(Integer::sum).orElse(0);
}

/**
* Renders the test results in Markdown.
*
* @param aggregation
* Aggregated score
*
* @return returns formatted string
*/
public String createSummary(final AggregatedScore aggregation) {
var scores = aggregation.getAnalysisScores();
if (scores.isEmpty()) {
return createNotEnabled();
}

var comment = new StringBuilder(MESSAGE_INITIAL_CAPACITY);

for (AnalysisScore score : scores) {
comment.append("#");
comment.append(getTitle(score));
if (score.getReport().isEmpty()) {
comment.append("no warnings found");
}
else {
comment.append(String.format("%d warnings found (%d errors, %d high, %d normal, %d low)",
score.getTotalSize(), score.getErrorSize(),
score.getHighSeveritySize(), score.getNormalSeveritySize(), score.getLowSeveritySize()));
}
comment.append("\n");
}

return comment.toString();

}
}
49 changes: 43 additions & 6 deletions src/main/java/edu/hm/hafner/grading/CoverageMarkdown.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,15 @@ abstract class CoverageMarkdown extends ScoreMarkdown {
public String create(final AggregatedScore aggregation) {
var scores = getCoverageScores(aggregation);
if (scores.isEmpty()) {
return getTitle(": not enabled");
return createNotEnabled();
}

var comment = new StringBuilder(MESSAGE_INITIAL_CAPACITY);

for (CoverageScore score : scores) {
var configuration = score.getConfiguration();
comment.append(getTitle(String.format(": %d of %d", score.getValue(), score.getMaxScore()), score.getName()));
comment.append(
getTitle(String.format(": %d of %d", score.getValue(), score.getMaxScore()), score.getName()));
comment.append(formatColumns("Name", coveredText, missedText, "Impact"));
comment.append(formatColumns(":-:", ":-:", ":-:", ":-:"));
score.getSubScores().forEach(subScore -> comment.append(formatColumns(
Expand All @@ -61,13 +62,49 @@ public String create(final AggregatedScore aggregation) {
return comment.toString();
}

/**
* Renders the test results in Markdown.
*
* @param aggregation
* Aggregated score
*
* @return returns formatted string
*/
public String createSummary(final AggregatedScore aggregation) {
var scores = getCoverageScores(aggregation);
if (scores.isEmpty()) {
return createNotEnabled();
}

var comment = new StringBuilder(MESSAGE_INITIAL_CAPACITY);

for (CoverageScore score : scores) {
comment.append("#");
comment.append(getTitle(score));
comment.append(String.format("%d%% %s, %d%% %s",
score.getCoveredPercentage(), getPlainText(coveredText),
score.getMissedPercentage(), getPlainText(missedText)));
comment.append("\n");
}

return comment.toString();
}

private String getPlainText(final String label) {
return label.replace("%", "");
}

/**
* Returns the concrete coverage scores to render.
*
* @param aggregation
* the aggregated score
*
* @return the coverage scores
*/
protected abstract List<CoverageScore> getCoverageScores(AggregatedScore aggregation);

private int sum(final AggregatedScore score, final Function<CoverageScore, Integer> property) {
return getCoverageScores(score).stream().map(property).reduce(Integer::sum).orElse(0);
}

private int average(final AggregatedScore score, final Function<CoverageScore, Integer> property) {
return sum(score, property) / getCoverageScores(score).size();
}
}
51 changes: 46 additions & 5 deletions src/main/java/edu/hm/hafner/grading/GradingReport.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ public String getHeader() {
}

/**
* Returns a short summary for the grading results. This text does not use Markdown and fits into a
* single line.
* Returns a short summary for the grading results. This text does not use Markdown and fits into a single line.
*
* @param score
* the aggregated score
Expand Down Expand Up @@ -57,33 +56,75 @@ public String getSummary(final AggregatedScore score) {
summary);
}

/**
* Creates a summary of the grading results in Markdown.
*
* @param score
* the aggregated score
* @param title
* the title of the summary
*
* @return Markdown text
*/
public String getMarkdownSummary(final AggregatedScore score, final String title) {
var summary = new StringBuilder();

summary.append(createTotal(score, title));

if (score.hasTests()) {
var markdown = new TestMarkdown();
summary.append(markdown.createSummary(score));
}
if (score.hasCodeCoverage()) {
var markdown = new CodeCoverageMarkdown();
summary.append(markdown.createSummary(score));
}
if (score.hasMutationCoverage()) {
var markdown = new MutationCoverageMarkdown();
summary.append(markdown.createSummary(score));
}
if (score.hasAnalysis()) {
var markdown = new AnalysisMarkdown();
summary.append(markdown.createSummary(score));
}

return summary.toString();
}

/**
* Creates a detailed description of the grading results in Markdown.
*
* @param score
* the aggregated score
*
* @return Markdown text
*/
public String getDetails(final AggregatedScore score) {
return String.format("# Total score: %s/%s%n",
score.getAchievedScore(), score.getMaxScore())
return createTotal(score, "Total score")
+ new TestMarkdown().create(score)
+ new AnalysisMarkdown().create(score)
+ new CodeCoverageMarkdown().create(score)
+ new MutationCoverageMarkdown().create(score);
}

private String createTotal(final AggregatedScore score, final String title) {
return String.format("## %s: %s/%s%n",
title, score.getAchievedScore(), score.getMaxScore());
}

/**
* Creates an error message in Markdown.
*
* @param score
* the aggregated score
* @param exception
* the exception that caused the error
*
* @return Markdown text
*/
public String getErrors(final AggregatedScore score, final Throwable exception) {
return String.format("# Partial score: %s/%s%n:construction: The grading has been aborted due to an error.:construction:%n",
return String.format(
"# Partial score: %s/%s%n:construction: The grading has been aborted due to an error.:construction:%n",
score.getAchievedScore(), score.getMaxScore())
+ createExceptionSection(exception)
+ createLogSection(score);
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/edu/hm/hafner/grading/ScoreMarkdown.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ protected String getTitle(final String message, final String name) {
return String.format("## :%s: %s%s :%s:%n", icon, name, message, icon);
}

protected String getTitle(final Score<?, ?> score) {
return getTitle(String.format(": %d of %d", score.getValue(), score.getMaxScore()), score.getName());
}

String formatColumns(final Object... columns) {
return format("|%s", columns);
}
Expand Down Expand Up @@ -70,4 +74,7 @@ protected String renderImpact(final int impact) {
}
}

protected String createNotEnabled() {
return getTitle(": not enabled");
}
}
39 changes: 37 additions & 2 deletions src/main/java/edu/hm/hafner/grading/TestMarkdown.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ public TestMarkdown() {
public String create(final AggregatedScore aggregation) {
var scores = aggregation.getTestScores();
if (scores.isEmpty()) {
return getTitle(": not enabled");
return createNotEnabled();
}

var comment = new StringBuilder(MESSAGE_INITIAL_CAPACITY);

for (TestScore score : scores) {
var configuration = score.getConfiguration();
comment.append(getTitle(String.format(": %d of %d", score.getValue(), score.getMaxScore()), score.getName()));
comment.append(getTitle(score));
comment.append(formatColumns("Name", "Passed", "Skipped", "Failed", "Impact"));
comment.append(formatColumns(":-:", ":-:", ":-:", ":-:", ":-:"));
score.getSubScores().forEach(subScore -> comment.append(formatColumns(
Expand Down Expand Up @@ -76,6 +76,41 @@ public String create(final AggregatedScore aggregation) {

}

/**
* Renders the test results in Markdown.
*
* @param aggregation
* Aggregated score
*
* @return returns formatted string
*/
public String createSummary(final AggregatedScore aggregation) {
var scores = aggregation.getTestScores();
if (scores.isEmpty()) {
return createNotEnabled();
}

var comment = new StringBuilder(MESSAGE_INITIAL_CAPACITY);

for (TestScore score : scores) {
comment.append("#");
comment.append(getTitle(score));
if (score.hasFailures()) {
comment.append(String.format("%d tests failed, %d passed", score.getFailedSize(), score.getPassedSize()));
}
else {
comment.append(String.format("%d tests passed", score.getPassedSize()));
}
if (score.getSkippedSize() > 0) {
comment.append(String.format(", %d skipped", score.getSkippedSize()));
}
comment.append("\n");
}

return comment.toString();

}

private int sum(final AggregatedScore score, final Function<TestScore, Integer> property) {
return score.getTestScores().stream().map(property).reduce(Integer::sum).orElse(0);
}
Expand Down
14 changes: 14 additions & 0 deletions src/test/java/edu/hm/hafner/grading/GradingReportTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ void shouldCreateEmptyResults() {
"Unit Tests Score: not enabled",
"Coverage Score: not enabled",
"Static Analysis Warnings Score: not enabled");
assertThat(results.getMarkdownSummary(score, "Summary"))
.contains("# Summary: 0/0");
}

@Test
Expand All @@ -40,6 +42,18 @@ void shouldCreateAllResults() {
":microbe: PIT: 20 of 100",
"Style: 30 of 100",
"Bugs: 0 of 100");
assertThat(results.getMarkdownSummary(score, "Summary")).contains(
"# Summary: 167/500",
"JUnit: 77 of 100",
"14 tests failed, 5 passed, 3 skipped",
"JaCoCo: 40 of 100",
"70% Covered , 30% Missed",
"PIT: 20 of 100",
"60% Killed , 40% Survived",
"Style: 30 of 100",
"10 warnings found (1 errors, 2 high, 3 normal, 4 low)",
"Bugs: 0 of 100",
"10 warnings found (4 errors, 3 high, 2 normal, 1 low)");
}

@Test
Expand Down

0 comments on commit 5c89929

Please sign in to comment.