From 43cca2102115f3bf8ec74df572dda84e461c9b97 Mon Sep 17 00:00:00 2001 From: abaudet Date: Fri, 24 Jan 2020 18:03:24 +0400 Subject: [PATCH] feat(report) Add new score value for aggregation of several modules When using several modules, the current mutation coverage was not enough accurate. If the same mutation survived in one submodule but was killed by a test in another module (typically an integration test), the result was survived. The mutation coverage was then 0/2 (0%). Developer HAD TO analyze manually each line to be sure that the same mutation really survived. Now developer can quickly see packages and files that need to be covered. Only the unique mutations are considered. --- .../pitest/aggregate/ReportAggregator.java | 12 ++- .../report/html/AnnotatedLineFactory.java | 8 +- .../html/DetectionStatusCalculator.java | 10 ++ .../pitest/mutationtest/report/html/Line.java | 13 +-- .../MergeStatusForSameMutationAndLine.java | 102 ++++++++++++++++++ .../html/MutationHtmlReportListener.java | 3 +- .../report/html/MutationScore.java | 54 ++++++++++ .../report/html/MutationScoreUtil.java | 29 +++++ .../report/html/MutationTestSummaryData.java | 44 +++++++- .../report/html/MutationTotals.java | 11 ++ .../report/html/ResultComparator.java | 11 +- .../mutation/mutation_package_index.st | 26 +++++ .../templates/mutation/package_index.st | 25 +++++ .../resources/templates/mutation/style.css | 39 ++++++- .../html/MutationTestSummaryDataTest.java | 27 +++-- 15 files changed, 383 insertions(+), 31 deletions(-) create mode 100644 pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/DetectionStatusCalculator.java create mode 100644 pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/MergeStatusForSameMutationAndLine.java create mode 100644 pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/MutationScore.java create mode 100644 pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/MutationScoreUtil.java 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 0bce89536..9a74bc23f 100644 --- a/pitest-aggregator/src/main/java/org/pitest/aggregate/ReportAggregator.java +++ b/pitest-aggregator/src/main/java/org/pitest/aggregate/ReportAggregator.java @@ -99,14 +99,20 @@ private Map> blocksToMap( for (final BlockCoverage blockData : coverageData) { for (int i = blockData.getBlock().getFirstInsnInBlock(); i <= blockData.getBlock().getLastInsnInBlock(); i++) { - blockCoverageMap.put(new InstructionLocation(blockData.getBlock(), i), - new HashSet<>( - FCollection.map(blockData.getTests(), toTestInfo(blockData)))); + addBlockCoverage(blockCoverageMap, new InstructionLocation(blockData.getBlock(), i), + FCollection.map(blockData.getTests(), toTestInfo(blockData))); } } return blockCoverageMap; } + private void addBlockCoverage(Map> blockCoverageMap, InstructionLocation instructionLocation, List tests) { + if (!blockCoverageMap.containsKey(instructionLocation)) { + blockCoverageMap.put(instructionLocation, new HashSet<>()); + } + blockCoverageMap.get(instructionLocation).addAll(tests); + } + private Function toTestInfo(final BlockCoverage blockData) { return a -> new TestInfo(null, a, 0, Optional.ofNullable(blockData.getBlock().getLocation().getClassName()), blockData.getBlock().getBlock()); } 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 8bdb9214f..4637293f6 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 @@ -34,13 +34,16 @@ public class AnnotatedLineFactory { private final Collection mutations; private final CoverageDatabase statistics; private final Collection classesInFile; + private final DetectionStatusCalculator statusCalculator; public AnnotatedLineFactory( final Collection mutations, - final CoverageDatabase statistics, final Collection classes) { + final CoverageDatabase statistics, final Collection classes, + final DetectionStatusCalculator statusCalculator) { this.mutations = mutations; this.statistics = statistics; this.classesInFile = classes; + this.statusCalculator = statusCalculator; } public List convert(final Reader source) throws IOException { @@ -59,9 +62,10 @@ private Function stringToAnnotatedLine() { @Override public Line apply(final String a) { + List mutationsForLine = getMutationsForLine(this.lineNumber); final Line l = new Line(this.lineNumber, StringUtil.escapeBasicHtmlChars(a), lineCovered(this.lineNumber), - getMutationsForLine(this.lineNumber)); + mutationsForLine, statusCalculator.calculate(mutationsForLine)); this.lineNumber++; return l; } diff --git a/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/DetectionStatusCalculator.java b/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/DetectionStatusCalculator.java new file mode 100644 index 000000000..b1b3a26c6 --- /dev/null +++ b/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/DetectionStatusCalculator.java @@ -0,0 +1,10 @@ +package org.pitest.mutationtest.report.html; + +import java.util.List; + +import org.pitest.mutationtest.DetectionStatus; +import org.pitest.mutationtest.MutationResult; + +public interface DetectionStatusCalculator { + DetectionStatus calculate(List mutationsForLine); +} diff --git a/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/Line.java b/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/Line.java index 00e7ee53b..690660b57 100644 --- a/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/Line.java +++ b/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/Line.java @@ -14,6 +14,7 @@ */ package org.pitest.mutationtest.report.html; +import java.util.Collections; import java.util.List; import java.util.Optional; @@ -25,14 +26,17 @@ public class Line { private final String text; private final LineStatus lineCovered; private final List mutations; + private final DetectionStatus detectionStatus; public Line(final long number, final String text, - final LineStatus lineCovered, final List mutations) { + final LineStatus lineCovered, final List mutations, + final DetectionStatus detectionStatus) { this.number = number; this.text = text; this.lineCovered = lineCovered; this.mutations = mutations; - mutations.sort(new ResultComparator()); + this.detectionStatus = detectionStatus; + Collections.sort(mutations, new ResultComparator()); } public long getNumber() { @@ -52,10 +56,7 @@ public List getMutations() { } public Optional detectionStatus() { - if (this.mutations.isEmpty()) { - return Optional.empty(); - } - return Optional.ofNullable(this.mutations.get(0).getStatus()); + return Optional.ofNullable(detectionStatus); } public int getNumberOfMutations() { diff --git a/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/MergeStatusForSameMutationAndLine.java b/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/MergeStatusForSameMutationAndLine.java new file mode 100644 index 000000000..255157c64 --- /dev/null +++ b/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/MergeStatusForSameMutationAndLine.java @@ -0,0 +1,102 @@ +package org.pitest.mutationtest.report.html; + +import static org.pitest.mutationtest.report.html.MutationScoreUtil.groupBySameMutationOnSameLines; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.pitest.mutationtest.DetectionStatus; +import org.pitest.mutationtest.MutationResult; +import org.pitest.mutationtest.engine.MutationIdentifier; +import org.pitest.mutationtest.report.html.ResultComparator.DetectionStatusComparator; + +/** + * Compute the {@link DetectionStatus} according to the list of mutations applied on the line. + * This algorithm works with multi-projects. For example: + * + * Tested class + *

+ * 1   class Foo {
+ * 2     public int compare() {
+ * 3       if (a > b) {
+ * 4         return -1;
+ * 5       }
+ * 6       if (a < b) {
+ * 7         return 1;
+ * 8       }
+ * 9       return 0;
+ * 10    }
+ * 11  }
+ * 
+ * + * Module A contains Foo class. + * Module B depends on Module A. + * + * Test results 1 + * + * + * + * + * + * + * + * + * + *
mutations
ModuleTestMutation results
Module AUnitTest.identical()
  • line 9: return replaced by -1 -> SURVIVED
Module AUnitTest.identical()
  • line 9: return replaced by 1 -> SURVIVED
Module BIntegrationTest.sort()
  • line 9: return replaced by -1 -> KILLED
Module BIntegrationTest.sort()
  • line 9: return replaced by 1 -> SURVIVED
+ * + * There are several mutations applied on the same line and one mutation has survived across all tests and one mutation has been killed. + * So the result should be SURVIVED because for the same line, at least one mutation has survived. + * + * Test results 2 + * + * + * + * + * + * + * + * + * + *
mutations
ModuleTestMutation results
Module AUnitTest.identical()
  • line 9: return replaced by -1 -> SURVIVED
Module AUnitTest.identical()
  • line 9: return replaced by 1 -> KILLED
Module BIntegrationTest.sort()
  • line 9: return replaced by -1 -> KILLED
Module BIntegrationTest.sort()
  • line 9: return replaced by 1 -> SURVIVED
+ * + * In this case, all mutations are killed across several projects. So the result should be KILLED. + * + * @author Aurélien Baudet + * + */ +public class MergeStatusForSameMutationAndLine implements DetectionStatusCalculator { + @Override + public DetectionStatus calculate(List mutationsForLine) { + if (mutationsForLine.isEmpty()) { + return null; + } + Map> grouped = groupBySameMutationOnSameLines(mutationsForLine); + Map statusForSameMutation = new HashMap<>(); + // compute the status for each mutation + for (Entry> resultsByMutation : grouped.entrySet()) { + statusForSameMutation.put(resultsByMutation.getKey(), computeDetectionStatusForSameLineAndMutation(resultsByMutation.getValue())); + } + // for different mutations, take the worst mutation + List status = new ArrayList<>(statusForSameMutation.values()); + Collections.sort(status, new DetectionStatusComparator()); + if (status.isEmpty()) { + return null; + } + return status.get(0); + } + + private DetectionStatus computeDetectionStatusForSameLineAndMutation(Collection results) { + List list = new ArrayList<>(results); + Collections.sort(list, new ResultComparator()); + if (list.isEmpty()) { + return null; + } + // use best status to handle several tests across projects + return list.get(list.size() - 1).getStatus(); + } +} 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 298a77d1d..1644aca06 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 @@ -146,7 +146,8 @@ 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, + new MergeStatusForSameMutationAndLine()); return alf.convert(reader.get()); } return Collections.emptyList(); diff --git a/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/MutationScore.java b/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/MutationScore.java new file mode 100644 index 000000000..493bd0a0c --- /dev/null +++ b/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/MutationScore.java @@ -0,0 +1,54 @@ +package org.pitest.mutationtest.report.html; + +public class MutationScore { + private long numberOfUniqueMutations; + private long numberOfUniqueMutationsKilled; + private long numberOfUniqueMutationsDetected; + + public MutationScore() { + this(0, 0, 0); + } + + public MutationScore(long numberOfUniqueMutations, + long numberOfUniqueMutationsKilled, + long numberOfUniqueMutationsDetected) { + super(); + this.numberOfUniqueMutations = numberOfUniqueMutations; + this.numberOfUniqueMutationsKilled = numberOfUniqueMutationsKilled; + this.numberOfUniqueMutationsDetected = numberOfUniqueMutationsDetected; + } + + public long getNumberOfUniqueMutations() { + return numberOfUniqueMutations; + } + + public long getNumberOfUniqueMutationsKilled() { + return numberOfUniqueMutationsKilled; + } + + public long getNumberOfUniqueMutationsDetected() { + return numberOfUniqueMutationsDetected; + } + + public long getNumberOfUniqueMutationsPossiblyDetected() { + return numberOfUniqueMutationsDetected - numberOfUniqueMutationsKilled; + } + + public int getKilledScore() { + return numberOfUniqueMutations == 0 ? 100 + : Math.round((100f * numberOfUniqueMutationsKilled) + / numberOfUniqueMutations); + } + + public int getPossiblyDetectedScore() { + return numberOfUniqueMutations == 0 ? 100 + : Math.round((100f * getNumberOfUniqueMutationsDetected()) + / numberOfUniqueMutations); + } + + public void add(MutationScore score) { + numberOfUniqueMutations += score.numberOfUniqueMutations; + numberOfUniqueMutationsDetected += score.numberOfUniqueMutationsDetected; + numberOfUniqueMutationsKilled += score.numberOfUniqueMutationsKilled; + } +} diff --git a/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/MutationScoreUtil.java b/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/MutationScoreUtil.java new file mode 100644 index 000000000..54701ac13 --- /dev/null +++ b/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/MutationScoreUtil.java @@ -0,0 +1,29 @@ +package org.pitest.mutationtest.report.html; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.pitest.mutationtest.MutationResult; +import org.pitest.mutationtest.engine.MutationIdentifier; + +public final class MutationScoreUtil { + private MutationScoreUtil() { + super(); + } + + public static Map> groupBySameMutationOnSameLines(Collection mutations) { + Map> grouped = new HashMap<>(); + for (MutationResult each : mutations) { + Collection results = grouped.get(each.getDetails().getId()); + if (results == null) { + results = new ArrayList<>(); + grouped.put(each.getDetails().getId(), results); + } + results.add(each); + } + return grouped; + } + +} diff --git a/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/MutationTestSummaryData.java b/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/MutationTestSummaryData.java index 3f23c8e02..cb86b9d36 100644 --- a/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/MutationTestSummaryData.java +++ b/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/MutationTestSummaryData.java @@ -14,19 +14,22 @@ */ package org.pitest.mutationtest.report.html; -import org.pitest.classinfo.ClassInfo; -import org.pitest.coverage.TestInfo; -import org.pitest.functional.FCollection; -import org.pitest.mutationtest.MutationResult; +import static org.pitest.mutationtest.DetectionStatus.KILLED; +import static org.pitest.mutationtest.report.html.MutationScoreUtil.groupBySameMutationOnSameLines; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; -import java.util.Set; import java.util.TreeSet; +import java.util.Set; import java.util.function.BiFunction; import java.util.function.Function; +import org.pitest.classinfo.ClassInfo; +import org.pitest.coverage.TestInfo; +import org.pitest.functional.FCollection; +import org.pitest.mutationtest.MutationResult; + public class MutationTestSummaryData { private final String fileName; @@ -55,6 +58,7 @@ public MutationTotals getTotals() { mt.addLines(getNumberOfLines()); mt.addLinesCovered(this.numberOfCoveredLines); mt.addMutationsWithCoverage(this.getNumberOfMutationsWithCoverage()); + mt.addMutationScore(new MutationScore(getNumberOfUniqueMutations(), getNumberOfUniqueMutationsKilled(), getNumberOfUniqueMutationsDetected())); return mt; } @@ -130,6 +134,36 @@ private long getNumberOfMutationsDetected() { return count; } + private long getNumberOfUniqueMutations() { + return groupBySameMutationOnSameLines(mutations).entrySet().size(); + } + + private long getNumberOfUniqueMutationsDetected() { + int count = 0; + for (final Collection results : groupBySameMutationOnSameLines(mutations).values()) { + for (MutationResult each : results) { + if (each.getStatus().isDetected()) { + count++; + break; + } + } + } + return count; + } + + private long getNumberOfUniqueMutationsKilled() { + int count = 0; + for (final Collection results : groupBySameMutationOnSameLines(mutations).values()) { + for (MutationResult each : results) { + if (each.getStatus() == KILLED) { + count++; + break; + } + } + } + return count; + } + private Function> mutationToTargettedTests() { return a -> a.getDetails().getTestsInOrder(); } diff --git a/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/MutationTotals.java b/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/MutationTotals.java index cd852546f..7bf114b58 100644 --- a/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/MutationTotals.java +++ b/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/MutationTotals.java @@ -8,6 +8,7 @@ public class MutationTotals { private long numberOfMutations = 0; private long numberOfMutationsDetected = 0; private long numberOfMutationsWithCoverage = 0; + private MutationScore mutationScore = new MutationScore(); public long getNumberOfFiles() { return this.numberOfFiles; @@ -49,6 +50,10 @@ public void addMutationsDetetcted(final long mutationsKilled) { this.numberOfMutationsDetected += mutationsKilled; } + public void addMutationScore(final MutationScore score) { + mutationScore.add(score); + } + public int getLineCoverage() { return this.numberOfLines == 0 ? 100 : Math .round((100f * this.numberOfLinesCovered) / this.numberOfLines); @@ -74,6 +79,10 @@ public long getNumberOfMutationsWithCoverage() { return this.numberOfMutationsWithCoverage; } + public MutationScore getMutationScore() { + return mutationScore; + } + public void add(final MutationTotals data) { add(data.getNumberOfLines(), data.getNumberOfFiles(), data); } @@ -85,5 +94,7 @@ private void add(final long lines, final long files, final MutationTotals data) this.addMutations(data.getNumberOfMutations()); this.addMutationsDetetcted(data.getNumberOfMutationsDetected()); this.addMutationsWithCoverage(data.getNumberOfMutationsWithCoverage()); + this.addMutationScore(data.getMutationScore()); } + } \ No newline at end of file diff --git a/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/ResultComparator.java b/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/ResultComparator.java index 2dcec745a..02a2b2aa5 100644 --- a/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/ResultComparator.java +++ b/pitest-html-report/src/main/java/org/pitest/mutationtest/report/html/ResultComparator.java @@ -41,8 +41,17 @@ public int compare(MutationResult o1, MutationResult o2) { } - private int getRanking(DetectionStatus status) { + private static int getRanking(DetectionStatus status) { return RANK.get(status); } + + public static class DetectionStatusComparator implements Comparator, Serializable { + private static final long serialVersionUID = 1L; + + @Override + public int compare(DetectionStatus o1, DetectionStatus o2) { + return getRanking(o1) - getRanking(o2); + } + } } 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 9fd4e3ed1..6a69a0ea6 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 @@ -15,6 +15,7 @@ Line Coverage Mutation Coverage Test Strength + Mutation Score @@ -23,6 +24,18 @@ $totals.lineCoverage$%
$totals.numberOfLinesCovered$/$totals.numberOfLines$
$totals.mutationCoverage$%
$totals.numberOfMutationsDetected$/$totals.numberOfMutations$
$totals.testStrength$%
$totals.numberOfMutationsDetected$/$totals.numberOfMutationsWithCoverage$
+ +
$totals.mutationScore.killedScore$%
+
+
+
+
$totals.mutationScore.numberOfUniqueMutationsKilled$/$totals.mutationScore.numberOfUniqueMutations$
+
+
+
Killed: $totals.mutationScore.numberOfUniqueMutationsKilled$
+
Uncertain: $totals.mutationScore.numberOfUniqueMutationsPossiblyDetected$
+
+ @@ -37,6 +50,7 @@ Line Coverage Mutation Coverage Test Strength + Mutation Score @@ -47,6 +61,18 @@ $packageSummaries:{ summary |
$summary.totals.lineCoverage$%
$summary.totals.numberOfLinesCovered$/$summary.totals.numberOfLines$
$summary.totals.mutationCoverage$%
$summary.totals.numberOfMutationsDetected$/$summary.totals.numberOfMutations$
$summary.totals.testStrength$%
$summary.totals.numberOfMutationsDetected$/$summary.totals.numberOfMutationsWithCoverage$
+ +
$summary.totals.mutationScore.killedScore$%
+
+
+
+
$summary.totals.mutationScore.numberOfUniqueMutationsKilled$/$summary.totals.mutationScore.numberOfUniqueMutations$
+
+
+
Killed: $summary.totals.mutationScore.numberOfUniqueMutationsKilled$
+
Uncertain: $summary.totals.mutationScore.numberOfUniqueMutationsPossiblyDetected$
+
+ }$ 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 7de80926e..2ff783e20 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 @@ -15,6 +15,7 @@ Line Coverage Mutation Coverage Test Strength + Mutation Score @@ -23,6 +24,17 @@ $packageData.totals.lineCoverage$%
$packageData.totals.numberOfLinesCovered$/$packageData.totals.numberOfLines$
$packageData.totals.mutationCoverage$%
$packageData.totals.numberOfMutationsDetected$/$packageData.totals.numberOfMutations$
$packageData.totals.testStrength$%
$packageData.totals.numberOfMutationsDetected$/$packageData.totals.numberOfMutationsWithCoverage$
+ $packageData.totals.mutationScore.killedScore$% +
+
+
+
$packageData.totals.mutationScore.numberOfUniqueMutationsKilled$/$packageData.totals.mutationScore.numberOfUniqueMutations$
+
+
+
Killed: $packageData.totals.mutationScore.numberOfUniqueMutationsKilled$
+
Uncertain: $packageData.totals.mutationScore.numberOfUniqueMutationsPossiblyDetected$
+
+ @@ -36,6 +48,7 @@ Line Coverage Mutation Coverage Test Strength + Mutation Score @@ -45,6 +58,18 @@ $packageData.summaryData:{ summary |
$summary.totals.lineCoverage$%
$summary.totals.numberOfLinesCovered$/$summary.totals.numberOfLines$
$summary.totals.mutationCoverage$%
$summary.totals.numberOfMutationsDetected$/$summary.totals.numberOfMutations$
$summary.totals.testStrength$%
$summary.totals.numberOfMutationsDetected$/$summary.totals.numberOfMutationsWithCoverage$
+ +
$summary.totals.mutationScore.killedScore$%
+
+
+
+
$summary.totals.mutationScore.numberOfUniqueMutationsKilled$/$summary.totals.mutationScore.numberOfUniqueMutations$
+
+
+
Killed: $summary.totals.mutationScore.numberOfUniqueMutationsKilled$
+
Uncertain: $summary.totals.mutationScore.numberOfUniqueMutationsPossiblyDetected$
+
+ }$ diff --git a/pitest-html-report/src/main/resources/templates/mutation/style.css b/pitest-html-report/src/main/resources/templates/mutation/style.css index cd65bd3ab..2572a1da8 100644 --- a/pitest-html-report/src/main/resources/templates/mutation/style.css +++ b/pitest-html-report/src/main/resources/templates/mutation/style.css @@ -99,11 +99,21 @@ body{ position: relative; } +.coverage_possibly_detected { + display: block; + height: 100%; + background: #dde7ef; + position: absolute; + left: 0; + top: 0; +} .coverage_complete { - display: inline-block; + display: block; height: 100%; background: #DFD; - float: left; + position: absolute; + left: 0; + top: 0; } .coverage_legend { @@ -560,4 +570,29 @@ body{ .width-100 { width: 100%; +} + +.legend { + display: inline-block; + font-size: 0.8em; + vertical-align: middle; +} +.legend .killed, +.legend .uncertain { + background: none; +} +.legend .killed:before, +.legend .uncertain:before { + content: ""; + width: 20px; + display: inline-block; + border: 1px solid #aaa; + margin-right: 5px; + height: 10px; +} +.legend .killed:before { + background: #DFD; +} +.legend .uncertain:before { + background: #dde7ef; } \ No newline at end of file diff --git a/pitest-html-report/src/test/java/org/pitest/mutationtest/report/html/MutationTestSummaryDataTest.java b/pitest-html-report/src/test/java/org/pitest/mutationtest/report/html/MutationTestSummaryDataTest.java index 9fa1088af..252478fe9 100644 --- a/pitest-html-report/src/test/java/org/pitest/mutationtest/report/html/MutationTestSummaryDataTest.java +++ b/pitest-html-report/src/test/java/org/pitest/mutationtest/report/html/MutationTestSummaryDataTest.java @@ -1,24 +1,25 @@ package org.pitest.mutationtest.report.html; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.TreeSet; +import java.util.stream.Collectors; + import org.junit.Test; import org.mockito.Mockito; import org.pitest.classinfo.ClassInfo; import org.pitest.mutationtest.DetectionStatus; import org.pitest.mutationtest.MutationResult; import org.pitest.mutationtest.MutationStatusTestPair; +import org.pitest.mutationtest.engine.MutationDetails; +import org.pitest.mutationtest.engine.MutationIdentifier; import org.pitest.mutationtest.engine.gregor.MethodMutatorFactory; import org.pitest.mutationtest.engine.gregor.config.Mutator; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.TreeSet; -import java.util.stream.Collectors; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.when; - public class MutationTestSummaryDataTest { private MutationTestSummaryData testee; @@ -180,7 +181,11 @@ private MutationTestSummaryData buildSummaryDataWithMutationResults(final ClassI } private MutationResult aMutationResult(DetectionStatus status) { - return new MutationResult(null, new MutationStatusTestPair(1, status, "A test")); + return new MutationResult(aMutationDetails(), new MutationStatusTestPair(1, status, "A test")); + } + + private MutationDetails aMutationDetails() { + return new MutationDetails(new MutationIdentifier(null, Collections.emptyList(), null), null, "", 0, 0); } private MutationTestSummaryData buildSummaryDataMutators() {