From 4111156d7e09a27473d92c7742ab157325b270c6 Mon Sep 17 00:00:00 2001 From: Henry Coles Date: Wed, 20 Sep 2023 17:58:08 +0100 Subject: [PATCH] suppress reporting of coverage stats Arcmutates advanced incremental processing includes the option to avoid gathering coverage for tests which cannot kill an in scope mutant. Although this speeds up processing the html report shows most lines as uncovered when this feature is activated. Reporting of line coverage it therefore disabled when this feature is activated. --- .../pitest/aggregate/ReportAggregator.java | 41 +++++++++++-------- .../mutationtest/config/ReportOptions.java | 10 +++++ .../report/xml/XMLReportFactory.java | 2 +- .../report/xml/XMLReportListener.java | 11 +++-- .../report/xml/XMLReportListenerTest.java | 6 +-- .../report/html/AnnotatedLineFactory.java | 17 ++++---- .../report/html/HtmlReportFactory.java | 2 +- .../html/MutationHtmlReportListener.java | 19 ++++++--- .../mutation/mutation_package_index.st | 8 +++- .../templates/mutation/package_index.st | 8 +++- .../html/MutationHtmlReportListenerTest.java | 2 +- .../AbstractPitAggregationReportMojo.java | 3 +- 12 files changed, 83 insertions(+), 46 deletions(-) diff --git a/pitest-aggregator/src/main/java/org/pitest/aggregate/ReportAggregator.java b/pitest-aggregator/src/main/java/org/pitest/aggregate/ReportAggregator.java index f9eab9bcb..e6b055dcf 100644 --- a/pitest-aggregator/src/main/java/org/pitest/aggregate/ReportAggregator.java +++ b/pitest-aggregator/src/main/java/org/pitest/aggregate/ReportAggregator.java @@ -8,7 +8,6 @@ import org.pitest.coverage.analysis.LineMapper; import org.pitest.mutationtest.ClassMutationResults; import org.pitest.mutationtest.MutationMetaData; -import org.pitest.mutationtest.MutationResult; import org.pitest.mutationtest.MutationResultListener; import org.pitest.mutationtest.SourceLocator; import org.pitest.mutationtest.build.CoverageTransformer; @@ -21,7 +20,10 @@ import org.pitest.util.ResultOutputStrategy; import java.io.File; +import java.io.IOException; +import java.io.UncheckedIOException; import java.nio.charset.Charset; +import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; @@ -29,9 +31,9 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.function.Function; import java.util.logging.Logger; import java.util.stream.Collectors; +import java.util.stream.Stream; import static java.util.Arrays.asList; @@ -68,7 +70,9 @@ private ReportAggregator(SettingsFactory settings, public AggregationResult aggregateReport() throws ReportAggregationException { SmartSourceLocator sourceLocator = new SmartSourceLocator(asPaths(this.sourceCodeDirectories), inputCharset); - final MutationResultListener mutationResultListener = createResultListener(sourceLocator, Collections.emptySet()); + boolean partialCoverage = scanForPartialCoverageFlag(mutationFiles); + + final MutationResultListener mutationResultListener = createResultListener(sourceLocator, Collections.emptySet(), partialCoverage); final ReportAggregatorResultListener reportAggregatorResultListener = new ReportAggregatorResultListener(); reportAggregatorResultListener.runStart(); @@ -93,11 +97,27 @@ public AggregationResult aggregateReport() throws ReportAggregationException { return reportAggregatorResultListener.result(); } - private MutationResultListener createResultListener(SourceLocator sourceLocator, Collection mutatorNames) throws ReportAggregationException { + private boolean scanForPartialCoverageFlag(Set mutationFiles) { + // scan for the partial coverage flag. All files should have the same flag, so only really + // need to scan the first line of the first file, but expressing as a loop here just because. + for (File each : mutationFiles) { + try (Stream lines = Files.lines(each.toPath())) { + // search for a false flag as this is the most likely case + if (lines.anyMatch(l -> l.contains(" mutatorNames, boolean partialCoverage) throws ReportAggregationException { final CodeSource codeSource = this.codeSourceAggregator.createCodeSource(); final ReportCoverage coverageDatabase = calculateCoverage(codeSource); - return new MutationHtmlReportListener(outputCharset, coverageDatabase, this.resultOutputStrategy, mutatorNames, sourceLocator); + return new MutationHtmlReportListener(outputCharset, coverageDatabase, this.resultOutputStrategy, mutatorNames, partialCoverage, sourceLocator); } private Collection asPaths(Collection files) { @@ -106,17 +126,6 @@ private Collection asPaths(Collection files) { .collect(Collectors.toList()); } - private static Function> resultToMutatorName() { - return a -> { - try { - final String mutatorName = a.getDetails().getId().getMutator();//MutatorUtil.loadMutator(a.getDetails().getMutator()).getName(); - return Collections.singletonList(mutatorName); - } catch (final Exception e) { - throw new RuntimeException("Cannot convert to mutator: " + a.getDetails().getMutator(), e); - } - }; - } - private ReportCoverage calculateCoverage(final CodeSource codeSource) throws ReportAggregationException { try { Collection coverageData = this.blockCoverageLoader.loadData().stream() diff --git a/pitest-entry/src/main/java/org/pitest/mutationtest/config/ReportOptions.java b/pitest-entry/src/main/java/org/pitest/mutationtest/config/ReportOptions.java index 216e01247..55c06939b 100644 --- a/pitest-entry/src/main/java/org/pitest/mutationtest/config/ReportOptions.java +++ b/pitest-entry/src/main/java/org/pitest/mutationtest/config/ReportOptions.java @@ -132,6 +132,8 @@ public class ReportOptions { private boolean includeLaunchClasspath = true; + private boolean reportCoverage = true; + private Properties properties; private int maxSurvivors; @@ -647,6 +649,13 @@ public void setOutputEncoding(Charset outputEncoding) { this.outputEncoding = outputEncoding; } + public boolean shouldReportCoverage() { + return reportCoverage; + } + + public void setReportCoverage(boolean reportCoverage) { + this.reportCoverage = reportCoverage; + } @Override public String toString() { @@ -695,6 +704,7 @@ public String toString() { .add("projectBase=" + projectBase) .add("inputEncoding=" + inputEncoding) .add("outputEncoding=" + outputEncoding) + .add("reportCoverage=" + reportCoverage) .toString(); } diff --git a/pitest-entry/src/main/java/org/pitest/mutationtest/report/xml/XMLReportFactory.java b/pitest-entry/src/main/java/org/pitest/mutationtest/report/xml/XMLReportFactory.java index 70891c304..c32951b2e 100644 --- a/pitest-entry/src/main/java/org/pitest/mutationtest/report/xml/XMLReportFactory.java +++ b/pitest-entry/src/main/java/org/pitest/mutationtest/report/xml/XMLReportFactory.java @@ -25,7 +25,7 @@ public class XMLReportFactory implements MutationResultListenerFactory { @Override public MutationResultListener getListener(Properties props, final ListenerArguments args) { - return new XMLReportListener(args.getOutputStrategy(), args.isFullMutationMatrix()); + return new XMLReportListener(args.getOutputStrategy(), args.isFullMutationMatrix(), args.data().shouldReportCoverage()); } @Override diff --git a/pitest-entry/src/main/java/org/pitest/mutationtest/report/xml/XMLReportListener.java b/pitest-entry/src/main/java/org/pitest/mutationtest/report/xml/XMLReportListener.java index 57280fa72..fb88bd96c 100644 --- a/pitest-entry/src/main/java/org/pitest/mutationtest/report/xml/XMLReportListener.java +++ b/pitest-entry/src/main/java/org/pitest/mutationtest/report/xml/XMLReportListener.java @@ -55,13 +55,16 @@ public class XMLReportListener implements MutationResultListener { private final Writer out; private final boolean fullMutationMatrix; - public XMLReportListener(final ResultOutputStrategy outputStrategy, boolean fullMutationMatrix) { - this(outputStrategy.createWriterForFile("mutations.xml"), fullMutationMatrix); + private final boolean partialCoverage; + + public XMLReportListener(final ResultOutputStrategy outputStrategy, boolean fullMutationMatrix, boolean partialCoverage) { + this(outputStrategy.createWriterForFile("mutations.xml"), fullMutationMatrix, partialCoverage); } - public XMLReportListener(final Writer out, boolean fullMutationMatrix) { + public XMLReportListener(final Writer out, boolean fullMutationMatrix, boolean partialCoverage) { this.out = out; this.fullMutationMatrix = fullMutationMatrix; + this.partialCoverage = partialCoverage; } private void writeResult(final ClassMutationResults metaData) { @@ -176,7 +179,7 @@ private void write(final String value) { @Override public void runStart() { write("\n"); - write("\n"); + write("\n"); } @Override diff --git a/pitest-entry/src/test/java/org/pitest/mutationtest/report/xml/XMLReportListenerTest.java b/pitest-entry/src/test/java/org/pitest/mutationtest/report/xml/XMLReportListenerTest.java index ac5c4a6d4..8408d4687 100644 --- a/pitest-entry/src/test/java/org/pitest/mutationtest/report/xml/XMLReportListenerTest.java +++ b/pitest-entry/src/test/java/org/pitest/mutationtest/report/xml/XMLReportListenerTest.java @@ -37,14 +37,14 @@ public class XMLReportListenerTest { @Before public void setup() { this.out = new StringWriter(); - this.testee = new XMLReportListener(this.out, false); + this.testee = new XMLReportListener(this.out, false, false); } @Test public void shouldCreateAValidXmlDocumentWhenNoResults() { this.testee.runStart(); this.testee.runEnd(); - final String expected = "\n\n\n"; + final String expected = "\n\n\n"; assertThat(expected).isEqualTo(this.out.toString()); } @@ -61,7 +61,7 @@ public void shouldOutputKillingTestWhenOneFound() { @Test public void shouldOutputFullMutationMatrixWhenEnabled() { - this.testee = new XMLReportListener(this.out, true); + this.testee = new XMLReportListener(this.out, true, false); final MutationResult mr = new MutationResult( MutationTestResultMother.createDetails(), new MutationStatusTestPair(3, DetectionStatus.KILLED, Arrays.asList("foo", "foo2"), Arrays.asList("bar"))); diff --git a/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/AnnotatedLineFactory.java b/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/AnnotatedLineFactory.java index 0f5afbf59..4f150d624 100644 --- a/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/AnnotatedLineFactory.java +++ b/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/AnnotatedLineFactory.java @@ -32,19 +32,20 @@ public class AnnotatedLineFactory { - private final Collection mutations; - private final ReportCoverage coverage; - private final Collection classesInFile; - - private final Set coveredLines; + private final Collection mutations; + private final Collection classesInFile; + private final Set coveredLines; + private final boolean reportCoverage; public AnnotatedLineFactory( final Collection mutations, - final ReportCoverage coverage, final Collection classes) { + final ReportCoverage coverage, + final Collection classes, + boolean reportCoverage) { this.mutations = mutations; - this.coverage = coverage; this.classesInFile = classes; this.coveredLines = findCoveredLines(classes,coverage); + this.reportCoverage = reportCoverage; } private Set findCoveredLines(Collection classes, ReportCoverage coverage) { @@ -93,7 +94,7 @@ private Predicate isAtLineNumber(final int lineNumber) { private LineStatus lineCovered(final int line) { - if (!isCodeLine(line)) { + if (!isCodeLine(line) || !reportCoverage) { return LineStatus.NotApplicable; } else { if (isLineCovered(line)) { diff --git a/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/HtmlReportFactory.java b/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/HtmlReportFactory.java index f32b61334..e47bacb59 100644 --- a/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/HtmlReportFactory.java +++ b/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/HtmlReportFactory.java @@ -27,7 +27,7 @@ public class HtmlReportFactory implements MutationResultListenerFactory { public MutationResultListener getListener(Properties props, ListenerArguments args) { return new MutationHtmlReportListener(args.data().getOutputEncoding(), args.getCoverage(), - args.getOutputStrategy(), args.getEngine().getMutatorNames(), + args.getOutputStrategy(), args.getEngine().getMutatorNames(), args.data().shouldReportCoverage(), args.getLocator()); } diff --git a/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/MutationHtmlReportListener.java b/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/MutationHtmlReportListener.java index bd0db514d..4bba4d2dd 100644 --- a/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/MutationHtmlReportListener.java +++ b/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/MutationHtmlReportListener.java @@ -56,16 +56,21 @@ public class MutationHtmlReportListener implements MutationResultListener { private final String css; private final Charset outputCharset; - - public MutationHtmlReportListener(Charset outputCharset, final ReportCoverage coverage, - final ResultOutputStrategy outputStrategy, - Collection mutatorNames, final SourceLocator... locators) { + private final boolean reportCoverage; + + public MutationHtmlReportListener(Charset outputCharset, + ReportCoverage coverage, + ResultOutputStrategy outputStrategy, + Collection mutatorNames, + boolean reportCoverage, + SourceLocator... locators) { this.outputCharset = outputCharset; this.coverage = coverage; this.outputStrategy = outputStrategy; this.sourceRoots = new HashSet<>(asList(locators)); this.mutatorNames = new HashSet<>(mutatorNames); this.css = loadCss(); + this.reportCoverage = reportCoverage; } private String loadCss() { @@ -101,7 +106,7 @@ private void generateAnnotatedSourceFile( st.setAttribute("sourceFile", sourceFile); st.setAttribute("mutatedClasses", mutationMetaData.getMutatedClasses()); st.setAttribute("outputCharset", this.outputCharset); - + st.setAttribute("showCoverage", this.reportCoverage); writer.write(st.toString()); @@ -153,7 +158,7 @@ private List createAnnotatedSourceCodeLines(final String sourceFile, sourceFile); if (reader.isPresent()) { final AnnotatedLineFactory alf = new AnnotatedLineFactory( - mutationsForThisFile.list(), this.coverage, classes); + mutationsForThisFile.list(), this.coverage, classes, this.reportCoverage); return alf.convert(reader.get()); } return Collections.emptyList(); @@ -215,6 +220,7 @@ private void createIndexPages() { st.setAttribute("totals", totals); st.setAttribute("packageSummaries", psd); st.setAttribute("outputCharset", this.outputCharset); + st.setAttribute("showCoverage", this.reportCoverage); try { writer.write(st.toString()); writer.close(); @@ -233,6 +239,7 @@ private void createPackageIndexPage(final PackageSummaryData psData) { .getPackageDirectory() + File.separator + "index.html"); st.setAttribute("packageData", psData); st.setAttribute("outputCharset", this.outputCharset); + st.setAttribute("showCoverage", this.reportCoverage); try { writer.write(st.toString()); writer.close(); diff --git a/pitest-html-report/src/main/resources/templates/mutation/mutation_package_index.st b/pitest-html-report/src/main/resources/templates/mutation/mutation_package_index.st index 82a5664a4..4916a5053 100644 --- a/pitest-html-report/src/main/resources/templates/mutation/mutation_package_index.st +++ b/pitest-html-report/src/main/resources/templates/mutation/mutation_package_index.st @@ -21,7 +21,9 @@ $totals.numberOfFiles$ - $totals.lineCoverage$%
$totals.numberOfLinesCovered$/$totals.numberOfLines$
+ $if(showCoverage)$ $totals.lineCoverage$%
$totals.numberOfLinesCovered$/$totals.numberOfLines$
+ $else$
n/a
+ $endif$ $totals.mutationCoverage$%
$totals.numberOfMutationsDetected$/$totals.numberOfMutations$
$totals.testStrength$%
$totals.numberOfMutationsDetected$/$totals.numberOfMutationsWithCoverage$
@@ -45,7 +47,9 @@ $packageSummaries:{ summary | $summary.packageName$ $summary.totals.numberOfFiles$ -
$summary.totals.lineCoverage$%
$summary.totals.numberOfLinesCovered$/$summary.totals.numberOfLines$
+ $if(showCoverage)$
$summary.totals.lineCoverage$%
$summary.totals.numberOfLinesCovered$/$summary.totals.numberOfLines$
+ $else$
n/a
+ $endif$
$summary.totals.mutationCoverage$%
$summary.totals.numberOfMutationsDetected$/$summary.totals.numberOfMutations$
$summary.totals.testStrength$%
$summary.totals.numberOfMutationsDetected$/$summary.totals.numberOfMutationsWithCoverage$
diff --git a/pitest-html-report/src/main/resources/templates/mutation/package_index.st b/pitest-html-report/src/main/resources/templates/mutation/package_index.st index 8918bb473..67fa013b4 100644 --- a/pitest-html-report/src/main/resources/templates/mutation/package_index.st +++ b/pitest-html-report/src/main/resources/templates/mutation/package_index.st @@ -21,7 +21,9 @@ $packageData.totals.numberOfFiles$ - $packageData.totals.lineCoverage$%
$packageData.totals.numberOfLinesCovered$/$packageData.totals.numberOfLines$
+ $if(showCoverage)$$packageData.totals.lineCoverage$%
$packageData.totals.numberOfLinesCovered$/$packageData.totals.numberOfLines$
+ $else$
n/a
+ $endif$ $packageData.totals.mutationCoverage$%
$packageData.totals.numberOfMutationsDetected$/$packageData.totals.numberOfMutations$
$packageData.totals.testStrength$%
$packageData.totals.numberOfMutationsDetected$/$packageData.totals.numberOfMutationsWithCoverage$
@@ -43,7 +45,9 @@ $packageData.summaryData:{ summary | $summary.fileName$ -
$summary.totals.lineCoverage$%
$summary.totals.numberOfLinesCovered$/$summary.totals.numberOfLines$
+ $if(showCoverage)$
$summary.totals.lineCoverage$%
$summary.totals.numberOfLinesCovered$/$summary.totals.numberOfLines$
+ $else$
n/a
+ $endif$
$summary.totals.mutationCoverage$%
$summary.totals.numberOfMutationsDetected$/$summary.totals.numberOfMutations$
$summary.totals.testStrength$%
$summary.totals.numberOfMutationsDetected$/$summary.totals.numberOfMutationsWithCoverage$
diff --git a/pitest-html-report/src/test/java/org/pitest/mutationtest/report/html/MutationHtmlReportListenerTest.java b/pitest-html-report/src/test/java/org/pitest/mutationtest/report/html/MutationHtmlReportListenerTest.java index 909538f57..2168269b0 100644 --- a/pitest-html-report/src/test/java/org/pitest/mutationtest/report/html/MutationHtmlReportListenerTest.java +++ b/pitest-html-report/src/test/java/org/pitest/mutationtest/report/html/MutationHtmlReportListenerTest.java @@ -69,7 +69,7 @@ public void setUp() { this.classInfo); this.testee = new MutationHtmlReportListener(StandardCharsets.UTF_8, this.coverageDb, - this.outputStrategy, Collections.emptyList(), this.sourceLocator); + this.outputStrategy, Collections.emptyList(), true, this.sourceLocator); } @Test diff --git a/pitest-maven/src/main/java/org/pitest/maven/report/AbstractPitAggregationReportMojo.java b/pitest-maven/src/main/java/org/pitest/maven/report/AbstractPitAggregationReportMojo.java index 63a9c4036..b155c8f47 100644 --- a/pitest-maven/src/main/java/org/pitest/maven/report/AbstractPitAggregationReportMojo.java +++ b/pitest-maven/src/main/java/org/pitest/maven/report/AbstractPitAggregationReportMojo.java @@ -157,8 +157,7 @@ private List getProjectFilesByFilter(final File projectBaseDir, } @SuppressWarnings("unchecked") - private List getCompiledDirs(final MavenProject project) - throws Exception { + private List getCompiledDirs(final MavenProject project) { final List sourceRoots = new ArrayList<>(); for (final Object artifactObj : FCollection .filter(project.getPluginArtifactMap().values(), new DependencyFilter(