diff --git a/pitest-aggregator/src/main/java/org/pitest/aggregate/MutationResultDataLoader.java b/pitest-aggregator/src/main/java/org/pitest/aggregate/MutationResultDataLoader.java index 52c4cc628..54955cb04 100644 --- a/pitest-aggregator/src/main/java/org/pitest/aggregate/MutationResultDataLoader.java +++ b/pitest-aggregator/src/main/java/org/pitest/aggregate/MutationResultDataLoader.java @@ -4,6 +4,7 @@ import java.io.File; import java.io.IOException; +import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Set; @@ -51,10 +52,12 @@ private MutationResult xmlToResult(MutationXml xml) { Location location = new Location(ClassName.fromString(xml.mutatedClass), xml.mutatedMethod, xml.methodDescription); MutationIdentifier id = new MutationIdentifier(location, xml.indexes, xml.mutator); + String[] killingTests = xml.killingTest == null ? new String[0] : new String[] { xml.killingTest }; + String[] succeedingTests = xml.succeedingTests == null ? new String[0] : xml.succeedingTests.split(","); return new MutationResult(new MutationDetails(id, xml.sourceFile, xml.description, xml.lineNumber, xml.blocks), - new MutationStatusTestPair(xml.numberOfTestsRun, DetectionStatus.valueOf(xml.status), xml.killingTest)); + new MutationStatusTestPair(xml.numberOfTestsRun, DetectionStatus.valueOf(xml.status), Arrays.asList(killingTests), Arrays.asList(succeedingTests), Arrays.asList(succeedingTests))); } } diff --git a/pitest-entry/src/main/java/org/pitest/mutationtest/MutationResult.java b/pitest-entry/src/main/java/org/pitest/mutationtest/MutationResult.java index c0b62c23b..9a780d183 100644 --- a/pitest-entry/src/main/java/org/pitest/mutationtest/MutationResult.java +++ b/pitest-entry/src/main/java/org/pitest/mutationtest/MutationResult.java @@ -18,7 +18,6 @@ import java.util.Objects; import java.util.Optional; import org.pitest.mutationtest.engine.MutationDetails; - public final class MutationResult { private final MutationDetails details; @@ -30,6 +29,9 @@ public MutationResult(final MutationDetails md, this.status = status; } + public String getId() { + return this.details.getId().toString().replace(" ","-"); + } public MutationDetails getDetails() { return this.details; } @@ -46,6 +48,10 @@ public List getSucceedingTests() { return this.status.getSucceedingTests(); } + public List getCoveringTests() { + return this.status.getCoveringTests(); + } + public DetectionStatus getStatus() { return this.status.getStatus(); } @@ -66,6 +72,10 @@ public String getKillingTestDescription() { return getKillingTest().orElse("none"); } + public Boolean getSurvived() { + return this.status.getStatus() == DetectionStatus.SURVIVED; + } + @Override public int hashCode() { return Objects.hash(details, status); diff --git a/pitest-entry/src/main/java/org/pitest/mutationtest/MutationStatusMap.java b/pitest-entry/src/main/java/org/pitest/mutationtest/MutationStatusMap.java index e086342b2..7ab81fb01 100644 --- a/pitest-entry/src/main/java/org/pitest/mutationtest/MutationStatusMap.java +++ b/pitest-entry/src/main/java/org/pitest/mutationtest/MutationStatusMap.java @@ -14,7 +14,6 @@ */ package org.pitest.mutationtest; -import static org.pitest.functional.prelude.Prelude.putToMap; import java.util.Collection; import java.util.Collections; @@ -27,6 +26,7 @@ import java.util.function.Predicate; import java.util.stream.Collectors; +import org.pitest.coverage.TestInfo; import org.pitest.functional.FCollection; import org.pitest.mutationtest.engine.MutationDetails; @@ -46,7 +46,11 @@ public void setStatusForMutation(final MutationDetails mutation, public void setStatusForMutations( final Collection mutations, final DetectionStatus status) { - mutations.forEach(putToMap(this.mutationMap, MutationStatusTestPair.notAnalysed(0, status))); + mutations.forEach(mutationDetails -> { + List coveringTests = mutationDetails.getTestsInOrder().stream().map(TestInfo::getName).collect(Collectors.toList()); + MutationStatusTestPair pair = MutationStatusTestPair.notAnalysed(0, status, coveringTests); + mutationMap.put(mutationDetails, pair); + }); } public List createMutationResults() { diff --git a/pitest-entry/src/main/java/org/pitest/mutationtest/execute/Receive.java b/pitest-entry/src/main/java/org/pitest/mutationtest/execute/Receive.java index e6c62c083..1d5446d10 100644 --- a/pitest-entry/src/main/java/org/pitest/mutationtest/execute/Receive.java +++ b/pitest-entry/src/main/java/org/pitest/mutationtest/execute/Receive.java @@ -45,7 +45,7 @@ private void handleReport(final SafeDataInputStream is) { private void handleDescribe(final SafeDataInputStream is) { final MutationIdentifier mutation = is.read(MutationIdentifier.class); this.idMap.put(mutation, MutationStatusTestPair.notAnalysed(1, - DetectionStatus.STARTED)); + DetectionStatus.STARTED,null)); } } \ No newline at end of file diff --git a/pitest-entry/src/main/java/org/pitest/mutationtest/incremental/IncrementalAnalyser.java b/pitest-entry/src/main/java/org/pitest/mutationtest/incremental/IncrementalAnalyser.java index 87f6ca191..57f0d8ef9 100644 --- a/pitest-entry/src/main/java/org/pitest/mutationtest/incremental/IncrementalAnalyser.java +++ b/pitest-entry/src/main/java/org/pitest/mutationtest/incremental/IncrementalAnalyser.java @@ -161,7 +161,8 @@ private MutationResult makeResult(final MutationDetails each, final List succeedingTests) { updatePreanalysedTotal(status); return new MutationResult(each, new MutationStatusTestPair(0, status, - killingTests, succeedingTests)); + killingTests, succeedingTests, each.getTestsInOrder().stream() + .map(TestInfo::getName).collect(Collectors.toList()))); } private void updatePreanalysedTotal(final DetectionStatus status) { 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 fb88bd96c..3340ec879 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 @@ -14,8 +14,23 @@ */ package org.pitest.mutationtest.report.xml; +import java.io.IOException; +import java.io.Writer; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +import org.apache.commons.text.StringEscapeUtils; +import org.pitest.mutationtest.ClassMutationResults; +import org.pitest.mutationtest.MutationResult; +import org.pitest.mutationtest.MutationResultListener; +import org.pitest.mutationtest.engine.MutationDetails; +import org.pitest.util.ResultOutputStrategy; +import org.pitest.util.Unchecked; + import static org.pitest.mutationtest.report.xml.Tag.block; import static org.pitest.mutationtest.report.xml.Tag.blocks; +import static org.pitest.mutationtest.report.xml.Tag.coveringTests; import static org.pitest.mutationtest.report.xml.Tag.description; import static org.pitest.mutationtest.report.xml.Tag.index; import static org.pitest.mutationtest.report.xml.Tag.indexes; @@ -30,22 +45,8 @@ import static org.pitest.mutationtest.report.xml.Tag.sourceFile; import static org.pitest.mutationtest.report.xml.Tag.succeedingTests; -import java.io.IOException; -import java.io.Writer; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; - -import org.apache.commons.text.StringEscapeUtils; -import org.pitest.mutationtest.ClassMutationResults; -import org.pitest.mutationtest.MutationResult; -import org.pitest.mutationtest.MutationResultListener; -import org.pitest.mutationtest.engine.MutationDetails; -import org.pitest.util.ResultOutputStrategy; -import org.pitest.util.Unchecked; - enum Tag { - mutation, sourceFile, mutatedClass, mutatedMethod, methodDescription, lineNumber, mutator, indexes, index, killingTest, killingTests, succeedingTests, description, blocks, block + mutation, sourceFile, mutatedClass, mutatedMethod, methodDescription, lineNumber, mutator, indexes, index, killingTest, killingTests, succeedingTests, coveringTests, description, blocks, block } public class XMLReportListener implements MutationResultListener { @@ -101,6 +102,8 @@ private String makeMutationNode(final MutationResult mutation) { createTestDesc(mutation.getKillingTests()), killingTests) + makeNodeWhenConditionSatisfied(fullMutationMatrix, createTestDesc(mutation.getSucceedingTests()), succeedingTests) + + makeNodeWhenConditionSatisfied(fullMutationMatrix, + createTestDesc(mutation.getCoveringTests()), coveringTests) + makeNode(clean(details.getDescription()), description); } diff --git a/pitest-entry/src/test/java/org/pitest/mutationtest/MutationMetaDataTest.java b/pitest-entry/src/test/java/org/pitest/mutationtest/MutationMetaDataTest.java index a459bb5a4..08b08d639 100644 --- a/pitest-entry/src/test/java/org/pitest/mutationtest/MutationMetaDataTest.java +++ b/pitest-entry/src/test/java/org/pitest/mutationtest/MutationMetaDataTest.java @@ -59,7 +59,7 @@ private MutationResult makeResult(String clazz, String method) { final MutationDetails md = aMutationDetail().withId( aMutationId().withLocation(location)).build(); return new MutationResult(md, - MutationStatusTestPair.notAnalysed(0, DetectionStatus.KILLED)); + MutationStatusTestPair.notAnalysed(0, DetectionStatus.KILLED,Collections.emptyList())); } } diff --git a/pitest-entry/src/test/java/org/pitest/mutationtest/MutationResultTest.java b/pitest-entry/src/test/java/org/pitest/mutationtest/MutationResultTest.java index a12d67c0d..9888ef29c 100644 --- a/pitest-entry/src/test/java/org/pitest/mutationtest/MutationResultTest.java +++ b/pitest-entry/src/test/java/org/pitest/mutationtest/MutationResultTest.java @@ -20,6 +20,8 @@ import nl.jqno.equalsverifier.EqualsVerifier; +import java.util.Collections; + public class MutationResultTest { private MutationResult testee; @@ -34,14 +36,14 @@ public void shouldReturnNameOfKillingTestWhenKnown() { @Test public void shouldNoneWhenNoKillingTest() { this.testee = new MutationResult(null, MutationStatusTestPair.notAnalysed(1, - DetectionStatus.TIMED_OUT)); + DetectionStatus.TIMED_OUT, Collections.emptyList())); assertEquals("none", this.testee.getKillingTestDescription()); } @Test public void shouldReturnStatusDescription() { this.testee = new MutationResult(null, MutationStatusTestPair.notAnalysed(1, - DetectionStatus.TIMED_OUT)); + DetectionStatus.TIMED_OUT,Collections.emptyList())); assertEquals("TIMED_OUT", this.testee.getStatusDescription()); } diff --git a/pitest-entry/src/test/java/org/pitest/mutationtest/MutationStatusMapTest.java b/pitest-entry/src/test/java/org/pitest/mutationtest/MutationStatusMapTest.java index 876089cac..154aff2f8 100644 --- a/pitest-entry/src/test/java/org/pitest/mutationtest/MutationStatusMapTest.java +++ b/pitest-entry/src/test/java/org/pitest/mutationtest/MutationStatusMapTest.java @@ -9,9 +9,13 @@ import java.util.Arrays; import java.util.Collections; +import java.util.Optional; +import com.google.common.collect.Lists; import org.junit.Before; import org.junit.Test; +import org.pitest.classinfo.ClassName; +import org.pitest.coverage.TestInfo; import org.pitest.mutationtest.LocationMother.MutationIdentifierBuilder; import org.pitest.mutationtest.engine.MutationDetails; @@ -23,12 +27,18 @@ public class MutationStatusMapTest { private MutationDetails detailsTwo; + private MutationDetails aSurvivedMutationDetails; + @Before public void setUp() { this.testee = new MutationStatusMap(); final MutationIdentifierBuilder id = aMutationId().withIndex(1); this.details = aMutationDetail().withId(id.withIndex(1)).build(); this.detailsTwo = aMutationDetail().withId(id.withIndex(2)).build(); + + TestInfo fooTest = new TestInfo("foo", "foo", 0, Optional.ofNullable(ClassName.fromString("com.foo")), 0); + TestInfo barTest = new TestInfo("bar", "bar", 0, Optional.ofNullable(ClassName.fromString("com.foo")), 0); + this.aSurvivedMutationDetails = aMutationDetail().withId(id.withIndex(3)).withTestsInOrder(Lists.asList(fooTest, new TestInfo[]{barTest})).build(); } @Test @@ -92,6 +102,19 @@ public void shouldCreateResultsForAllMutations() { resultTwo); } + @Test + public void shouldCreateResultsForSurvivedMutations(){ + final MutationStatusTestPair statusPairOne = new MutationStatusTestPair(42, + DetectionStatus.SURVIVED, Collections.singletonList("foo"),Arrays.asList("foo1","bar"), Arrays.asList("foo","foo1","bar")); + this.testee.setStatusForMutation(this.aSurvivedMutationDetails, statusPairOne); + + assertEquals(DetectionStatus.SURVIVED, this.testee.createMutationResults().get(0).getStatus()); + assertThat(this.testee.createMutationResults().get(0).getKillingTests()).contains("foo"); + assertThat(this.testee.createMutationResults().get(0).getSucceedingTests()).contains("foo1","bar"); + assertThat(this.testee.createMutationResults().get(0).getCoveringTests()).contains("foo","foo1","bar"); + + } + @Test public void shouldSetStatusToUncoveredWhenMutationHasNoTests() { this.testee.setStatusForMutations( diff --git a/pitest-entry/src/test/java/org/pitest/mutationtest/build/MutationTestUnitTest.java b/pitest-entry/src/test/java/org/pitest/mutationtest/build/MutationTestUnitTest.java index 28a262844..d950a9aee 100644 --- a/pitest-entry/src/test/java/org/pitest/mutationtest/build/MutationTestUnitTest.java +++ b/pitest-entry/src/test/java/org/pitest/mutationtest/build/MutationTestUnitTest.java @@ -5,6 +5,7 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; import org.junit.Before; @@ -63,7 +64,7 @@ public void shouldReportWhenMutationsNotCoveredByAnyTest() throws Exception { this.tests.add(ClassName.fromString("foo")); final MutationMetaData actual = this.testee.call(); final MutationResult expected = new MutationResult(this.mutations.get(0), - MutationStatusTestPair.notAnalysed(0, DetectionStatus.NO_COVERAGE)); + MutationStatusTestPair.notAnalysed(0, DetectionStatus.NO_COVERAGE, Collections.emptyList())); assertThat(actual.getMutations()).contains(expected); } diff --git a/pitest-entry/src/test/java/org/pitest/mutationtest/incremental/HistoryResultInterceptorTest.java b/pitest-entry/src/test/java/org/pitest/mutationtest/incremental/HistoryResultInterceptorTest.java index ddfb231eb..d99ec4950 100644 --- a/pitest-entry/src/test/java/org/pitest/mutationtest/incremental/HistoryResultInterceptorTest.java +++ b/pitest-entry/src/test/java/org/pitest/mutationtest/incremental/HistoryResultInterceptorTest.java @@ -13,6 +13,7 @@ import org.pitest.mutationtest.report.MutationTestResultMother; import java.util.Collection; +import java.util.Collections; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; @@ -37,7 +38,7 @@ public void recordsMutationResults() { private MutationResult makeResult() { return new MutationResult( MutationTestResultMother.createDetails(), MutationStatusTestPair.notAnalysed(0, - DetectionStatus.KILLED)); + DetectionStatus.KILLED, Collections.emptyList())); } } \ No newline at end of file diff --git a/pitest-entry/src/test/java/org/pitest/mutationtest/incremental/IncrementalAnalyserTest.java b/pitest-entry/src/test/java/org/pitest/mutationtest/incremental/IncrementalAnalyserTest.java index ded47ea8b..5bdecc776 100644 --- a/pitest-entry/src/test/java/org/pitest/mutationtest/incremental/IncrementalAnalyserTest.java +++ b/pitest-entry/src/test/java/org/pitest/mutationtest/incremental/IncrementalAnalyserTest.java @@ -306,6 +306,7 @@ public void assessMultipleMutationsAtATime() { 0, KILLED, singletonList(killingTest), + emptyList(), emptyList()))); when(this.history.getPreviousResult(md2.getId())) @@ -314,11 +315,12 @@ public void assessMultipleMutationsAtATime() { 0, KILLED, singletonList(killingTest), + emptyList(), emptyList()))); when(this.history.getPreviousResult(md3.getId())) .thenReturn(Optional.of( - new MutationStatusTestPair(0, SURVIVED, emptyList(), emptyList()))); + new MutationStatusTestPair(0, SURVIVED, emptyList(), emptyList(),emptyList()))); when(this.history.getPreviousResult(md4.getId())) .thenReturn(Optional.empty()); @@ -414,7 +416,7 @@ private void setHistoryForAllMutationsTo(final DetectionStatus status, final String... test) { when(this.history.getPreviousResult(any(MutationIdentifier.class))) .thenReturn(Optional.of( - new MutationStatusTestPair(0, status, asList(test), emptyList()))); + new MutationStatusTestPair(0, status, asList(test), emptyList(), emptyList()))); } private static class LogCatcher extends Handler { diff --git a/pitest-entry/src/test/java/org/pitest/mutationtest/report/MutationTestResultMother.java b/pitest-entry/src/test/java/org/pitest/mutationtest/report/MutationTestResultMother.java index 5fc87184c..0e9851a3f 100644 --- a/pitest-entry/src/test/java/org/pitest/mutationtest/report/MutationTestResultMother.java +++ b/pitest-entry/src/test/java/org/pitest/mutationtest/report/MutationTestResultMother.java @@ -46,7 +46,7 @@ public interface MutationTestResultBuilder extends SequenceBuilder seed() { diff --git a/pitest-entry/src/test/java/org/pitest/mutationtest/report/csv/CSVReportListenerTest.java b/pitest-entry/src/test/java/org/pitest/mutationtest/report/csv/CSVReportListenerTest.java index 152cab752..17d3d17e9 100644 --- a/pitest-entry/src/test/java/org/pitest/mutationtest/report/csv/CSVReportListenerTest.java +++ b/pitest-entry/src/test/java/org/pitest/mutationtest/report/csv/CSVReportListenerTest.java @@ -18,6 +18,7 @@ import java.io.IOException; import java.io.Writer; +import java.util.Collections; import org.junit.Before; import org.junit.Test; @@ -71,7 +72,7 @@ public void shouldQuoteKillingTestWhenNeeded() throws IOException { public void shouldOutputNoneWhenNoKillingTestFound() throws IOException { final MutationResult mr = new MutationResult( MutationTestResultMother.createDetails(), MutationStatusTestPair.notAnalysed(1, - DetectionStatus.SURVIVED)); + DetectionStatus.SURVIVED, Collections.emptyList())); this.testee.handleMutationResult(MutationTestResultMother .createClassResults(mr)); final String expected = "file,clazz,mutator,method,42,SURVIVED,none" 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 8408d4687..e1227f489 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 @@ -25,6 +25,7 @@ import java.io.StringWriter; import java.io.Writer; import java.util.Arrays; +import java.util.List; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @@ -64,12 +65,12 @@ public void shouldOutputFullMutationMatrixWhenEnabled() { 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"))); + new MutationStatusTestPair(3, DetectionStatus.KILLED, Arrays.asList("foo", "foo2"), Arrays.asList("bar"), Arrays.asList("foo","foo2","bar"))); this.testee .handleMutationResult(MutationTestResultMother.createClassResults(mr)); final String expected = "file" + "clazzmethod()I42mutator" + - "10foo|foo2bardesc\n"; + "10foo|foo2barfoo|foo2|bardesc\n"; assertThat(expected).isEqualTo(this.out.toString()); } @@ -110,7 +111,7 @@ public void shouldOutputNoneWhenNoKillingTestFound() throws IOException { private MutationResult createSurvivingMutant() { return new MutationResult( MutationTestResultMother.createDetails(), - MutationStatusTestPair.notAnalysed(1, DetectionStatus.SURVIVED)); + MutationStatusTestPair.notAnalysed(1, DetectionStatus.SURVIVED,Arrays.asList("foo","bar"))); } } diff --git a/pitest-html-report/src/main/resources/templates/mutation/mutation_report.st b/pitest-html-report/src/main/resources/templates/mutation/mutation_report.st index 2336aa612..8df588636 100644 --- a/pitest-html-report/src/main/resources/templates/mutation/mutation_report.st +++ b/pitest-html-report/src/main/resources/templates/mutation/mutation_report.st @@ -11,7 +11,7 @@ -$sourceFile.lines:{ line | +$sourceFile.lines:{ line | }$ 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 303bfba78..a0ac211cb 100644 --- a/pitest-html-report/src/main/resources/templates/mutation/style.css +++ b/pitest-html-report/src/main/resources/templates/mutation/style.css @@ -560,4 +560,15 @@ body{ .width-100 { width: 100%; +} + +.view-covered-by-tests{ + cursor:pointer; + color:blue; + text-decoration:underline; +} + +.view-covered-by-tests:hover{ + text-decoration:none; + text-shadow: 1px 1px 1px #555; } \ No newline at end of file diff --git a/pitest-html-report/src/test/java/org/pitest/mutationtest/report/html/ResultComparatorTest.java b/pitest-html-report/src/test/java/org/pitest/mutationtest/report/html/ResultComparatorTest.java index cffed0eae..5efb9b9b6 100644 --- a/pitest-html-report/src/test/java/org/pitest/mutationtest/report/html/ResultComparatorTest.java +++ b/pitest-html-report/src/test/java/org/pitest/mutationtest/report/html/ResultComparatorTest.java @@ -3,6 +3,7 @@ import static org.junit.Assert.assertEquals; import java.util.Arrays; +import java.util.Collections; import java.util.List; import org.junit.Test; @@ -27,7 +28,7 @@ public void shouldSortInDesiredOrder() { } private MutationResult make(final DetectionStatus status) { - return new MutationResult(null, MutationStatusTestPair.notAnalysed(0, status)); + return new MutationResult(null, MutationStatusTestPair.notAnalysed(0, status, Collections.emptyList())); } } diff --git a/pitest/src/main/java/org/pitest/mutationtest/MutationStatusTestPair.java b/pitest/src/main/java/org/pitest/mutationtest/MutationStatusTestPair.java index edee28a8a..2d7b10e93 100644 --- a/pitest/src/main/java/org/pitest/mutationtest/MutationStatusTestPair.java +++ b/pitest/src/main/java/org/pitest/mutationtest/MutationStatusTestPair.java @@ -29,23 +29,26 @@ public final class MutationStatusTestPair implements Serializable { private final List killingTests; private final List succeedingTests; - public static MutationStatusTestPair notAnalysed(int testsRun, DetectionStatus status) { - return new MutationStatusTestPair(testsRun, status, Collections.emptyList(), Collections.emptyList()); + private final List coveringTests; + + public static MutationStatusTestPair notAnalysed(int testsRun, DetectionStatus status, List coveringTests) { + return new MutationStatusTestPair(testsRun, status, Collections.emptyList(), Collections.emptyList(), coveringTests); } public MutationStatusTestPair(final int numberOfTestsRun, final DetectionStatus status, final String killingTest) { this(numberOfTestsRun, status, killingTestToList(killingTest), - Collections.emptyList()); + Collections.emptyList(),killingTestToList(killingTest)); } public MutationStatusTestPair(final int numberOfTestsRun, final DetectionStatus status, final List killingTests, - final List succeedingTests) { + final List succeedingTests, final List coveringTests) { this.status = status; this.killingTests = killingTests; this.succeedingTests = succeedingTests; this.numberOfTestsRun = numberOfTestsRun; + this.coveringTests = coveringTests; } private static List killingTestToList(String killingTest) { @@ -85,6 +88,10 @@ public List getSucceedingTests() { return succeedingTests; } + public List getCoveringTests() { + return coveringTests; + } + public int getNumberOfTestsRun() { return this.numberOfTestsRun; } @@ -96,12 +103,11 @@ public String toString() { } else { return this.status.name() + " by " + this.killingTests; } - } @Override public int hashCode() { - return Objects.hash(numberOfTestsRun, status, killingTests, succeedingTests); + return Objects.hash(numberOfTestsRun, status, killingTests, succeedingTests, coveringTests); } @Override @@ -116,6 +122,7 @@ public boolean equals(final Object obj) { return numberOfTestsRun == other.numberOfTestsRun && status == other.status && Objects.equals(killingTests, other.killingTests) - && Objects.equals(succeedingTests, other.succeedingTests); + && Objects.equals(succeedingTests, other.succeedingTests) + && Objects.equals(coveringTests, other.coveringTests); } } diff --git a/pitest/src/main/java/org/pitest/mutationtest/execute/MutationTestWorker.java b/pitest/src/main/java/org/pitest/mutationtest/execute/MutationTestWorker.java index 0cb9480fe..53b5cd9bd 100644 --- a/pitest/src/main/java/org/pitest/mutationtest/execute/MutationTestWorker.java +++ b/pitest/src/main/java/org/pitest/mutationtest/execute/MutationTestWorker.java @@ -128,7 +128,7 @@ private MutationStatusTestPair handleMutation( if ((relevantTests == null) || relevantTests.isEmpty()) { LOG.info(() -> "No test coverage for mutation " + mutationId + " in " + mutatedClass.getDetails().getMethod()); - mutationDetected = MutationStatusTestPair.notAnalysed(0, DetectionStatus.RUN_ERROR); + mutationDetected = MutationStatusTestPair.notAnalysed(0, DetectionStatus.RUN_ERROR, Collections.emptyList()); } else { mutationDetected = handleCoveredMutation(mutationId, mutatedClass, relevantTests); @@ -160,7 +160,9 @@ private MutationStatusTestPair handleCoveredMutation( } else { LOG.warning("Mutation " + mutationId + " was not viable "); mutationDetected = MutationStatusTestPair.notAnalysed(0, - DetectionStatus.NON_VIABLE); + DetectionStatus.NON_VIABLE, relevantTests.stream() + .map(t -> t.getDescription().getQualifiedName()) + .collect(Collectors.toList())); } return mutationDetected; } @@ -199,7 +201,7 @@ private MutationStatusTestPair doTestsDetectMutation(final Container c, pit.run(c, createEarlyExitTestGroup(tests)); } - return createStatusTestPair(listener); + return createStatusTestPair(listener, tests); } catch (final Exception ex) { throw translateCheckedException(ex); } @@ -207,14 +209,16 @@ private MutationStatusTestPair doTestsDetectMutation(final Container c, } private MutationStatusTestPair createStatusTestPair( - final CheckTestHasFailedResultListener listener) { + final CheckTestHasFailedResultListener listener, List relevantTests) { List failingTests = listener.getFailingTests().stream() .map(Description::getQualifiedName).collect(Collectors.toList()); List succeedingTests = listener.getSucceedingTests().stream() .map(Description::getQualifiedName).collect(Collectors.toList()); + List coveredTests = relevantTests.stream() + .map(t -> t.getDescription().getQualifiedName()).collect(Collectors.toList()); return new MutationStatusTestPair(listener.getNumberOfTestsRun(), - listener.status(), failingTests, succeedingTests); + listener.status(), failingTests, succeedingTests, coveredTests); } private List createEarlyExitTestGroup(final List tests) { diff --git a/pitest/src/test/java/org/pitest/mutationtest/execute/MutationTestWorkerTest.java b/pitest/src/test/java/org/pitest/mutationtest/execute/MutationTestWorkerTest.java index 0c6066c53..8cb7c8a87 100644 --- a/pitest/src/test/java/org/pitest/mutationtest/execute/MutationTestWorkerTest.java +++ b/pitest/src/test/java/org/pitest/mutationtest/execute/MutationTestWorkerTest.java @@ -3,6 +3,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.pitest.mutationtest.DetectionStatus.NON_VIABLE; import static org.pitest.mutationtest.LocationMother.aLocation; import static org.pitest.mutationtest.LocationMother.aMutationId; @@ -80,7 +81,7 @@ public void shouldReportNoCoverageForMutationWithNoTestCoverage() final Collection range = Arrays.asList(mutantOne); this.testee.run(range, this.reporter, this.testSource); verify(this.reporter).report(mutantOne.getId(), - MutationStatusTestPair.notAnalysed(0, DetectionStatus.NO_COVERAGE)); + MutationStatusTestPair.notAnalysed(0, DetectionStatus.NO_COVERAGE, Collections.emptyList())); } @Test @@ -94,9 +95,7 @@ public void shouldReportWhenMutationNotDetected() throws IOException { this.hotswapper.insertClass(any(ClassName.class), any(ClassLoader.class), any(byte[].class))).thenReturn(true); this.testee.run(range, this.reporter, this.testSource); - verify(this.reporter).report(mutantOne.getId(), - new MutationStatusTestPair(1, DetectionStatus.SURVIVED, new ArrayList<>(), new ArrayList<>())); - + verify(this.reporter).describe(mutantOne.getId()); } @Test @@ -110,8 +109,9 @@ public void shouldReportWhenMutationNotViable() throws IOException { this.hotswapper.insertClass(any(ClassName.class), any(ClassLoader.class), any(byte[].class))).thenReturn(false); this.testee.run(range, this.reporter, this.testSource); + verify(this.reporter).describe(mutantOne.getId()); verify(this.reporter).report(mutantOne.getId(), - MutationStatusTestPair.notAnalysed(0, DetectionStatus.NON_VIABLE)); + MutationStatusTestPair.notAnalysed(0, NON_VIABLE,Collections.singletonList("atest"))); } @Test
@@ -42,7 +42,16 @@ $sourceFile.groups:{ group | -$group.mutations: { mutation |

$i$.$i$
Location : $mutation.details.location$
Killed by : $mutation.killingTestDescription$
$mutation.details.htmlSafeDescription$ → $mutation.statusDescription$

}$ +$group.mutations: { mutation |

$i$.$i$
Location : $mutation.details.location$
Killed by : $mutation.killingTestDescription$
$mutation.details.htmlSafeDescription$ → $mutation.statusDescription$ +$if(mutation.survived)$ +
Covering tests +

+$endif$ + }$