From b299c1bc5f1801fbbe0817dfed7f3a7475a504ff Mon Sep 17 00:00:00 2001 From: Ulli Hafner Date: Tue, 21 Mar 2023 23:31:10 +0100 Subject: [PATCH 1/9] Improve checks title. When there are modified lines, print coverages of those lines. Otherwise, fall back to project coverage. --- .../steps/CoverageChecksPublisher.java | 37 ++++++++++++++-- .../metrics/steps/CoverageViewModel.java | 1 - .../metrics/AbstractCoverageTest.java | 17 +++++++- .../charts/TreeMapNodeConverterTest.java | 3 +- .../steps/CoverageChecksPublisherTest.java | 42 ++++++++++++++++++- 5 files changed, 93 insertions(+), 7 deletions(-) diff --git a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java index 3d43eead2..082cc1d03 100644 --- a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java +++ b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java @@ -5,7 +5,10 @@ import java.util.Collections; import java.util.List; import java.util.NavigableMap; +import java.util.NavigableSet; +import java.util.Set; import java.util.TreeMap; +import java.util.TreeSet; import java.util.stream.Collectors; import org.apache.commons.lang3.math.Fraction; @@ -93,9 +96,37 @@ ChecksDetails extractChecksDetails() { } private String getChecksTitle() { - return String.format("%s: %s", - FORMATTER.getDisplayName(Baseline.MODIFIED_LINES), - action.formatValue(Baseline.MODIFIED_LINES, Metric.LINE)); + Baseline baseline = selectBaseline(); + return getMetricsForTitle().stream() + .filter(metric -> action.hasValue(baseline, metric)) + .map(metric -> format(baseline, metric)) + .collect(Collectors.joining(", ", "", ".")); + } + + private Baseline selectBaseline() { + if (action.hasBaselineResult(Baseline.MODIFIED_LINES)) { + return Baseline.MODIFIED_LINES; + } + else { + return Baseline.PROJECT; + } + } + + private String format(final Baseline baseline, final Metric metric) { + String suffix; + if (action.hasDelta(baseline, metric)) { + suffix = String.format(" (%s)", action.formatDelta(baseline, metric)); + } + else { + suffix = ""; + } + return String.format("%s: %s%s", + FORMATTER.getDisplayName(metric), action.formatValue(baseline, metric), suffix); + } + + private NavigableSet getMetricsForTitle() { + return new TreeSet<>( + Set.of(Metric.LINE, Metric.BRANCH, Metric.MUTATION)); } private String getSummary() { diff --git a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageViewModel.java b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageViewModel.java index d7a735a8b..659b72a92 100644 --- a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageViewModel.java +++ b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageViewModel.java @@ -68,7 +68,6 @@ public class CoverageViewModel extends DefaultAsyncTableContentProvider implemen static final String ABSOLUTE_COVERAGE_TABLE_ID = "absolute-coverage-table"; static final String MODIFIED_LINES_COVERAGE_TABLE_ID = "modified-lines-coverage-table"; - static final String MODIFIED_FILES_COVERAGE_TABLE_ID = "modified-files-coverage-table"; static final String INDIRECT_COVERAGE_TABLE_ID = "indirect-coverage-table"; private static final String INLINE_SUFFIX = "-inline"; private static final String INFO_MESSAGES_VIEW_URL = "info"; diff --git a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/AbstractCoverageTest.java b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/AbstractCoverageTest.java index 0f1fd9f5c..5ecd4e615 100644 --- a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/AbstractCoverageTest.java +++ b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/AbstractCoverageTest.java @@ -10,6 +10,7 @@ import org.junitpioneer.jupiter.DefaultLocale; import edu.hm.hafner.coverage.Coverage.CoverageBuilder; +import edu.hm.hafner.coverage.CoverageParser; import edu.hm.hafner.coverage.Metric; import edu.hm.hafner.coverage.Node; import edu.hm.hafner.coverage.Value; @@ -50,8 +51,22 @@ public abstract class AbstractCoverageTest extends ResourceTest { * @return the parsed coverage tree */ protected Node readJacocoResult(final String fileName) { + return readResult(fileName, new JacocoParser()); + } + + /** + * Reads and parses a JaCoCo coverage report. + * + * @param fileName + * the name of the coverage report file + * @param parser + * the parser to use + * + * @return the parsed coverage tree + */ + protected Node readResult(final String fileName, final CoverageParser parser) { try { - var node = new JacocoParser().parse(Files.newBufferedReader(getResourceAsFile(fileName)), log); + var node = parser.parse(Files.newBufferedReader(getResourceAsFile(fileName)), log); node.splitPackages(); return node; } diff --git a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/charts/TreeMapNodeConverterTest.java b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/charts/TreeMapNodeConverterTest.java index 3be8940fe..2d70893c7 100644 --- a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/charts/TreeMapNodeConverterTest.java +++ b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/charts/TreeMapNodeConverterTest.java @@ -5,6 +5,7 @@ import org.junit.jupiter.api.Test; +import edu.hm.hafner.coverage.CoverageParser; import edu.hm.hafner.coverage.Metric; import edu.hm.hafner.coverage.Node; import edu.hm.hafner.echarts.LabeledTreeMapNode; @@ -70,7 +71,7 @@ private List aggregateChildren(final LabeledTreeMapNode root } @Override - protected Node readJacocoResult(final String fileName) { + protected Node readResult(final String fileName, final CoverageParser parser) { return super.readJacocoResult("../steps/" + fileName); } diff --git a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisherTest.java b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisherTest.java index 0ff8117e9..eb2e99723 100644 --- a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisherTest.java +++ b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisherTest.java @@ -8,6 +8,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.Fraction; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import org.junitpioneer.jupiter.DefaultLocale; @@ -15,6 +16,7 @@ import edu.hm.hafner.coverage.Coverage.CoverageBuilder; import edu.hm.hafner.coverage.Metric; import edu.hm.hafner.coverage.Node; +import edu.hm.hafner.coverage.parser.PitestParser; import hudson.model.Run; @@ -39,6 +41,35 @@ class CoverageChecksPublisherTest extends AbstractCoverageTest { private static final String REPORT_NAME = "Name"; private static final int ANNOTATIONS_COUNT_FOR_MODIFIED = 3; + @Test + void shouldShowProjectBaselineForJaCoCo() { + var result = readJacocoResult("jacoco-codingstyle.xml"); + + var publisher = new CoverageChecksPublisher(createActionWithoutDelta(result), result, REPORT_NAME, + ChecksAnnotationScope.SKIP, createJenkins()); + + assertThatTitleIs(publisher, "Line Coverage: 91.02% (294/323), Branch Coverage: 93.97% (109/116)."); + } + + @Test + void shouldShowProjectBaselineForPit() { + var result = readResult("mutations.xml", new PitestParser()); + + var publisher = new CoverageChecksPublisher(createActionWithoutDelta(result), result, REPORT_NAME, + ChecksAnnotationScope.SKIP, createJenkins()); + + assertThatTitleIs(publisher, "Line Coverage: 93.84% (198/211), Mutation Coverage: 90.24% (222/246)."); + } + + private void assertThatTitleIs(final CoverageChecksPublisher publisher, final String expectedTitle) { + var checkDetails = publisher.extractChecksDetails(); + assertThat(checkDetails.getOutput()).isPresent().get().satisfies(output -> { + assertThat(output.getTitle()).isPresent() + .get() + .isEqualTo(expectedTitle); + }); + } + @ParameterizedTest(name = "should create checks (scope = {0}, expected annotations = {1})") @CsvSource({"SKIP, 0", "ALL_LINES, 36", "MODIFIED_LINES, 3"}) void shouldCreateChecksReport(final ChecksAnnotationScope scope, final int expectedAnnotations) { @@ -61,7 +92,7 @@ private void assertThatDetailsAreCorrect(final ChecksDetails checkDetails, final assertThat(checkDetails.getOutput()).isPresent().get().satisfies(output -> { assertThat(output.getTitle()).isPresent() .get() - .isEqualTo("Modified code lines: 50.00% (1/2)"); + .isEqualTo("Line Coverage: 50.00% (1/2) (+50.00%)"); assertThat(output.getText()).isEmpty(); assertChecksAnnotations(output, expectedAnnotations); assertSummary(output); @@ -134,4 +165,13 @@ private CoverageBuildAction createCoverageBuildAction(final Node result) { List.of(testCoverage), new TreeMap<>(Map.of(Metric.LINE, Fraction.ONE_HALF)), List.of(testCoverage), new TreeMap<>(Map.of(Metric.LINE, Fraction.ONE_HALF)), List.of(testCoverage), false); } + + private CoverageBuildAction createActionWithoutDelta(final Node result) { + var run = mock(Run.class); + when(run.getUrl()).thenReturn(BUILD_LINK); + + return new CoverageBuildAction(run, COVERAGE_ID, REPORT_NAME, StringUtils.EMPTY, result, + new QualityGateResult(), null, "refId", + new TreeMap<>(), List.of(), new TreeMap<>(), List.of(), new TreeMap<>(), List.of(), false); + } } From 0a93286941cb36444e26e416c81c183f0a6f68d6 Mon Sep 17 00:00:00 2001 From: Ulli Hafner Date: Wed, 22 Mar 2023 14:48:40 +0100 Subject: [PATCH 2/9] Always set an end line for annotations. --- .../steps/CoverageChecksPublisher.java | 23 +++++++++++++------ .../steps/CoverageChecksPublisherTest.java | 5 +++- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java index 082cc1d03..46c617d18 100644 --- a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java +++ b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java @@ -163,7 +163,10 @@ private Collection getMissingLines(final FileNode fi var builder = createAnnotationBuilder(fileNode).withTitle("Not covered line"); return fileNode.getMissedLines().stream() - .map(line -> builder.withMessage("Line " + line + " is not covered by tests").withStartLine(line).build()) + .map(line -> builder.withMessage("Line " + line + " is not covered by tests") + .withStartLine(line) + .withEndLine(line) + .build()) .collect(Collectors.toList()); } @@ -172,7 +175,9 @@ private Collection getSurvivedMutations(final FileNo return fileNode.getSurvivedMutations().entrySet().stream() .map(entry -> builder.withMessage(createMutationMessage(entry.getKey(), entry.getValue())) - .withStartLine(entry.getKey()).build()) + .withStartLine(entry.getKey()) + .withEndLine(entry.getKey()) + .build()) .collect(Collectors.toList()); } @@ -188,7 +193,9 @@ private Collection getPartiallyCoveredLines(final Fi return fileNode.getPartiallyCoveredLines().entrySet().stream() .map(entry -> builder.withMessage(createBranchMessage(entry.getKey(), entry.getValue())) - .withStartLine(entry.getKey()).build()) + .withStartLine(entry.getKey()) + .withEndLine(entry.getKey()) + .build()) .collect(Collectors.toList()); } @@ -213,19 +220,21 @@ private String getCoverageReportBaseUrl() { private String getOverallCoverageSummary(final Node root) { String sectionHeader = getSectionHeader(2, Messages.Checks_Summary()); - var modifiedFilesCoverageRoot = root.filterByModifiedFiles(); - var modifiedLinesCoverageRoot = root.filterByModifiedLines(); - var indirectlyChangedCoverage = root.filterByIndirectChanges(); - var projectCoverageHeader = getBulletListItem(1, formatText(TextFormat.BOLD, getUrlText(Baseline.PROJECT_DELTA.getTitle(), getCoverageReportBaseUrl() + Baseline.PROJECT_DELTA.getUrl()))); + + var modifiedFilesCoverageRoot = root.filterByModifiedFiles(); var modifiedFilesCoverageHeader = getBulletListItem(1, formatText(TextFormat.BOLD, getUrlText(Baseline.MODIFIED_FILES_DELTA.getTitle(), getCoverageReportBaseUrl() + Baseline.MODIFIED_FILES_DELTA.getUrl()))); + + var modifiedLinesCoverageRoot = root.filterByModifiedLines(); var modifiedLinesCoverageHeader = getBulletListItem(1, formatText(TextFormat.BOLD, getUrlText(Baseline.MODIFIED_LINES_DELTA.getTitle(), getCoverageReportBaseUrl() + Baseline.MODIFIED_LINES_DELTA.getUrl()))); + + var indirectlyChangedCoverage = root.filterByIndirectChanges(); var indirectCoverageChangesHeader = getBulletListItem(1, formatText(TextFormat.BOLD, getUrlText(Baseline.INDIRECT.getTitle(), getCoverageReportBaseUrl() + Baseline.INDIRECT.getUrl()))); diff --git a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisherTest.java b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisherTest.java index eb2e99723..144a33d32 100644 --- a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisherTest.java +++ b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisherTest.java @@ -92,7 +92,7 @@ private void assertThatDetailsAreCorrect(final ChecksDetails checkDetails, final assertThat(checkDetails.getOutput()).isPresent().get().satisfies(output -> { assertThat(output.getTitle()).isPresent() .get() - .isEqualTo("Line Coverage: 50.00% (1/2) (+50.00%)"); + .isEqualTo("Line Coverage: 50.00% (1/2) (+50.00%)."); assertThat(output.getText()).isEmpty(); assertChecksAnnotations(output, expectedAnnotations); assertSummary(output); @@ -115,6 +115,7 @@ private void assertChecksAnnotations(final ChecksOutput checksOutput, final int assertThat(annotation.getPath()).contains("edu/hm/hafner/util/TreeStringBuilder.java"); assertThat(annotation.getMessage()).contains("Line 61 is not covered by tests"); assertThat(annotation.getStartLine()).isPresent().get().isEqualTo(61); + assertThat(annotation.getEndLine()).isPresent().get().isEqualTo(61); }, annotation -> { assertThat(annotation.getTitle()).contains("Not covered line"); @@ -122,6 +123,7 @@ private void assertChecksAnnotations(final ChecksOutput checksOutput, final int assertThat(annotation.getPath()).contains("edu/hm/hafner/util/TreeStringBuilder.java"); assertThat(annotation.getMessage()).contains("Line 62 is not covered by tests"); assertThat(annotation.getStartLine()).isPresent().get().isEqualTo(62); + assertThat(annotation.getEndLine()).isPresent().get().isEqualTo(62); }, annotation -> { assertThat(annotation.getTitle()).contains("Partially covered line"); @@ -129,6 +131,7 @@ private void assertChecksAnnotations(final ChecksOutput checksOutput, final int assertThat(annotation.getPath()).contains("edu/hm/hafner/util/TreeStringBuilder.java"); assertThat(annotation.getMessage()).contains("Line 113 is only partially covered, one branch is missing"); assertThat(annotation.getStartLine()).isPresent().get().isEqualTo(113); + assertThat(annotation.getEndLine()).isPresent().get().isEqualTo(113); }); } else { From 00cbf8a9d7e07b52db67838afd76ef6657c27494 Mon Sep 17 00:00:00 2001 From: Ulli Hafner Date: Wed, 22 Mar 2023 21:34:05 +0100 Subject: [PATCH 3/9] Compute description by looping over baselines and values. --- .../steps/CoverageChecksPublisher.java | 105 ++++++------------ ...e-publisher-summary.checks-expected-result | 19 +--- 2 files changed, 39 insertions(+), 85 deletions(-) diff --git a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java index 46c617d18..4f71de7da 100644 --- a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java +++ b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java @@ -17,6 +17,7 @@ import edu.hm.hafner.coverage.FileNode; import edu.hm.hafner.coverage.Metric; import edu.hm.hafner.coverage.Node; +import edu.hm.hafner.coverage.Value; import edu.hm.hafner.util.VisibleForTesting; import hudson.Functions; @@ -90,7 +91,7 @@ ChecksDetails extractChecksDetails() { .withName(checksName) .withStatus(ChecksStatus.COMPLETED) .withConclusion(getCheckConclusion(action.getQualityGateResult().getOverallStatus())) - .withDetailsURL(getCoverageReportBaseUrl()) + .withDetailsURL(getBaseUrl()) .withOutput(output) .build(); } @@ -213,81 +214,41 @@ private ChecksAnnotationBuilder createAnnotationBuilder(final FileNode fileNode) .withAnnotationLevel(ChecksAnnotationLevel.WARNING); } - private String getCoverageReportBaseUrl() { + private String getBaseUrl() { return jenkinsFacade.getAbsoluteUrl(action.getOwner().getUrl(), action.getUrlName()); } - private String getOverallCoverageSummary(final Node root) { - String sectionHeader = getSectionHeader(2, Messages.Checks_Summary()); - - var projectCoverageHeader = getBulletListItem(1, - formatText(TextFormat.BOLD, getUrlText(Baseline.PROJECT_DELTA.getTitle(), - getCoverageReportBaseUrl() + Baseline.PROJECT_DELTA.getUrl()))); - - var modifiedFilesCoverageRoot = root.filterByModifiedFiles(); - var modifiedFilesCoverageHeader = getBulletListItem(1, - formatText(TextFormat.BOLD, getUrlText(Baseline.MODIFIED_FILES_DELTA.getTitle(), - getCoverageReportBaseUrl() + Baseline.MODIFIED_FILES_DELTA.getUrl()))); - - var modifiedLinesCoverageRoot = root.filterByModifiedLines(); - var modifiedLinesCoverageHeader = getBulletListItem(1, - formatText(TextFormat.BOLD, getUrlText(Baseline.MODIFIED_LINES_DELTA.getTitle(), - getCoverageReportBaseUrl() + Baseline.MODIFIED_LINES_DELTA.getUrl()))); - - var indirectlyChangedCoverage = root.filterByIndirectChanges(); - var indirectCoverageChangesHeader = getBulletListItem(1, - formatText(TextFormat.BOLD, getUrlText(Baseline.INDIRECT.getTitle(), - getCoverageReportBaseUrl() + Baseline.INDIRECT.getUrl()))); - - var projectCoverageLine = getBulletListItem(2, - formatCoverageForMetric(Metric.LINE, Baseline.PROJECT)); - var projectCoverageBranch = getBulletListItem(2, - formatCoverageForMetric(Metric.BRANCH, Baseline.PROJECT)); - var projectCoverageComplexity = getBulletListItem(2, formatRootValueOfMetric(root, Metric.COMPLEXITY_DENSITY)); - var projectCoverageLoc = getBulletListItem(2, formatRootValueOfMetric(root, Metric.LOC)); - - var modifiedFilesCoverageLine = getBulletListItem(2, - formatCoverageForMetric(Metric.LINE, Baseline.MODIFIED_FILES)); - var modifiedFilesCoverageBranch = getBulletListItem(2, - formatCoverageForMetric(Metric.BRANCH, Baseline.MODIFIED_FILES)); - var modifiedFilesCoverageComplexity = getBulletListItem(2, - formatRootValueOfMetric(modifiedFilesCoverageRoot, Metric.COMPLEXITY_DENSITY)); - var modifiedFilesCoverageLoc = getBulletListItem(2, - formatRootValueOfMetric(modifiedFilesCoverageRoot, Metric.LOC)); - - var modifiedLinesCoverageLine = getBulletListItem(2, - formatCoverageForMetric(Metric.LINE, Baseline.MODIFIED_LINES)); - var modifiedLinesCoverageBranch = getBulletListItem(2, - formatCoverageForMetric(Metric.BRANCH, Baseline.MODIFIED_LINES)); - var modifiedLinesCoverageLoc = getBulletListItem(2, - formatRootValueOfMetric(modifiedLinesCoverageRoot, Metric.LOC)); - - var indirectCoverageChangesLine = getBulletListItem(2, - formatCoverageForMetric(Metric.LINE, Baseline.INDIRECT)); - var indirectCoverageChangesBranch = getBulletListItem(2, - formatCoverageForMetric(Metric.BRANCH, Baseline.INDIRECT)); - var indirectCoverageChangesLoc = getBulletListItem(2, - formatRootValueOfMetric(indirectlyChangedCoverage, Metric.LOC)); + private List getBaselines() { + return List.of(Baseline.PROJECT, Baseline.MODIFIED_FILES, Baseline.MODIFIED_LINES, Baseline.INDIRECT); + } - return sectionHeader - + projectCoverageHeader - + projectCoverageLine - + projectCoverageBranch - + projectCoverageComplexity - + projectCoverageLoc - + modifiedFilesCoverageHeader - + modifiedFilesCoverageLine - + modifiedFilesCoverageBranch - + modifiedFilesCoverageComplexity - + modifiedFilesCoverageLoc - + modifiedLinesCoverageHeader - + modifiedLinesCoverageLine - + modifiedLinesCoverageBranch - + modifiedLinesCoverageLoc - + indirectCoverageChangesHeader - + indirectCoverageChangesLine - + indirectCoverageChangesBranch - + indirectCoverageChangesLoc; + + private String getOverallCoverageSummary(final Node root) { + StringBuilder description = new StringBuilder(getSectionHeader(2, Messages.Checks_Summary())); + + for (Baseline baseline : getBaselines()) { + if (action.hasBaselineResult(baseline)) { + String title; + if (action.hasDelta(baseline)) { + title = action.getDeltaBaseline(baseline).getTitle(); + } + else { + title = baseline.getTitle(); + } + description.append(getBulletListItem(1, + formatText(TextFormat.BOLD, + getUrlText(title, getBaseUrl() + baseline.getUrl())))); + for (Value value : action.getValues(baseline)) { + String display = String.format("%s: %s", action.getFormatter().getDisplayName(value.getMetric()), + action.getFormatter().formatValue(value)); + if (action.hasDelta(baseline, value.getMetric())) { + display += String.format(" (%s)", action.formatDelta(baseline, value.getMetric())); + } + description.append(getBulletListItem(2, display)); + } + } + } + return description.toString(); } /** diff --git a/plugin/src/test/resources/io/jenkins/plugins/coverage/metrics/steps/coverage-publisher-summary.checks-expected-result b/plugin/src/test/resources/io/jenkins/plugins/coverage/metrics/steps/coverage-publisher-summary.checks-expected-result index b35ca8ef9..feaa7440a 100644 --- a/plugin/src/test/resources/io/jenkins/plugins/coverage/metrics/steps/coverage-publisher-summary.checks-expected-result +++ b/plugin/src/test/resources/io/jenkins/plugins/coverage/metrics/steps/coverage-publisher-summary.checks-expected-result @@ -1,23 +1,16 @@ ## Coverage Report Overview * **[Overall project (difference to reference job)](http://127.0.0.1:8080/job/pipeline-coding-style/job/5/coverage#overview)** - * Line Coverage: 91.02% (294/323) / +50.00% - * Branch Coverage: 93.97% (109/116) / n/a - * Complexity Density: +49.54% + * Line Coverage: 91.02% (294/323) (+50.00%) + * Branch Coverage: 93.97% (109/116) + * Complexity Density: 0.50% * Lines of Code: 323 * **[Modified files (difference to overall project)](http://127.0.0.1:8080/job/pipeline-coding-style/job/5/coverage#modifiedFilesCoverage)** - * Line Coverage: 50.00% (1/2) / +50.00% - * Branch Coverage: n/a / n/a - * Complexity Density: +43.40% - * Lines of Code: 53 + * Line Coverage: 50.00% (1/2) (+50.00%) * **[Modified code lines (difference to modified files)](http://127.0.0.1:8080/job/pipeline-coding-style/job/5/coverage#modifiedLinesCoverage)** - * Line Coverage: 50.00% (1/2) / +50.00% - * Branch Coverage: n/a / n/a - * Lines of Code: 3 + * Line Coverage: 50.00% (1/2) (+50.00%) * **[Indirect changes](http://127.0.0.1:8080/job/pipeline-coding-style/job/5/coverage#indirectCoverage)** - * Line Coverage: 50.00% (1/2) / n/a - * Branch Coverage: n/a / n/a - * Lines of Code: n/a + * Line Coverage: 50.00% (1/2) ## Quality Gates Summary - INACTIVE From bd393dbee17e7903cf2182817405b0da0433a389 Mon Sep 17 00:00:00 2001 From: Ulli Hafner Date: Thu, 23 Mar 2023 07:51:06 +0100 Subject: [PATCH 4/9] Compute description by looping over baselines and values. --- .../metrics/model/ElementFormatter.java | 15 +++++++++++++++ .../metrics/steps/CoverageBuildAction.java | 17 +++++++++++++++++ .../metrics/steps/CoverageChecksPublisher.java | 14 +++----------- .../resources/coverage/coverage-summary.jelly | 9 +-------- ...age-publisher-summary.checks-expected-result | 6 +++--- 5 files changed, 39 insertions(+), 22 deletions(-) diff --git a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/model/ElementFormatter.java b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/model/ElementFormatter.java index d952037b5..db50e1f85 100644 --- a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/model/ElementFormatter.java +++ b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/model/ElementFormatter.java @@ -226,6 +226,21 @@ public String formatValueWithMetric(final Value value) { + format(value, Functions.getCurrentLocale()); } + /** + * Returns a formatted and localized String representation of the specified value prefixed with the metric name. + * The value will be printed with all details (number of covered and missed items). + * + * @param value + * the value to format + * + * @return the value formatted as a string + */ + @SuppressWarnings("unused") // Called by jelly view + public String formatDetailedValueWithMetric(final Value value) { + return getDisplayName(value.getMetric()) + ": " + + formatDetails(value, Functions.getCurrentLocale()); + } + /** * Transforms percentages with a ',' decimal separator to a representation using a '.' in order to use the * percentage for styling HTML tags. diff --git a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageBuildAction.java b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageBuildAction.java index aface9cff..96585e9bb 100644 --- a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageBuildAction.java +++ b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageBuildAction.java @@ -277,6 +277,23 @@ public Baseline getDeltaBaseline(final Baseline baseline) { throw new NoSuchElementException("No delta baseline for this baseline: " + baseline); } + /** + * Returns the title text for the specified baseline. + * + * @param baseline + * the baseline to get the title for + * + * @return the title + */ + public String getTitle(final Baseline baseline) { + if (hasDelta(baseline)) { + return getDeltaBaseline(baseline).getTitle(); + } + else { + return baseline.getTitle(); + } + } + /** * Returns all available values for the specified baseline. * diff --git a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java index 4f71de7da..6df9fad94 100644 --- a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java +++ b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java @@ -228,21 +228,13 @@ private String getOverallCoverageSummary(final Node root) { for (Baseline baseline : getBaselines()) { if (action.hasBaselineResult(baseline)) { - String title; - if (action.hasDelta(baseline)) { - title = action.getDeltaBaseline(baseline).getTitle(); - } - else { - title = baseline.getTitle(); - } description.append(getBulletListItem(1, formatText(TextFormat.BOLD, - getUrlText(title, getBaseUrl() + baseline.getUrl())))); + getUrlText(action.getTitle(baseline), getBaseUrl() + baseline.getUrl())))); for (Value value : action.getValues(baseline)) { - String display = String.format("%s: %s", action.getFormatter().getDisplayName(value.getMetric()), - action.getFormatter().formatValue(value)); + String display = FORMATTER.formatDetailedValueWithMetric(value); if (action.hasDelta(baseline, value.getMetric())) { - display += String.format(" (%s)", action.formatDelta(baseline, value.getMetric())); + display += String.format(" - Delta: %s", action.formatDelta(baseline, value.getMetric())); } description.append(getBulletListItem(2, display)); } diff --git a/plugin/src/main/resources/coverage/coverage-summary.jelly b/plugin/src/main/resources/coverage/coverage-summary.jelly index 4693884db..7139e9d10 100644 --- a/plugin/src/main/resources/coverage/coverage-summary.jelly +++ b/plugin/src/main/resources/coverage/coverage-summary.jelly @@ -10,14 +10,7 @@
  • - - - ${it.getDeltaBaseline(baseline).title} - - - ${baseline.title} - - + ${it.getTitle(baseline)}
    diff --git a/plugin/src/test/resources/io/jenkins/plugins/coverage/metrics/steps/coverage-publisher-summary.checks-expected-result b/plugin/src/test/resources/io/jenkins/plugins/coverage/metrics/steps/coverage-publisher-summary.checks-expected-result index feaa7440a..fde6afb9b 100644 --- a/plugin/src/test/resources/io/jenkins/plugins/coverage/metrics/steps/coverage-publisher-summary.checks-expected-result +++ b/plugin/src/test/resources/io/jenkins/plugins/coverage/metrics/steps/coverage-publisher-summary.checks-expected-result @@ -1,14 +1,14 @@ ## Coverage Report Overview * **[Overall project (difference to reference job)](http://127.0.0.1:8080/job/pipeline-coding-style/job/5/coverage#overview)** - * Line Coverage: 91.02% (294/323) (+50.00%) + * Line Coverage: 91.02% (294/323) - Delta: +50.00% * Branch Coverage: 93.97% (109/116) * Complexity Density: 0.50% * Lines of Code: 323 * **[Modified files (difference to overall project)](http://127.0.0.1:8080/job/pipeline-coding-style/job/5/coverage#modifiedFilesCoverage)** - * Line Coverage: 50.00% (1/2) (+50.00%) + * Line Coverage: 50.00% (1/2) - Delta: +50.00% * **[Modified code lines (difference to modified files)](http://127.0.0.1:8080/job/pipeline-coding-style/job/5/coverage#modifiedLinesCoverage)** - * Line Coverage: 50.00% (1/2) (+50.00%) + * Line Coverage: 50.00% (1/2) - Delta: +50.00% * **[Indirect changes](http://127.0.0.1:8080/job/pipeline-coding-style/job/5/coverage#indirectCoverage)** * Line Coverage: 50.00% (1/2) From bf2b0182f31fd65cd474d13a8d0abd49f82de90b Mon Sep 17 00:00:00 2001 From: Ulli Hafner Date: Thu, 23 Mar 2023 08:05:01 +0100 Subject: [PATCH 5/9] Remove unused variable. --- .../coverage/metrics/steps/CoverageChecksPublisher.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java index 6df9fad94..a6d83bc9d 100644 --- a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java +++ b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java @@ -132,7 +132,7 @@ private NavigableSet getMetricsForTitle() { private String getSummary() { var root = rootNode; - return getOverallCoverageSummary(root) + "\n\n" + return getOverallCoverageSummary() + "\n\n" + getQualityGatesSummary() + "\n\n" + getProjectMetricsSummary(root); } @@ -223,7 +223,7 @@ private List getBaselines() { } - private String getOverallCoverageSummary(final Node root) { + private String getOverallCoverageSummary() { StringBuilder description = new StringBuilder(getSectionHeader(2, Messages.Checks_Summary())); for (Baseline baseline : getBaselines()) { From d2600cbd3daee477034855a120dc35ca21605b22 Mon Sep 17 00:00:00 2001 From: Ulli Hafner Date: Thu, 23 Mar 2023 08:05:24 +0100 Subject: [PATCH 6/9] Fix styling. --- .../plugins/coverage/metrics/steps/CoverageChecksPublisher.java | 1 - 1 file changed, 1 deletion(-) diff --git a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java index a6d83bc9d..1e810e823 100644 --- a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java +++ b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java @@ -222,7 +222,6 @@ private List getBaselines() { return List.of(Baseline.PROJECT, Baseline.MODIFIED_FILES, Baseline.MODIFIED_LINES, Baseline.INDIRECT); } - private String getOverallCoverageSummary() { StringBuilder description = new StringBuilder(getSectionHeader(2, Messages.Checks_Summary())); From bcc84783ff70851c8e4c37de8adda7f2c0352447 Mon Sep 17 00:00:00 2001 From: Ulli Hafner Date: Thu, 23 Mar 2023 14:25:32 +0100 Subject: [PATCH 7/9] Remove unused methods. --- .../metrics/steps/CoverageChecksPublisher.java | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java index 1e810e823..62ef594a6 100644 --- a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java +++ b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageChecksPublisher.java @@ -281,17 +281,6 @@ private String getProjectMetricsSummary(final Node result) { + projectCoverageDeltaRow; } - private String formatCoverageForMetric(final Metric metric, final Baseline baseline) { - return String.format("%s: %s / %s", FORMATTER.getDisplayName(metric), - action.formatValue(baseline, metric), action.formatDelta(baseline, metric)); - } - - private String formatRootValueOfMetric(final Node root, final Metric metric) { - var value = root.getValue(metric); - return value.map(FORMATTER::formatValueWithMetric) - .orElseGet(() -> FORMATTER.getDisplayName(metric) + ": " + Messages.Coverage_Not_Available()); - } - private String formatText(final TextFormat format, final String text) { switch (format) { case BOLD: From 7915e6d1a8210952d2dc059c6ce8151cee51dd5c Mon Sep 17 00:00:00 2001 From: Ulli Hafner Date: Thu, 23 Mar 2023 14:52:42 +0100 Subject: [PATCH 8/9] Fix broken test. --- .../metrics/charts/TreeMapNodeConverterTest.java | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/charts/TreeMapNodeConverterTest.java b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/charts/TreeMapNodeConverterTest.java index 2d70893c7..198a33bca 100644 --- a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/charts/TreeMapNodeConverterTest.java +++ b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/charts/TreeMapNodeConverterTest.java @@ -5,7 +5,6 @@ import org.junit.jupiter.api.Test; -import edu.hm.hafner.coverage.CoverageParser; import edu.hm.hafner.coverage.Metric; import edu.hm.hafner.coverage.Node; import edu.hm.hafner.echarts.LabeledTreeMapNode; @@ -23,12 +22,12 @@ * @author Ullrich Hafner */ class TreeMapNodeConverterTest extends AbstractCoverageTest { - private static final ColorProvider COLOR_PROVIDER = ColorProviderFactory.createDefaultColorProvider(); + private static final String PREFIX = "../steps/"; @Test void shouldConvertCodingStyleToTree() { - Node tree = readJacocoResult(JACOCO_CODING_STYLE_FILE); + Node tree = readJacocoResult(PREFIX + JACOCO_CODING_STYLE_FILE); LabeledTreeMapNode root = new TreeMapNodeConverter().toTreeChartModel(tree, Metric.LINE, COLOR_PROVIDER); assertThat(root.getName()).isEqualTo("Java coding style"); @@ -50,7 +49,7 @@ void shouldConvertCodingStyleToTree() { @Test void shouldReadBranchCoverage() { - Node tree = readJacocoResult(JACOCO_ANALYSIS_MODEL_FILE); + Node tree = readJacocoResult(PREFIX + JACOCO_ANALYSIS_MODEL_FILE); LabeledTreeMapNode root = new TreeMapNodeConverter().toTreeChartModel(tree, Metric.BRANCH, COLOR_PROVIDER); @@ -70,11 +69,6 @@ private List aggregateChildren(final LabeledTreeMapNode root return subChildren; } - @Override - protected Node readResult(final String fileName, final CoverageParser parser) { - return super.readJacocoResult("../steps/" + fileName); - } - /** * Gets the matching fill color for the coverage percentage. * From 50788298aa183cf165ab83aa38ae6ada5eaa45a0 Mon Sep 17 00:00:00 2001 From: Ulli Hafner Date: Thu, 23 Mar 2023 19:48:07 +0100 Subject: [PATCH 9/9] Fix POM of UI tests. --- ui-tests/pom.xml | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/ui-tests/pom.xml b/ui-tests/pom.xml index 0250c5f0f..4a63707ee 100644 --- a/ui-tests/pom.xml +++ b/ui-tests/pom.xml @@ -16,10 +16,14 @@ UI Tests of Code Coverage Plugin - 2.396 + 2.395 + 3.39 2.3 2.36.1 ${project.groupId}.code.coverage.api.ui.tests + + + -Djava.awt.headless=true -Xmx1024m -Djenkins.test.timeout=1000 --add-opens java.base/sun.reflect.annotation=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.util.concurrent=ALL-UNNAMED @@ -36,7 +40,7 @@ org.jenkins-ci acceptance-test-harness - 1.118 + 5504.v485694f31cdf org.apache.httpcomponents @@ -134,6 +138,13 @@ + + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + + + @@ -143,6 +154,13 @@ true + + org.revapi + revapi-maven-plugin + + true + + org.assertj assertj-assertions-generator-maven-plugin @@ -226,11 +244,9 @@ - org.revapi - revapi-maven-plugin - - true - + org.jenkins-ci.tools + maven-hpi-plugin + ${hpi-plugin.version}