Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,13 @@ private MutationMetrics(){}
.setDescription("Kills per Test")
.create();

public static final String TEST_TOTAL_EXECUTED_KEY = "dc5_mutationAnalysis_mutations_tests_executed";
public static final Metric<Serializable> TEST_TOTAL_EXECUTED=new Metric.Builder(TEST_TOTAL_EXECUTED_KEY, "Test: Executions", Metric.ValueType.INT)
.setDirection(DIRECTION_BETTER)
.setDomain(MUTATION_ANALYSIS_DOMAIN)
.setDescription("Number of Tests executed")
.create();

public static final String TEST_KILL_RATIO_KEY = "dc5_mutationAnalysis_mutations_testkill_ratio";
public static final Metric<Serializable> TEST_KILL_RATIO=new Metric.Builder(TEST_KILL_RATIO_KEY, "Test: Kill Ratio", Metric.ValueType.PERCENT)
.setDirection(DIRECTION_WORST)
Expand Down Expand Up @@ -208,6 +215,7 @@ private MutationMetrics(){}
MUTATIONS_MEMORY_ERROR,
MUTATIONS_SURVIVED,
TEST_KILLS,
TEST_TOTAL_EXECUTED,
UTILITY_GLOBAL_MUTATIONS,
UTILITY_GLOBAL_ALIVE
));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public class ResourceMutationMetrics {
private int mutationsTimedOut;
private int mutationsUnknown;
private int mutationsDetected;
private int numTestsRun;
private double mutationCoverage;
private final InputFile resource;

Expand Down Expand Up @@ -69,6 +70,7 @@ public void addMutant(final Mutant mutant) {
mutationsDetected++;
}
mutationsTotal++;
numTestsRun += mutant.getNumberOfTestsRun();
switch (mutant.getState()) {
case KILLED:
mutationsKilled++;
Expand Down Expand Up @@ -187,6 +189,16 @@ public double getMutationCoverage() {
return mutationCoverage;
}

/**
* Returns the total number of tests executed to kill the mutants (or not)
* @return
* a number >= 0
*/
public int getNumTestsRun() {

return numTestsRun;
}

/**
* The Sonar resource to which the mutant metrics are bound.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public class Mutant {

private final int lineNumber;
private final int index;
private final int numberOfTestsRun;
private final State state;
private final MutationOperator mutationOperator;
private final String sourceFile;
Expand Down Expand Up @@ -79,6 +80,7 @@ private Mutant(final Builder builder) {
this.mutationOperator = builder.mutationOperator;
this.mutatorSuffix = builder.mutatorSuffix;
this.index = builder.index;
this.numberOfTestsRun = builder.numberOfTestsRun;
this.killingTest = builder.state.isDetected() ? builder.killingTest : "";
this.description = builder.description;
this.toString = "Mutant [sourceFile="
Expand All @@ -95,6 +97,8 @@ private Mutant(final Builder builder) {
+ builder.state
+ ", mutationOperator="
+ builder.mutationOperator.getName()
+ ", numberOfTestsRun="
+ builder.numberOfTestsRun
+ ", killingTest="
+ this.killingTest
+ (this.description == null ? "" : ", description=" + this.description)
Expand All @@ -110,6 +114,7 @@ private Mutant(final Builder builder) {
this.mutatorSuffix.hashCode(),
this.sourceFile.hashCode(),
this.killingTest.hashCode(),
this.numberOfTestsRun,
this.description == null ? 0 : this.description.hashCode());

this.testDescriptor = new TestDescriptor(this.killingTest);
Expand Down Expand Up @@ -220,6 +225,16 @@ public String getKillingTest() {
return killingTest;
}

/**
*
* @return the number of tests that had to be executed to kill the mutant. The number is
* usually >= 1.
*/
public int getNumberOfTestsRun() {

return numberOfTestsRun;
}

/**
* Newer versions of Pit produce a description containing more details about what has been mutated.
*
Expand Down Expand Up @@ -279,6 +294,9 @@ private boolean equalsMutant(final Mutant other) { // NOSONAR
if (lineNumber != other.lineNumber) {
return false;
}
if (numberOfTestsRun != other.numberOfTestsRun) {
return false;
}
if (!methodDescription.equals(other.methodDescription)) {
return false;
}
Expand Down Expand Up @@ -436,6 +454,7 @@ public static class Builder {
private MutationOperator mutationOperator;
private String mutatorSuffix;
private int index;
private int numberOfTestsRun;
private String killingTest;
private String description;

Expand Down Expand Up @@ -594,6 +613,19 @@ public Builder killedBy(final String killingTest) {
return this;
}

/**
*
* @param numberOfTestsRun
* the number of tests that had to be executed before the mutant was killed. Pitest only executes tests that
* execute code actually cover a specific mutant to reduce the overall execution time.
* @return
* this builder
*/
public Builder numberOfTestsRun(final int numberOfTestsRun){
this.numberOfTestsRun = numberOfTestsRun;
return this;
}

/**
* Creates a new {@link ch.devcon5.sonar.plugins.mutationanalysis.model.Mutant} with all the parameters specified.
* As the {@link ch.devcon5.sonar.plugins.mutationanalysis.model.Mutant} requires all parameter to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public class PitestReportParser {
private static final Logger LOG = LoggerFactory.getLogger(PitestReportParser.class);

private static final String ATTR_STATUS = "status";
private static final String ATTR_NUMBER_OF_TESTS_RUN = "numberOfTestsRun";

private static final String ELEMENT_KILLING_TEST = "killingTest";

Expand Down Expand Up @@ -195,7 +196,9 @@ private void startElement(final XMLStreamReader reader, final Collection<Mutant>
*/
private Mutant parseMutant(final XMLStreamReader reader) throws XMLStreamException {

final Mutant.Builder builder = Mutant.builder().mutantStatus(getMutantStatus(reader));
final Mutant.Builder builder = Mutant.builder()
.mutantStatus(getMutantStatus(reader))
.numberOfTestsRun(getNumberOfTestsRun(reader));

while (true) {
int event = reader.next();
Expand Down Expand Up @@ -266,4 +269,21 @@ private String getMutantStatus(final XMLStreamReader reader) {

return reader.getAttributeValue(NAMESPACE_URI, ATTR_STATUS);
}

/**
* Reads the status of {@link Mutant} from the XMLStream.
*
* @param reader
* the {@link XMLStreamReader} whose cursor is at the start element position of a &lt;mutation&gt; element
*
* @return the mutant status as a string
*/
private int getNumberOfTestsRun(final XMLStreamReader reader) {

final String numberOfTestsRun = reader.getAttributeValue(NAMESPACE_URI, ATTR_NUMBER_OF_TESTS_RUN);
if(numberOfTestsRun != null){
return Integer.parseInt(numberOfTestsRun);
}
return 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,12 @@ private void saveResourceMetrics(final ResourceMutationMetrics resourceMetrics,
context.newMeasure().on(resource).forMetric(MutationMetrics.MUTATIONS_NO_COVERAGE).withValue(resourceMetrics.getMutationsNoCoverage()).save();
context.newMeasure().on(resource).forMetric(MutationMetrics.MUTATIONS_KILLED).withValue(resourceMetrics.getMutationsKilled()).save();
context.newMeasure().on(resource).forMetric(MutationMetrics.MUTATIONS_SURVIVED).withValue(resourceMetrics.getMutationsSurvived()).save();
context.newMeasure()
.on(resource)
.forMetric(MutationMetrics.MUTATIONS_ALIVE)
.withValue(resourceMetrics.getMutationsTotal() - resourceMetrics.getMutationsDetected())
.save();
context.newMeasure().on(resource).forMetric(MutationMetrics.MUTATIONS_ALIVE).withValue(resourceMetrics.getMutationsTotal() - resourceMetrics.getMutationsDetected()).save();
context.newMeasure().on(resource).forMetric(MutationMetrics.MUTATIONS_MEMORY_ERROR).withValue(resourceMetrics.getMutationsMemoryError()).save();
context.newMeasure().on(resource).forMetric(MutationMetrics.MUTATIONS_TIMED_OUT).withValue(resourceMetrics.getMutationsTimedOut()).save();
context.newMeasure().on(resource).forMetric(MutationMetrics.MUTATIONS_UNKNOWN).withValue(resourceMetrics.getMutationsUnknown()).save();
context.newMeasure().on(resource).forMetric(MutationMetrics.MUTATIONS_DETECTED).withValue(resourceMetrics.getMutationsDetected()).save();
context.newMeasure().on(resource).forMetric(MutationMetrics.TEST_TOTAL_EXECUTED).withValue(resourceMetrics.getNumTestsRun()).save();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public static Mutant newUndetectedMutant() {
.inLine(8)
.usingMutator(MutationOperators.find("INVERT_NEGS"))
.atIndex(10)
.numberOfTestsRun(123)
.killedBy("com.foo.bar.SomeClassKillingTest")
.build();
}
Expand All @@ -52,6 +53,7 @@ public static Mutant newDetectedMutant() {
.inLine(17)
.usingMutator(MutationOperators.find("INVERT_NEGS"))
.atIndex(5)
.numberOfTestsRun(256)
.killedBy("com.foo.bar.SomeClassKillingTest")
.build();
}
Expand All @@ -67,6 +69,7 @@ public static Mutant newSurvivedMutantWithSuffix(){
.usingMutator("org.pitest.mutationtest.engine.gregor.mutators.RemoveConditionalMutator_EQUAL_ELSE")
.atIndex(10)
.killedBy("com.foo.bar.SomeClassKillingTest")
.numberOfTestsRun(42)
.withDescription("removed conditional - replaced equality check with false")
.build();
}
Expand Down Expand Up @@ -146,6 +149,13 @@ public void testGetLineNumber() throws Exception {
assertEquals(8, newUndetectedMutant().getLineNumber());
}

@Test
public void testGetNumberOfTestsRun() throws Exception {

assertEquals(256, newDetectedMutant().getNumberOfTestsRun());
}


@Test
public void testGetMutator() throws Exception {

Expand Down Expand Up @@ -193,6 +203,7 @@ public void testToString() throws Exception {
+ "lineNumber=17, "
+ "state=KILLED, "
+ "mutationOperator=Invert Negs Mutator, "
+ "numberOfTestsRun=256, "
+ "killingTest=com.foo.bar.SomeClassKillingTest]",
newDetectedMutant().toString());

Expand All @@ -206,6 +217,7 @@ public void testToString_withDescription() throws Exception {
+ "lineNumber=8, "
+ "state=SURVIVED, "
+ "mutationOperator=Remove Conditional Mutator, "
+ "numberOfTestsRun=42, "
+ "killingTest=, "
+ "description=removed conditional - replaced equality check with false]",
newSurvivedMutantWithSuffix().toString());
Expand Down Expand Up @@ -249,6 +261,7 @@ public void testEquals_differentStatus_false() throws Exception {
.withMethodParameters(expected.getMethodDescription())
.usingMutator(expected.getMutationOperator())
.atIndex(expected.getIndex())
.numberOfTestsRun(expected.getNumberOfTestsRun())
.killedBy(expected.getKillingTest())
.build();

Expand All @@ -268,6 +281,7 @@ public void testEquals_differentSourceFile_false() throws Exception {
.withMethodParameters(expected.getMethodDescription())
.usingMutator(expected.getMutationOperator())
.atIndex(expected.getIndex())
.numberOfTestsRun(expected.getNumberOfTestsRun())
.killedBy(expected.getKillingTest())
.build();
assertNotEquals(expected, other);
Expand All @@ -286,6 +300,7 @@ public void testEquals_differentMutatedClass_false() throws Exception {
.withMethodParameters(expected.getMethodDescription())
.usingMutator(expected.getMutationOperator())
.atIndex(expected.getIndex())
.numberOfTestsRun(expected.getNumberOfTestsRun())
.killedBy(expected.getKillingTest())
.build();

Expand All @@ -305,6 +320,7 @@ public void testEquals_differentMutatedMethod_false() throws Exception {
.withMethodParameters(expected.getMethodDescription())
.usingMutator(expected.getMutationOperator())
.atIndex(expected.getIndex())
.numberOfTestsRun(expected.getNumberOfTestsRun())
.killedBy(expected.getKillingTest())
.build();
assertNotEquals(expected, other);
Expand All @@ -323,6 +339,7 @@ public void testEquals_differentMethodDescription_false() throws Exception {
.withMethodParameters("()")
.usingMutator(expected.getMutationOperator())
.atIndex(expected.getIndex())
.numberOfTestsRun(expected.getNumberOfTestsRun())
.killedBy(expected.getKillingTest())
.build();

Expand All @@ -342,6 +359,7 @@ public void testEquals_differentLineNumber_false() throws Exception {
.withMethodParameters(expected.getMethodDescription())
.usingMutator(expected.getMutationOperator())
.atIndex(expected.getIndex())
.numberOfTestsRun(expected.getNumberOfTestsRun())
.killedBy(expected.getKillingTest())
.build();

Expand All @@ -361,6 +379,7 @@ public void testEquals_differentMutator_false() throws Exception {
.withMethodParameters(expected.getMethodDescription())
.usingMutator(MutationOperators.find("ARGUMENT_PROPAGATION"))
.atIndex(expected.getIndex())
.numberOfTestsRun(expected.getNumberOfTestsRun())
.killedBy(expected.getKillingTest())
.build();

Expand All @@ -381,6 +400,27 @@ public void testEquals_differentSuffix_false() throws Exception {
.usingMutator("org.pitest.mutationtest.engine.gregor.mutators.RemoveConditionalMutator_EQUAL_IF")
.withDescription(expected.getDescription().get())
.atIndex(expected.getIndex())
.numberOfTestsRun(expected.getNumberOfTestsRun())
.killedBy(expected.getKillingTest())
.build();

assertNotEquals(expected, other);
}

@Test
public void testEquals_differentNumberOfTestsRun_false() throws Exception {

final Mutant expected = newDetectedMutant();
final Mutant other = Mutant.builder()
.mutantStatus(expected.getState())
.inSourceFile(expected.getSourceFile())
.inClass(expected.getMutatedClass())
.inMethod(expected.getMutatedMethod())
.inLine(expected.getLineNumber())
.withMethodParameters(expected.getMethodDescription())
.usingMutator(expected.getMutationOperator())
.atIndex(expected.getIndex())
.numberOfTestsRun(-1)
.killedBy(expected.getKillingTest())
.build();

Expand All @@ -400,6 +440,7 @@ public void testEquals_differentIndex_false() throws Exception {
.withMethodParameters(expected.getMethodDescription())
.usingMutator(expected.getMutationOperator())
.atIndex(127)
.numberOfTestsRun(expected.getNumberOfTestsRun())
.killedBy(expected.getKillingTest())
.build();

Expand All @@ -419,6 +460,7 @@ public void testEquals_differentKillingTest_false() throws Exception {
.withMethodParameters(expected.getMethodDescription())
.usingMutator(expected.getMutationOperator())
.atIndex(expected.getIndex())
.numberOfTestsRun(expected.getNumberOfTestsRun())
.killedBy("otherTest")
.build();

Expand All @@ -438,6 +480,7 @@ public void testEquals_differentDescription_false() throws Exception {
.withMethodParameters(expected.getMethodDescription())
.usingMutator(expected.getMutationOperator())
.atIndex(expected.getIndex())
.numberOfTestsRun(expected.getNumberOfTestsRun())
.killedBy(expected.getKillingTest())
.withDescription("other Description")
.build();
Expand Down Expand Up @@ -475,6 +518,7 @@ public void testHashCode_detected_reproducible() throws Exception {
refCode = prime * refCode + mutant.getMutatorSuffix().hashCode();
refCode = prime * refCode + mutant.getSourceFile().hashCode();
refCode = prime * refCode + mutant.getKillingTest().hashCode();
refCode = prime * refCode + mutant.getNumberOfTestsRun();
refCode = prime * refCode + mutant.getDescription().hashCode();

assertEquals(refCode, mutant.hashCode());
Expand All @@ -498,6 +542,7 @@ public void testHashCode_undetected_reproducible() throws Exception {
refCode = prime * refCode + mutant.getMutatorSuffix().hashCode();
refCode = prime * refCode + mutant.getSourceFile().hashCode();
refCode = prime * refCode + mutant.getKillingTest().hashCode();
refCode = prime * refCode + mutant.getNumberOfTestsRun();
refCode = prime * refCode + mutant.getDescription().hashCode();

assertEquals(refCode, mutant.hashCode());
Expand Down
Loading