diff --git a/src/main/java/edu/hm/hafner/grading/AnalysisMarkdown.java b/src/main/java/edu/hm/hafner/grading/AnalysisMarkdown.java index 31fa28a4..5f306753 100644 --- a/src/main/java/edu/hm/hafner/grading/AnalysisMarkdown.java +++ b/src/main/java/edu/hm/hafner/grading/AnalysisMarkdown.java @@ -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); @@ -68,4 +68,38 @@ public String create(final AggregatedScore aggregation) { private int sum(final AggregatedScore score, final Function 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(); + + } } diff --git a/src/main/java/edu/hm/hafner/grading/CoverageMarkdown.java b/src/main/java/edu/hm/hafner/grading/CoverageMarkdown.java index c469bb62..f63d4825 100644 --- a/src/main/java/edu/hm/hafner/grading/CoverageMarkdown.java +++ b/src/main/java/edu/hm/hafner/grading/CoverageMarkdown.java @@ -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( @@ -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 getCoverageScores(AggregatedScore aggregation); private int sum(final AggregatedScore score, final Function property) { return getCoverageScores(score).stream().map(property).reduce(Integer::sum).orElse(0); } - - private int average(final AggregatedScore score, final Function property) { - return sum(score, property) / getCoverageScores(score).size(); - } } diff --git a/src/main/java/edu/hm/hafner/grading/GradingReport.java b/src/main/java/edu/hm/hafner/grading/GradingReport.java index eb2de30c..fcca3959 100644 --- a/src/main/java/edu/hm/hafner/grading/GradingReport.java +++ b/src/main/java/edu/hm/hafner/grading/GradingReport.java @@ -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 @@ -57,22 +56,62 @@ 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. * @@ -80,10 +119,12 @@ public String getDetails(final AggregatedScore 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); diff --git a/src/main/java/edu/hm/hafner/grading/ScoreMarkdown.java b/src/main/java/edu/hm/hafner/grading/ScoreMarkdown.java index cbcb905b..4028a3bc 100644 --- a/src/main/java/edu/hm/hafner/grading/ScoreMarkdown.java +++ b/src/main/java/edu/hm/hafner/grading/ScoreMarkdown.java @@ -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); } @@ -70,4 +74,7 @@ protected String renderImpact(final int impact) { } } + protected String createNotEnabled() { + return getTitle(": not enabled"); + } } diff --git a/src/main/java/edu/hm/hafner/grading/TestMarkdown.java b/src/main/java/edu/hm/hafner/grading/TestMarkdown.java index 6f9721cb..1c5c96f4 100644 --- a/src/main/java/edu/hm/hafner/grading/TestMarkdown.java +++ b/src/main/java/edu/hm/hafner/grading/TestMarkdown.java @@ -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( @@ -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 property) { return score.getTestScores().stream().map(property).reduce(Integer::sum).orElse(0); } diff --git a/src/test/java/edu/hm/hafner/grading/GradingReportTest.java b/src/test/java/edu/hm/hafner/grading/GradingReportTest.java index 91d09289..6b8594d1 100644 --- a/src/test/java/edu/hm/hafner/grading/GradingReportTest.java +++ b/src/test/java/edu/hm/hafner/grading/GradingReportTest.java @@ -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 @@ -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