diff --git a/pom.xml b/pom.xml
index 9925ba6..7bfc9fc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -24,7 +24,7 @@
mutation-analysis-plugin
ch.devcon5.sonar
sonar-plugin
- 1.6
+ 1.7
${project.artifactId}
Sonar Plugin for integrating and visualizing mutation analysis results
@@ -79,6 +79,7 @@
Mutation Analysis Plugin
2015-2021
info@devcon5.ch
+ 7.9.5
@@ -166,6 +167,7 @@
mutationanalysis
ch.devcon5.sonar.plugins.mutationanalysis.MutationAnalysisPlugin
Mutation Analysis
+ ${sonarQubeMinVersion}
diff --git a/src/main/java/ch/devcon5/sonar/plugins/mutationanalysis/metrics/MutationMetrics.java b/src/main/java/ch/devcon5/sonar/plugins/mutationanalysis/metrics/MutationMetrics.java
index 5cdb829..74e61f4 100644
--- a/src/main/java/ch/devcon5/sonar/plugins/mutationanalysis/metrics/MutationMetrics.java
+++ b/src/main/java/ch/devcon5/sonar/plugins/mutationanalysis/metrics/MutationMetrics.java
@@ -118,6 +118,17 @@ private MutationMetrics(){}
.setDecimalScale(1)
.create();
+ public static final String MUTATIONS_TEST_STRENGTH_KEY = "dc5_mutationAnalysis_mutations_test_strength";
+ public static final Metric MUTATIONS_TEST_STRENGTH = new Metric.Builder(MUTATIONS_TEST_STRENGTH_KEY, "Test Strength", Metric.ValueType.PERCENT)
+ .setDirection(DIRECTION_BETTER)
+ .setDomain(MUTATION_ANALYSIS_DOMAIN)
+ .setQualitative(true)
+ .setDescription("Test strength percentage")
+ .setBestValue(100.)
+ .setWorstValue(0.)
+ .setDecimalScale(1)
+ .create();
+
public static final String MUTATIONS_DENSITY_KEY = "dc5_mutationAnalysis_mutations_density";
public static final Metric MUTATIONS_DENSITY=new Metric.Builder(MUTATIONS_DENSITY_KEY, "Mutation: Density", Metric.ValueType.PERCENT)
.setDirection(DIRECTION_WORST)
@@ -224,6 +235,7 @@ private MutationMetrics(){}
MUTATIONS_DATA,
MUTATIONS_TOTAL_PERCENT,
MUTATIONS_COVERAGE,
+ MUTATIONS_TEST_STRENGTH,
MUTATIONS_DENSITY,
MUTATIONS_ALIVE_PERCENT,
TEST_KILL_RATIO
diff --git a/src/main/java/ch/devcon5/sonar/plugins/mutationanalysis/metrics/MutationScoreComputer.java b/src/main/java/ch/devcon5/sonar/plugins/mutationanalysis/metrics/MutationScoreComputer.java
index 529a4ae..8371550 100644
--- a/src/main/java/ch/devcon5/sonar/plugins/mutationanalysis/metrics/MutationScoreComputer.java
+++ b/src/main/java/ch/devcon5/sonar/plugins/mutationanalysis/metrics/MutationScoreComputer.java
@@ -46,8 +46,8 @@ public MutationScoreComputer(final Configuration config) {
public MeasureComputerDefinition define(final MeasureComputerDefinitionContext defContext) {
return defContext.newDefinitionBuilder()
- .setInputMetrics(MutationMetrics.MUTATIONS_DETECTED.key(), MutationMetrics.MUTATIONS_TOTAL.key())
- .setOutputMetrics(MutationMetrics.MUTATIONS_COVERAGE.key())
+ .setInputMetrics(MutationMetrics.MUTATIONS_DETECTED.key(), MutationMetrics.MUTATIONS_TOTAL.key(), MutationMetrics.MUTATIONS_SURVIVED.key())
+ .setOutputMetrics(MutationMetrics.MUTATIONS_COVERAGE.key(), MutationMetrics.MUTATIONS_TEST_STRENGTH.key())
.build();
}
@@ -69,12 +69,30 @@ public void compute(final MeasureComputerContext context) {
final Double coverage = 100.0 * coveredElements / elements;
LOG.info("Computed Mutation Coverage of {}% for {}", coverage, context.getComponent());
context.addMeasure(MutationMetrics.MUTATIONS_COVERAGE.key(), coverage);
+
+ final Measure aliveMutantsMeasure = context.getMeasure(MutationMetrics.MUTATIONS_SURVIVED.key());
+ int aliveMutants = aliveMutantsMeasure != null ? aliveMutantsMeasure.getIntValue() : 0;
+
+ final Measure killedMutantsMeasure = context.getMeasure(MutationMetrics.MUTATIONS_DETECTED.key());
+ int killedMutants;
+ double testStrength = 0;
+ if (killedMutantsMeasure != null) {
+ killedMutants = killedMutantsMeasure.getIntValue();
+ int allMutantsQuantity = aliveMutants + killedMutants;
+ if (allMutantsQuantity != 0) {
+ testStrength = 100.0 * killedMutants / allMutantsQuantity;
+ }
+ }
+ LOG.info("Computed Test Strength of {}% for {}", testStrength, context.getComponent());
+ context.addMeasure(MutationMetrics.MUTATIONS_TEST_STRENGTH.key(), testStrength);
} else {
//modules with no mutants (0 total) are always 100% covered (0 of 0 is 100%, right?)
context.addMeasure(MutationMetrics.MUTATIONS_COVERAGE.key(), 100.0);
+ context.addMeasure(MutationMetrics.MUTATIONS_TEST_STRENGTH.key(), 100.0);
}
} else if(config.getBoolean(FORCE_MISSING_COVERAGE_TO_ZERO).orElse(Boolean.FALSE)){
context.addMeasure(MutationMetrics.MUTATIONS_COVERAGE.key(), 0.0);
+ context.addMeasure(MutationMetrics.MUTATIONS_TEST_STRENGTH.key(), 0.0);
}
}
}
diff --git a/src/test/java/ch/devcon5/sonar/plugins/mutationanalysis/metrics/MutationMetricsTest.java b/src/test/java/ch/devcon5/sonar/plugins/mutationanalysis/metrics/MutationMetricsTest.java
index 6d9417e..1367e69 100644
--- a/src/test/java/ch/devcon5/sonar/plugins/mutationanalysis/metrics/MutationMetricsTest.java
+++ b/src/test/java/ch/devcon5/sonar/plugins/mutationanalysis/metrics/MutationMetricsTest.java
@@ -34,6 +34,7 @@ public class MutationMetricsTest {
public void testMetricConstants() throws Exception {
assertNotNull(MutationMetrics.MUTATIONS_COVERAGE);
+ assertNotNull(MutationMetrics.MUTATIONS_TEST_STRENGTH);
assertNotNull(MutationMetrics.MUTATIONS_DATA);
assertNotNull(MutationMetrics.MUTATIONS_DETECTED);
assertNotNull(MutationMetrics.MUTATIONS_KILLED);
diff --git a/src/test/java/ch/devcon5/sonar/plugins/mutationanalysis/metrics/MutationScoreComputerTest.java b/src/test/java/ch/devcon5/sonar/plugins/mutationanalysis/metrics/MutationScoreComputerTest.java
index 51b532a..638a621 100644
--- a/src/test/java/ch/devcon5/sonar/plugins/mutationanalysis/metrics/MutationScoreComputerTest.java
+++ b/src/test/java/ch/devcon5/sonar/plugins/mutationanalysis/metrics/MutationScoreComputerTest.java
@@ -20,15 +20,6 @@
package ch.devcon5.sonar.plugins.mutationanalysis.metrics;
-import static ch.devcon5.sonar.plugins.mutationanalysis.metrics.MutationMetrics.MUTATIONS_COVERAGE_KEY;
-import static ch.devcon5.sonar.plugins.mutationanalysis.metrics.MutationMetrics.MUTATIONS_DETECTED_KEY;
-import static ch.devcon5.sonar.plugins.mutationanalysis.metrics.MutationMetrics.MUTATIONS_TOTAL_KEY;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Arrays;
-
import ch.devcon5.sonar.plugins.mutationanalysis.MutationAnalysisPlugin;
import ch.devcon5.sonar.plugins.mutationanalysis.testharness.MeasureComputerTestHarness;
import org.junit.Before;
@@ -37,6 +28,17 @@
import org.sonar.api.ce.measure.test.TestMeasureComputerContext;
import org.sonar.api.ce.measure.test.TestMeasureComputerDefinitionContext;
+import java.util.Arrays;
+import java.util.HashSet;
+
+import static ch.devcon5.sonar.plugins.mutationanalysis.metrics.MutationMetrics.MUTATIONS_COVERAGE_KEY;
+import static ch.devcon5.sonar.plugins.mutationanalysis.metrics.MutationMetrics.MUTATIONS_DETECTED_KEY;
+import static ch.devcon5.sonar.plugins.mutationanalysis.metrics.MutationMetrics.MUTATIONS_SURVIVED_KEY;
+import static ch.devcon5.sonar.plugins.mutationanalysis.metrics.MutationMetrics.MUTATIONS_TEST_STRENGTH_KEY;
+import static ch.devcon5.sonar.plugins.mutationanalysis.metrics.MutationMetrics.MUTATIONS_TOTAL_KEY;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
public class MutationScoreComputerTest {
private MutationScoreComputer computer;
@@ -58,8 +60,8 @@ public void define() {
final MeasureComputer.MeasureComputerDefinition def = computer.define(context);
- assertTrue(def.getInputMetrics().containsAll(Arrays.asList(MUTATIONS_DETECTED_KEY, MUTATIONS_TOTAL_KEY)));
- assertTrue(def.getOutputMetrics().containsAll(Arrays.asList(MUTATIONS_COVERAGE_KEY)));
+ assertEquals(def.getInputMetrics(), new HashSet<>(Arrays.asList(MUTATIONS_DETECTED_KEY, MUTATIONS_TOTAL_KEY, MUTATIONS_SURVIVED_KEY)));
+ assertEquals(def.getOutputMetrics(), new HashSet<>(Arrays.asList(MUTATIONS_COVERAGE_KEY, MUTATIONS_TEST_STRENGTH_KEY)));
}
@Test
@@ -120,6 +122,21 @@ public void compute_3of5Mutations_to_60percentCoverage() {
}
+ @Test
+ public void compute_1of5MutationsKilled_to_20percentTestStrength() {
+
+ final TestMeasureComputerContext measureContext = harness.createMeasureContextForSourceFile("compKey");
+
+ measureContext.addInputMeasure(MUTATIONS_TOTAL_KEY, 5);
+ measureContext.addInputMeasure(MUTATIONS_SURVIVED_KEY, 4);
+ measureContext.addInputMeasure(MUTATIONS_DETECTED_KEY, 1);
+
+ computer.compute(measureContext);
+
+ assertEquals(20.0, measureContext.getMeasure(MUTATIONS_TEST_STRENGTH_KEY).getDoubleValue(), 0.05);
+
+ }
+
@Test
public void compute_NoCoveredElements_0percentCoverage() {
@@ -130,6 +147,7 @@ public void compute_NoCoveredElements_0percentCoverage() {
computer.compute(measureContext);
assertEquals(0.0, measureContext.getMeasure(MUTATIONS_COVERAGE_KEY).getDoubleValue(), 0.05);
+ assertEquals(0.0, measureContext.getMeasure(MUTATIONS_TEST_STRENGTH_KEY).getDoubleValue(), 0.05);
}