Skip to content

Commit

Permalink
Add the test-strength metric for PIT results.
Browse files Browse the repository at this point in the history
  • Loading branch information
uhafner committed Jan 16, 2024
1 parent f926267 commit 68dbd2d
Show file tree
Hide file tree
Showing 6 changed files with 2,907 additions and 9 deletions.
1 change: 1 addition & 0 deletions src/main/java/edu/hm/hafner/coverage/Metric.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public enum Metric {

/** Additional metrics without children. */
MUTATION(new ValuesAggregator()),
TEST_STRENGTH(new ValuesAggregator()),
COMPLEXITY(new ValuesAggregator(), MetricTendency.SMALLER_IS_BETTER),
COMPLEXITY_MAXIMUM(new MethodMaxComplexityFinder(), MetricTendency.SMALLER_IS_BETTER),
COMPLEXITY_DENSITY(new DensityEvaluator(), MetricTendency.SMALLER_IS_BETTER),
Expand Down
20 changes: 13 additions & 7 deletions src/main/java/edu/hm/hafner/coverage/Mutation.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
* @author Melissa Bauer
*/
@SuppressWarnings("PMD.DataClass")
// TODO: intern some strings after deserialization to improve the memory footprint
public final class Mutation implements Serializable {
private static final long serialVersionUID = -7725185756332899065L;

Expand Down Expand Up @@ -251,27 +250,34 @@ public MutationBuilder withMutatedMethodSignature(final String mutatedMethodSign
* the tree string builder to create the file names
*/
public void buildAndAddToModule(final ModuleNode root, final TreeStringBuilder treeStringBuilder) {
String packageName = StringUtils.substringBeforeLast(mutatedClass, ".");
String className = StringUtils.substringAfterLast(mutatedClass, ".");
var packageName = StringUtils.substringBeforeLast(mutatedClass, ".");
var packageNode = root.findOrCreatePackageNode(packageName);
var relativePath = packageName.replace('.', '/') + '/' + sourceFile;
var fileNode = packageNode.findOrCreateFileNode(sourceFile, treeStringBuilder.intern(relativePath));
var className = StringUtils.substringAfterLast(mutatedClass, ".");
var classNode = fileNode.findOrCreateClassNode(className);
var methodNode = classNode.findMethod(mutatedMethod, mutatedMethodSignature)
.orElseGet(() -> classNode.createMethodNode(mutatedMethod, mutatedMethodSignature));

var coverage = methodNode.getValue(Metric.MUTATION)
updateMetricForMethod(Metric.MUTATION, methodNode);
if (status != MutationStatus.NO_COVERAGE) {
updateMetricForMethod(Metric.TEST_STRENGTH, methodNode);
}
fileNode.addMutation(build());
}

private void updateMetricForMethod(final Metric metric, final MethodNode methodNode) {
var existingCoverage = methodNode.getValue(metric)
.map(Coverage.class::cast)
.orElse(Coverage.nullObject(Metric.MUTATION));
var builder = new CoverageBuilder(coverage);
.orElse(Coverage.nullObject(metric));
var builder = new CoverageBuilder(existingCoverage);
if (isDetected) {
builder.incrementCovered();
}
else {
builder.incrementMissed();
}
methodNode.replaceValue(builder.build());
fileNode.addMutation(build());
}

public Mutation build() {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/edu/hm/hafner/coverage/MutationStatus.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public enum MutationStatus {
SURVIVED(COVERED),
NO_COVERAGE(MISSED),
NON_VIABLE(UNKNOWN),
TIMED_OUT(UNKNOWN),
TIMED_OUT(COVERED),
MEMORY_ERROR(UNKNOWN),
RUN_ERROR(UNKNOWN);

Expand Down
1 change: 1 addition & 0 deletions src/main/java/edu/hm/hafner/coverage/Value.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ public static Value valueOf(final String stringRepresentation) {
case INSTRUCTION:
case BRANCH:
case MUTATION:
case TEST_STRENGTH:
return Coverage.valueOf(metric, value);
case COMPLEXITY_DENSITY:
return new FractionValue(metric, Fraction.getFraction(value));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ void shouldConvertMutationsToTree() {
"Coverage");
assertThat(tree.getAll(METHOD)).hasSize(99);

assertThat(tree).hasOnlyMetrics(MODULE, PACKAGE, FILE, CLASS, METHOD, MUTATION, LINE, LOC);
assertThat(tree).hasOnlyMetrics(MODULE, PACKAGE, FILE, CLASS, METHOD, MUTATION, LINE, TEST_STRENGTH, LOC);

assertThat(tree.getValue(MUTATION)).isPresent().get().isInstanceOfSatisfying(Coverage.class,
coverage -> assertThat(coverage).hasCovered(222).hasTotal(246));
Expand All @@ -187,4 +187,55 @@ void shouldConvertMutationsToTree() {
.isNotEmpty().get()
.isInstanceOfSatisfying(Coverage.class, m -> assertThat(m).hasCovered(3).hasMissed(2)));
}

@Test
void shouldMapTimeouts() {
ModuleNode tree = readReport("mutations-with-timeout.xml");

assertThat(tree.getAll(MODULE)).hasSize(1);
assertThat(tree.getAll(PACKAGE)).hasSize(18).extracting(Node::getName)
.containsExactlyInAnyOrder("edu.hm.hafner.analysis",
"edu.hm.hafner.analysis.parser",
"edu.hm.hafner.analysis.parser.pvsstudio",
"edu.hm.hafner.analysis.parser.findbugs",
"edu.hm.hafner.analysis.parser.violations",
"edu.hm.hafner.analysis.parser.fxcop",
"edu.hm.hafner.analysis.parser.pmd",
"edu.hm.hafner.analysis.parser.ccm",
"edu.hm.hafner.analysis.parser.dry.dupfinder",
"edu.hm.hafner.analysis.parser.gendarme",
"edu.hm.hafner.analysis.registry",
"edu.hm.hafner.analysis.parser.checkstyle",
"edu.hm.hafner.analysis.parser.jcreport",
"edu.hm.hafner.analysis.util",
"edu.hm.hafner.analysis.parser.dry.cpd",
"edu.hm.hafner.analysis.parser.dry",
"edu.hm.hafner.analysis.parser.dry.simian",
"edu.hm.hafner.analysis.parser.pylint");
assertThat(tree.getMutations()).filteredOn(m -> m.getStatus().equals(MutationStatus.TIMED_OUT))
.hasSize(3)
.extracting(Mutation::isDetected)
.containsOnly(true);
assertThat(tree.getMutations()).filteredOn(m -> m.getStatus().equals(MutationStatus.KILLED))
.hasSize(2270)
.extracting(Mutation::isDetected)
.containsOnly(true);
assertThat(tree.getMutations()).filteredOn(m -> m.getStatus().equals(MutationStatus.NO_COVERAGE))
.hasSize(106)
.extracting(Mutation::isDetected)
.containsOnly(false);
assertThat(tree.getMutations())
.filteredOn(Mutation::isDetected)
.hasSize(2273);
assertThat(tree.getMutations())
.map(Mutation::getStatus)
.containsOnly(MutationStatus.KILLED,
MutationStatus.SURVIVED,
MutationStatus.TIMED_OUT,
MutationStatus.NO_COVERAGE);
assertThat(tree.getValue(MUTATION))
.contains(Coverage.valueOf("MUTATION: 2273/2836"));
assertThat(tree.getValue(TEST_STRENGTH))
.contains(Coverage.valueOf("TEST_STRENGTH: 2273/2730"));
}
}
Loading

0 comments on commit 68dbd2d

Please sign in to comment.