aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorLéo Geoffroy <leo.geoffroy@sonarsource.com>2024-08-09 15:20:44 +0200
committersonartech <sonartech@sonarsource.com>2024-08-26 20:03:05 +0000
commitf47e4cc9197bc07818510b16f3998ae1da9e8b2a (patch)
tree6b62d698038a709f1e1cdf9acbf98d6447706154 /server
parent305b3d5937ece0b9aeaaa931fc0d9a4c1e6ba52b (diff)
downloadsonarqube-f47e4cc9197bc07818510b16f3998ae1da9e8b2a.tar.gz
sonarqube-f47e4cc9197bc07818510b16f3998ae1da9e8b2a.zip
SONAR-22727 Add new software qualities maintainability measures
Diffstat (limited to 'server')
-rw-r--r--server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/MaintainabilityMeasuresVisitor.java46
-rw-r--r--server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewMaintainabilityMeasuresVisitor.java54
-rw-r--r--server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/MaintainabilityMeasuresVisitorTest.java142
-rw-r--r--server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewMaintainabilityMeasuresVisitorTest.java307
-rw-r--r--server/sonar-server-common/src/main/java/org/sonar/server/measure/DebtRatingGrid.java11
-rw-r--r--server/sonar-server-common/src/test/java/org/sonar/server/measure/DebtRatingGridTest.java15
6 files changed, 392 insertions, 183 deletions
diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/MaintainabilityMeasuresVisitor.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/MaintainabilityMeasuresVisitor.java
index 8301ead2685..ec9221056c1 100644
--- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/MaintainabilityMeasuresVisitor.java
+++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/MaintainabilityMeasuresVisitor.java
@@ -30,6 +30,7 @@ import org.sonar.ce.task.projectanalysis.measure.RatingMeasures;
import org.sonar.ce.task.projectanalysis.metric.Metric;
import org.sonar.ce.task.projectanalysis.metric.MetricRepository;
import org.sonar.server.measure.Rating;
+import org.sonar.server.metric.SoftwareQualitiesMetrics;
import static org.sonar.api.measures.CoreMetrics.DEVELOPMENT_COST_KEY;
import static org.sonar.api.measures.CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY;
@@ -38,6 +39,10 @@ import static org.sonar.api.measures.CoreMetrics.SQALE_DEBT_RATIO_KEY;
import static org.sonar.api.measures.CoreMetrics.SQALE_RATING_KEY;
import static org.sonar.api.measures.CoreMetrics.TECHNICAL_DEBT_KEY;
import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilder;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.EFFORT_TO_REACH_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_A_KEY;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO_KEY;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT_KEY;
/**
* Compute measures related to maintainability for projects and descendants :
@@ -45,6 +50,9 @@ import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilde
* {@link CoreMetrics#SQALE_DEBT_RATIO_KEY}
* {@link CoreMetrics#SQALE_RATING_KEY}
* {@link CoreMetrics#EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY}
+ * {@link SoftwareQualitiesMetrics#SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO_KEY}
+ * {@link SoftwareQualitiesMetrics#SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY}
+ * {@link SoftwareQualitiesMetrics#EFFORT_TO_REACH_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_A_KEY}
*/
public class MaintainabilityMeasuresVisitor extends PathAwareVisitorAdapter<MaintainabilityMeasuresVisitor.Counter> {
private final MeasureRepository measureRepository;
@@ -53,11 +61,18 @@ public class MaintainabilityMeasuresVisitor extends PathAwareVisitorAdapter<Main
private final Metric nclocMetric;
private final Metric developmentCostMetric;
+ // Maintainability metrics based on RuleType
private final Metric maintainabilityRemediationEffortMetric;
private final Metric debtRatioMetric;
private final Metric maintainabilityRatingMetric;
private final Metric effortToMaintainabilityRatingAMetric;
+ // Maintainability metrics based on Software Quality
+ private final Metric softwareQualityMaintainabilityRemediationEffortMetric;
+ private final Metric softwareQualityDebtRatioMetric;
+ private final Metric softwareQualityEffortToMaintainabilityRatingAMetric;
+ private final Metric softwareQualityMaintainabilityRatingMetric;
+
public MaintainabilityMeasuresVisitor(MetricRepository metricRepository, MeasureRepository measureRepository, RatingSettings ratingSettings) {
super(CrawlerDepthLimit.FILE, Order.POST_ORDER, CounterFactory.INSTANCE);
this.measureRepository = measureRepository;
@@ -66,12 +81,18 @@ public class MaintainabilityMeasuresVisitor extends PathAwareVisitorAdapter<Main
// Input metrics
this.nclocMetric = metricRepository.getByKey(NCLOC_KEY);
this.maintainabilityRemediationEffortMetric = metricRepository.getByKey(TECHNICAL_DEBT_KEY);
+ this.softwareQualityMaintainabilityRemediationEffortMetric = metricRepository.getByKey(SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT_KEY);
// Output metrics
this.developmentCostMetric = metricRepository.getByKey(DEVELOPMENT_COST_KEY);
+
this.debtRatioMetric = metricRepository.getByKey(SQALE_DEBT_RATIO_KEY);
this.maintainabilityRatingMetric = metricRepository.getByKey(SQALE_RATING_KEY);
this.effortToMaintainabilityRatingAMetric = metricRepository.getByKey(EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY);
+
+ this.softwareQualityDebtRatioMetric = metricRepository.getByKey(SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO_KEY);
+ this.softwareQualityMaintainabilityRatingMetric = metricRepository.getByKey(SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY);
+ this.softwareQualityEffortToMaintainabilityRatingAMetric = metricRepository.getByKey(EFFORT_TO_REACH_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_A_KEY);
}
@Override
@@ -99,16 +120,21 @@ public class MaintainabilityMeasuresVisitor extends PathAwareVisitorAdapter<Main
private void computeAndSaveMeasures(Component component, Path<Counter> path) {
addDevelopmentCostMeasure(component, path.current());
- double density = computeDensity(component, path.current());
- addDebtRatioMeasure(component, density);
+ double density = computeDensity(maintainabilityRemediationEffortMetric, component, path.current());
+ addDebtRatioMeasure(debtRatioMetric, component, density);
addMaintainabilityRatingMeasure(component, density);
- addEffortToMaintainabilityRatingAMeasure(component, path);
+ addEffortToMaintainabilityRatingAMeasure(maintainabilityRemediationEffortMetric, effortToMaintainabilityRatingAMetric, component, path);
+
+ double densityBasedOnSoftwareQuality = computeDensity(softwareQualityMaintainabilityRemediationEffortMetric, component, path.current());
+ addDebtRatioMeasure(softwareQualityDebtRatioMetric, component, densityBasedOnSoftwareQuality);
+ addSoftwareQualityMaintainabilityRatingMeasure(component, densityBasedOnSoftwareQuality);
+ addEffortToMaintainabilityRatingAMeasure(softwareQualityMaintainabilityRemediationEffortMetric, softwareQualityEffortToMaintainabilityRatingAMetric, component, path);
addToParent(path);
}
- private double computeDensity(Component component, Counter developmentCost) {
- Optional<Measure> measure = measureRepository.getRawMeasure(component, maintainabilityRemediationEffortMetric);
+ private double computeDensity(Metric remediationEffortMetric, Component component, Counter developmentCost) {
+ Optional<Measure> measure = measureRepository.getRawMeasure(component, remediationEffortMetric);
double maintainabilityRemediationEffort = measure.isPresent() ? measure.get().getLongValue() : 0L;
if (Double.doubleToRawLongBits(developmentCost.devCosts) != 0L) {
return maintainabilityRemediationEffort / developmentCost.devCosts;
@@ -121,7 +147,7 @@ public class MaintainabilityMeasuresVisitor extends PathAwareVisitorAdapter<Main
measureRepository.add(component, developmentCostMetric, newMeasureBuilder().create(Long.toString(developmentCost.devCosts)));
}
- private void addDebtRatioMeasure(Component component, double density) {
+ private void addDebtRatioMeasure(Metric debtRatioMetric, Component component, double density) {
measureRepository.add(component, debtRatioMetric, newMeasureBuilder().create(100.0 * density, debtRatioMetric.getDecimalScale()));
}
@@ -130,7 +156,13 @@ public class MaintainabilityMeasuresVisitor extends PathAwareVisitorAdapter<Main
measureRepository.add(component, maintainabilityRatingMetric, RatingMeasures.get(rating));
}
- private void addEffortToMaintainabilityRatingAMeasure(Component component, Path<Counter> path) {
+ private void addSoftwareQualityMaintainabilityRatingMeasure(Component component, double density) {
+ Rating rating = ratingSettings.getDebtRatingGrid().getAToDRatingForDensity(density);
+ measureRepository.add(component, softwareQualityMaintainabilityRatingMetric, RatingMeasures.get(rating));
+ }
+
+ private void addEffortToMaintainabilityRatingAMeasure(Metric maintainabilityRemediationEffortMetric, Metric effortToMaintainabilityRatingAMetric,
+ Component component, Path<Counter> path) {
long developmentCostValue = path.current().devCosts;
Optional<Measure> effortMeasure = measureRepository.getRawMeasure(component, maintainabilityRemediationEffortMetric);
long effort = effortMeasure.isPresent() ? effortMeasure.get().getLongValue() : 0L;
diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewMaintainabilityMeasuresVisitor.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewMaintainabilityMeasuresVisitor.java
index 7223d35ff01..0a59cbd50c1 100644
--- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewMaintainabilityMeasuresVisitor.java
+++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewMaintainabilityMeasuresVisitor.java
@@ -36,6 +36,7 @@ import org.sonar.ce.task.projectanalysis.measure.MeasureRepository;
import org.sonar.ce.task.projectanalysis.metric.Metric;
import org.sonar.ce.task.projectanalysis.metric.MetricRepository;
import org.sonar.ce.task.projectanalysis.source.NewLinesRepository;
+import org.sonar.server.metric.SoftwareQualitiesMetrics;
import static org.sonar.api.measures.CoreMetrics.NCLOC_DATA_KEY;
import static org.sonar.api.measures.CoreMetrics.NEW_DEVELOPMENT_COST_KEY;
@@ -45,6 +46,8 @@ import static org.sonar.api.measures.CoreMetrics.NEW_TECHNICAL_DEBT_KEY;
import static org.sonar.api.utils.KeyValueFormat.newIntegerConverter;
import static org.sonar.ce.task.projectanalysis.component.ComponentVisitor.Order.POST_ORDER;
import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilder;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO_KEY;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT_KEY;
/**
* This visitor depends on {@link IntegrateIssuesVisitor} for the computation of
@@ -52,6 +55,8 @@ import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilde
* Compute following measure :
* {@link CoreMetrics#NEW_SQALE_DEBT_RATIO_KEY}
* {@link CoreMetrics#NEW_MAINTAINABILITY_RATING_KEY}
+ * {@link SoftwareQualitiesMetrics#NEW_SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO_KEY}
+ * {@link SoftwareQualitiesMetrics#NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY}
*/
public class NewMaintainabilityMeasuresVisitor extends PathAwareVisitorAdapter<NewMaintainabilityMeasuresVisitor.Counter> {
private static final Logger LOG = LoggerFactory.getLogger(NewMaintainabilityMeasuresVisitor.class);
@@ -67,6 +72,10 @@ public class NewMaintainabilityMeasuresVisitor extends PathAwareVisitorAdapter<N
private final Metric newDebtRatioMetric;
private final Metric newMaintainabilityRatingMetric;
+ private final Metric newSoftwareQualityMaintainabilityDebtRatioMetric;
+ private final Metric newSoftwareQualityMaintainabilityRatingMetric;
+ private final Metric newSoftwareQualityRemediationEffortKey;
+
public NewMaintainabilityMeasuresVisitor(MetricRepository metricRepository, MeasureRepository measureRepository, NewLinesRepository newLinesRepository,
RatingSettings ratingSettings) {
super(CrawlerDepthLimit.FILE, POST_ORDER, CounterFactory.INSTANCE);
@@ -76,6 +85,7 @@ public class NewMaintainabilityMeasuresVisitor extends PathAwareVisitorAdapter<N
// computed by NewDebtAggregator which is executed by IntegrateIssuesVisitor
this.newDebtMetric = metricRepository.getByKey(NEW_TECHNICAL_DEBT_KEY);
+ this.newSoftwareQualityRemediationEffortKey = metricRepository.getByKey(NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT_KEY);
// which line is ncloc and which isn't
this.nclocDataMetric = metricRepository.getByKey(NCLOC_DATA_KEY);
@@ -83,6 +93,8 @@ public class NewMaintainabilityMeasuresVisitor extends PathAwareVisitorAdapter<N
this.newDevelopmentCostMetric = metricRepository.getByKey(NEW_DEVELOPMENT_COST_KEY);
this.newDebtRatioMetric = metricRepository.getByKey(NEW_SQALE_DEBT_RATIO_KEY);
this.newMaintainabilityRatingMetric = metricRepository.getByKey(NEW_MAINTAINABILITY_RATING_KEY);
+ this.newSoftwareQualityMaintainabilityDebtRatioMetric = metricRepository.getByKey(NEW_SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO_KEY);
+ this.newSoftwareQualityMaintainabilityRatingMetric = metricRepository.getByKey(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY);
}
@Override
@@ -107,19 +119,26 @@ public class NewMaintainabilityMeasuresVisitor extends PathAwareVisitorAdapter<N
if (!newLinesRepository.newLinesAvailable()) {
return;
}
- double density = computeDensity(path.current());
- double newDebtRatio = 100.0 * density;
- int newMaintainability = ratingSettings.getDebtRatingGrid().getRatingForDensity(density).getIndex();
+
float newDevelopmentCost = path.current().getDevCost().getValue();
measureRepository.add(component, this.newDevelopmentCostMetric, newMeasureBuilder().create(newDevelopmentCost));
+
+ double density = computeDensity(path.current().getNewDebt(), path.current().getDevCost());
+ double newDebtRatio = 100.0 * density;
+ int newMaintainabilityRating = ratingSettings.getDebtRatingGrid().getRatingForDensity(density).getIndex();
measureRepository.add(component, this.newDebtRatioMetric, newMeasureBuilder().create(newDebtRatio));
- measureRepository.add(component, this.newMaintainabilityRatingMetric, newMeasureBuilder().create(newMaintainability));
+ measureRepository.add(component, this.newMaintainabilityRatingMetric, newMeasureBuilder().create(newMaintainabilityRating));
+
+ double densityBasedOnSoftwareQuality = computeDensity(path.current().getNewSoftwareQualityDebt(), path.current().getDevCost());
+ double newSoftwareQualityDebtRatio = 100.0 * densityBasedOnSoftwareQuality;
+ int newSoftwareQualityMaintainabilityRating = ratingSettings.getDebtRatingGrid().getAToDRatingForDensity(densityBasedOnSoftwareQuality).getIndex();
+ measureRepository.add(component, this.newSoftwareQualityMaintainabilityDebtRatioMetric, newMeasureBuilder().create(newSoftwareQualityDebtRatio));
+ measureRepository.add(component, this.newSoftwareQualityMaintainabilityRatingMetric, newMeasureBuilder().create(newSoftwareQualityMaintainabilityRating));
}
- private static double computeDensity(Counter counter) {
- LongValue newDebt = counter.getNewDebt();
+ private static double computeDensity(LongValue newDebt, LongValue devCost) {
if (newDebt.isSet()) {
- long developmentCost = counter.getDevCost().getValue();
+ long developmentCost = devCost.getValue();
if (developmentCost != 0L) {
return newDebt.getValue() / (double) developmentCost;
}
@@ -169,6 +188,9 @@ public class NewMaintainabilityMeasuresVisitor extends PathAwareVisitorAdapter<N
if (hasDevCost) {
long newDebt = getLongValue(measureRepository.getRawMeasure(file, this.newDebtMetric));
devCostCounter.incrementNewDebt(newDebt);
+
+ long newSoftwareQualityDebt = getLongValue(measureRepository.getRawMeasure(file, this.newSoftwareQualityRemediationEffortKey));
+ devCostCounter.incrementNewSoftwareQualityDebt(newSoftwareQualityDebt);
}
}
@@ -192,25 +214,35 @@ public class NewMaintainabilityMeasuresVisitor extends PathAwareVisitorAdapter<N
public static final class Counter {
private final LongValue newDebt = new LongValue();
+ private final LongValue newSoftwareQualityDebt = new LongValue();
private final LongValue devCost = new LongValue();
public void add(Counter counter) {
this.newDebt.increment(counter.newDebt);
+ this.newSoftwareQualityDebt.increment(counter.newSoftwareQualityDebt);
this.devCost.increment(counter.devCost);
}
- LongValue incrementNewDebt(long value) {
- return newDebt.increment(value);
+ void incrementNewDebt(long value) {
+ newDebt.increment(value);
+ }
+
+ void incrementNewSoftwareQualityDebt(long value) {
+ newSoftwareQualityDebt.increment(value);
}
- LongValue incrementDevCost(long value) {
- return devCost.increment(value);
+ void incrementDevCost(long value) {
+ devCost.increment(value);
}
LongValue getNewDebt() {
return this.newDebt;
}
+ LongValue getNewSoftwareQualityDebt() {
+ return this.newSoftwareQualityDebt;
+ }
+
LongValue getDevCost() {
return this.devCost;
}
diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/MaintainabilityMeasuresVisitorTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/MaintainabilityMeasuresVisitorTest.java
index eb254a30d2d..e944aee492d 100644
--- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/MaintainabilityMeasuresVisitorTest.java
+++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/MaintainabilityMeasuresVisitorTest.java
@@ -19,15 +19,18 @@
*/
package org.sonar.ce.task.projectanalysis.qualitymodel;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
+import java.util.stream.Stream;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import org.sonar.ce.task.projectanalysis.component.Component;
import org.sonar.ce.task.projectanalysis.component.FileAttributes;
import org.sonar.ce.task.projectanalysis.component.ReportComponent;
import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule;
import org.sonar.ce.task.projectanalysis.component.VisitorsCrawler;
-import org.sonar.ce.task.projectanalysis.issue.ComponentIssuesRepositoryRule;
import org.sonar.ce.task.projectanalysis.measure.Measure;
import org.sonar.ce.task.projectanalysis.measure.MeasureRepositoryRule;
import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule;
@@ -36,6 +39,7 @@ import org.sonar.server.measure.Rating;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.params.provider.Arguments.arguments;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.api.measures.CoreMetrics.DEVELOPMENT_COST;
@@ -59,9 +63,18 @@ import static org.sonar.ce.task.projectanalysis.measure.MeasureRepoEntry.entryOf
import static org.sonar.ce.task.projectanalysis.measure.MeasureRepoEntry.toEntries;
import static org.sonar.server.measure.Rating.A;
import static org.sonar.server.measure.Rating.C;
+import static org.sonar.server.measure.Rating.D;
import static org.sonar.server.measure.Rating.E;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.EFFORT_TO_REACH_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_A;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.EFFORT_TO_REACH_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_A_KEY;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO_KEY;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_RATING;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT_KEY;
-public class MaintainabilityMeasuresVisitorTest {
+class MaintainabilityMeasuresVisitorTest {
static final String LANGUAGE_KEY_1 = "lKey1";
static final String LANGUAGE_KEY_2 = "lKey2";
@@ -84,29 +97,30 @@ public class MaintainabilityMeasuresVisitorTest {
.build())
.build();
- @Rule
+ @RegisterExtension
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
- @Rule
+ @RegisterExtension
public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
.add(NCLOC)
.add(DEVELOPMENT_COST)
.add(TECHNICAL_DEBT)
.add(SQALE_DEBT_RATIO)
.add(SQALE_RATING)
- .add(EFFORT_TO_REACH_MAINTAINABILITY_RATING_A);
+ .add(EFFORT_TO_REACH_MAINTAINABILITY_RATING_A)
+ .add(SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT)
+ .add(SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO)
+ .add(SOFTWARE_QUALITY_MAINTAINABILITY_RATING)
+ .add(EFFORT_TO_REACH_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_A);
- @Rule
+ @RegisterExtension
public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
- @Rule
- public ComponentIssuesRepositoryRule componentIssuesRepositoryRule = new ComponentIssuesRepositoryRule(treeRootHolder);
-
- private RatingSettings ratingSettings = mock(RatingSettings.class);
+ private final RatingSettings ratingSettings = mock(RatingSettings.class);
private VisitorsCrawler underTest;
- @Before
+ @BeforeEach
public void setUp() {
// assumes rating configuration is consistent
when(ratingSettings.getDebtRatingGrid()).thenReturn(new DebtRatingGrid(RATING_GRID));
@@ -116,7 +130,7 @@ public class MaintainabilityMeasuresVisitorTest {
}
@Test
- public void measures_created_for_project_are_all_zero_when_they_have_no_FILE_child() {
+ void measures_created_for_project_are_all_zero_when_they_have_no_FILE_child() {
ReportComponent root = builder(PROJECT, 1).build();
treeRootHolder.setRoot(root);
@@ -127,11 +141,14 @@ public class MaintainabilityMeasuresVisitorTest {
entryOf(DEVELOPMENT_COST_KEY, newMeasureBuilder().create("0")),
entryOf(SQALE_DEBT_RATIO_KEY, newMeasureBuilder().create(0d, 1)),
entryOf(SQALE_RATING_KEY, createMaintainabilityRatingMeasure(A)),
- entryOf(EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY, newMeasureBuilder().create(0L)));
+ entryOf(EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY, newMeasureBuilder().create(0L)),
+ entryOf(SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO_KEY, newMeasureBuilder().create(0d, 1)),
+ entryOf(SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY, createMaintainabilityRatingMeasure(A)),
+ entryOf(EFFORT_TO_REACH_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_A_KEY, newMeasureBuilder().create(0L)));
}
@Test
- public void compute_development_cost() {
+ void compute_development_cost() {
ReportComponent root = builder(PROJECT, 1).addChildren(
builder(DIRECTORY, 111).addChildren(
createFileComponent(LANGUAGE_KEY_1, 1111),
@@ -187,36 +204,44 @@ public class MaintainabilityMeasuresVisitorTest {
ncloc1211 * DEV_COST));
}
- @Test
- public void compute_maintainability_debt_ratio_measure() {
+ private static Stream<Arguments> metrics() {
+ return Stream.of(
+ arguments(TECHNICAL_DEBT_KEY, SQALE_DEBT_RATIO_KEY, SQALE_RATING_KEY, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY),
+ arguments(SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT_KEY, SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO_KEY, SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY,
+ EFFORT_TO_REACH_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_A_KEY));
+ }
+
+ @ParameterizedTest
+ @MethodSource("metrics")
+ void compute_maintainability_debt_ratio_measure(String remediationEffortKey, String debtRatioKey) {
treeRootHolder.setRoot(ROOT_PROJECT);
int file1Ncloc = 10;
addRawMeasure(NCLOC_KEY, FILE_1_REF, file1Ncloc);
long file1MaintainabilityCost = 100L;
- addRawMeasure(TECHNICAL_DEBT_KEY, FILE_1_REF, file1MaintainabilityCost);
+ addRawMeasure(remediationEffortKey, FILE_1_REF, file1MaintainabilityCost);
int file2Ncloc = 5;
addRawMeasure(NCLOC_KEY, FILE_2_REF, file2Ncloc);
long file2MaintainabilityCost = 1L;
- addRawMeasure(TECHNICAL_DEBT_KEY, FILE_2_REF, file2MaintainabilityCost);
+ addRawMeasure(remediationEffortKey, FILE_2_REF, file2MaintainabilityCost);
long directoryMaintainabilityCost = 100L;
- addRawMeasure(TECHNICAL_DEBT_KEY, DIRECTORY_REF, directoryMaintainabilityCost);
+ addRawMeasure(remediationEffortKey, DIRECTORY_REF, directoryMaintainabilityCost);
long projectMaintainabilityCost = 1000L;
- addRawMeasure(TECHNICAL_DEBT_KEY, PROJECT_REF, projectMaintainabilityCost);
+ addRawMeasure(remediationEffortKey, PROJECT_REF, projectMaintainabilityCost);
underTest.visit(ROOT_PROJECT);
- verifyAddedRawMeasure(FILE_1_REF, SQALE_DEBT_RATIO_KEY, file1MaintainabilityCost * 1d / (file1Ncloc * DEV_COST) * 100);
- verifyAddedRawMeasure(FILE_2_REF, SQALE_DEBT_RATIO_KEY, file2MaintainabilityCost * 1d / (file2Ncloc * DEV_COST) * 100);
- verifyAddedRawMeasure(DIRECTORY_REF, SQALE_DEBT_RATIO_KEY, directoryMaintainabilityCost * 1d / ((file1Ncloc + file2Ncloc) * DEV_COST) * 100);
- verifyAddedRawMeasure(PROJECT_REF, SQALE_DEBT_RATIO_KEY, projectMaintainabilityCost * 1d / ((file1Ncloc + file2Ncloc) * DEV_COST) * 100);
+ verifyAddedRawMeasure(FILE_1_REF, debtRatioKey, file1MaintainabilityCost * 1d / (file1Ncloc * DEV_COST) * 100);
+ verifyAddedRawMeasure(FILE_2_REF, debtRatioKey, file2MaintainabilityCost * 1d / (file2Ncloc * DEV_COST) * 100);
+ verifyAddedRawMeasure(DIRECTORY_REF, debtRatioKey, directoryMaintainabilityCost * 1d / ((file1Ncloc + file2Ncloc) * DEV_COST) * 100);
+ verifyAddedRawMeasure(PROJECT_REF, debtRatioKey, projectMaintainabilityCost * 1d / ((file1Ncloc + file2Ncloc) * DEV_COST) * 100);
}
@Test
- public void compute_maintainability_rating_measure() {
+ void compute_maintainability_rating_measure() {
treeRootHolder.setRoot(ROOT_PROJECT);
addRawMeasure(NCLOC_KEY, FILE_1_REF, 10);
@@ -237,58 +262,85 @@ public class MaintainabilityMeasuresVisitorTest {
}
@Test
- public void compute_effort_to_maintainability_rating_A_measure() {
+ void compute_software_quality_maintainability_rating_measure() {
+ treeRootHolder.setRoot(ROOT_PROJECT);
+
+ addRawMeasure(NCLOC_KEY, FILE_1_REF, 10);
+ addRawMeasure(SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT_KEY, FILE_1_REF, 100L);
+
+ addRawMeasure(NCLOC_KEY, FILE_2_REF, 5);
+ addRawMeasure(SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT_KEY, FILE_2_REF, 1L);
+
+ addRawMeasure(SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT_KEY, DIRECTORY_REF, 100L);
+ addRawMeasure(SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT_KEY, PROJECT_REF, 1000L);
+
+ underTest.visit(ROOT_PROJECT);
+
+ verifyAddedRawMeasure(FILE_1_REF, SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY, C);
+ verifyAddedRawMeasure(FILE_2_REF, SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY, A);
+ verifyAddedRawMeasure(DIRECTORY_REF, SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY, C);
+ verifyAddedRawMeasure(PROJECT_REF, SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY, D);
+ }
+
+ @ParameterizedTest
+ @MethodSource("metrics")
+ void compute_effort_to_maintainability_rating_A_measure(String remediationEffortKey, String debtRatioKey,
+ String ratingKey, String effortReachRatingAKey) {
treeRootHolder.setRoot(ROOT_PROJECT);
int file1Ncloc = 10;
long file1Effort = 100L;
addRawMeasure(NCLOC_KEY, FILE_1_REF, file1Ncloc);
- addRawMeasure(TECHNICAL_DEBT_KEY, FILE_1_REF, file1Effort);
+ addRawMeasure(remediationEffortKey, FILE_1_REF, file1Effort);
int file2Ncloc = 5;
long file2Effort = 20L;
addRawMeasure(NCLOC_KEY, FILE_2_REF, file2Ncloc);
- addRawMeasure(TECHNICAL_DEBT_KEY, FILE_2_REF, file2Effort);
+ addRawMeasure(remediationEffortKey, FILE_2_REF, file2Effort);
long dirEffort = 120L;
- addRawMeasure(TECHNICAL_DEBT_KEY, DIRECTORY_REF, dirEffort);
+ addRawMeasure(remediationEffortKey, DIRECTORY_REF, dirEffort);
long projectEffort = 150L;
- addRawMeasure(TECHNICAL_DEBT_KEY, PROJECT_REF, projectEffort);
+ addRawMeasure(remediationEffortKey, PROJECT_REF, projectEffort);
underTest.visit(ROOT_PROJECT);
- verifyAddedRawMeasure(FILE_1_REF, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY,
+ verifyAddedRawMeasure(FILE_1_REF, effortReachRatingAKey,
(long) (file1Effort - RATING_GRID[0] * file1Ncloc * DEV_COST));
- verifyAddedRawMeasure(FILE_2_REF, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY,
+ verifyAddedRawMeasure(FILE_2_REF, effortReachRatingAKey,
(long) (file2Effort - RATING_GRID[0] * file2Ncloc * DEV_COST));
- verifyAddedRawMeasure(DIRECTORY_REF, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY,
+ verifyAddedRawMeasure(DIRECTORY_REF, effortReachRatingAKey,
(long) (dirEffort - RATING_GRID[0] * (file1Ncloc + file2Ncloc) * DEV_COST));
- verifyAddedRawMeasure(PROJECT_REF, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY,
+ verifyAddedRawMeasure(PROJECT_REF, effortReachRatingAKey,
(long) (projectEffort - RATING_GRID[0] * (file1Ncloc + file2Ncloc) * DEV_COST));
}
- @Test
- public void compute_0_effort_to_maintainability_rating_A_when_effort_is_lower_than_dev_cost() {
+ @ParameterizedTest
+ @MethodSource("metrics")
+ void compute_0_effort_to_maintainability_rating_A_when_effort_is_lower_than_dev_cost(String remediationEffortKey, String debtRatioKey,
+ String ratingKey, String effortReachRatingAKey) {
treeRootHolder.setRoot(ROOT_PROJECT);
addRawMeasure(NCLOC_KEY, FILE_1_REF, 10);
- addRawMeasure(TECHNICAL_DEBT_KEY, FILE_1_REF, 2L);
+ addRawMeasure(remediationEffortKey, FILE_1_REF, 2L);
underTest.visit(ROOT_PROJECT);
- verifyAddedRawMeasure(FILE_1_REF, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY, 0L);
+ verifyAddedRawMeasure(FILE_1_REF, effortReachRatingAKey, 0L);
}
- @Test
- public void effort_to_maintainability_rating_A_is_same_as_effort_when_no_dev_cost() {
+ @ParameterizedTest
+ @MethodSource("metrics")
+ void effort_to_maintainability_rating_A_is_same_as_effort_when_no_dev_cost(String remediationEffortKey, String debtRatioKey,
+ String ratingKey, String effortReachRatingAKey) {
treeRootHolder.setRoot(ROOT_PROJECT);
- addRawMeasure(TECHNICAL_DEBT_KEY, FILE_1_REF, 100L);
+ addRawMeasure(remediationEffortKey, FILE_1_REF, 100L);
underTest.visit(ROOT_PROJECT);
- verifyAddedRawMeasure(FILE_1_REF, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY, 100);
+ verifyAddedRawMeasure(FILE_1_REF, effortReachRatingAKey, 100);
}
private void addRawMeasure(String metricKey, int componentRef, long value) {
diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewMaintainabilityMeasuresVisitorTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewMaintainabilityMeasuresVisitorTest.java
index f29905756dd..fb1eb27c595 100644
--- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewMaintainabilityMeasuresVisitorTest.java
+++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewMaintainabilityMeasuresVisitorTest.java
@@ -26,10 +26,14 @@ import java.util.Arrays;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
+import java.util.stream.Stream;
import org.assertj.core.data.Offset;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import org.sonar.api.utils.KeyValueFormat;
import org.sonar.ce.task.projectanalysis.component.Component;
import org.sonar.ce.task.projectanalysis.component.FileAttributes;
@@ -44,6 +48,7 @@ import org.sonar.server.measure.DebtRatingGrid;
import org.sonar.server.measure.Rating;
import static com.google.common.base.Preconditions.checkArgument;
+import static org.junit.jupiter.params.provider.Arguments.arguments;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.api.measures.CoreMetrics.NCLOC_DATA;
@@ -63,10 +68,17 @@ import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilde
import static org.sonar.ce.task.projectanalysis.measure.MeasureAssert.assertThat;
import static org.sonar.server.measure.Rating.A;
import static org.sonar.server.measure.Rating.D;
+import static org.sonar.server.measure.Rating.E;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO_KEY;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT_KEY;
public class NewMaintainabilityMeasuresVisitorTest {
- private static final double[] RATING_GRID = new double[]{0.1, 0.2, 0.5, 1};
+ private static final double[] RATING_GRID = new double[] {0.1, 0.2, 0.5, 1};
private static final String LANGUAGE_1_KEY = "language 1 key";
private static final long DEV_COST = 30L;
@@ -74,16 +86,20 @@ public class NewMaintainabilityMeasuresVisitorTest {
private static final int LANGUAGE_1_FILE_REF = 11111;
private static final Offset<Double> VALUE_COMPARISON_OFFSET = Offset.offset(0.01);
- @Rule
+ @RegisterExtension
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
- @Rule
+ @RegisterExtension
public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
.add(NEW_TECHNICAL_DEBT)
.add(NCLOC_DATA)
.add(NEW_SQALE_DEBT_RATIO)
.add(NEW_MAINTAINABILITY_RATING)
- .add(NEW_DEVELOPMENT_COST);
- @Rule
+ .add(NEW_DEVELOPMENT_COST)
+ .add(NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT)
+ .add(NEW_SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO)
+ .add(NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING);
+
+ @RegisterExtension
public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
private NewLinesRepository newLinesRepository = mock(NewLinesRepository.class);
@@ -91,180 +107,202 @@ public class NewMaintainabilityMeasuresVisitorTest {
private VisitorsCrawler underTest;
- @Before
+ @BeforeEach
public void setUp() {
when(ratingSettings.getDebtRatingGrid()).thenReturn(new DebtRatingGrid(RATING_GRID));
when(ratingSettings.getDevCost()).thenReturn(DEV_COST);
underTest = new VisitorsCrawler(Arrays.asList(new NewMaintainabilityMeasuresVisitor(metricRepository, measureRepository, newLinesRepository, ratingSettings)));
}
- @Test
- public void project_has_new_measures() {
+ private static Stream<Arguments> metrics() {
+ return Stream.of(
+ arguments(NEW_TECHNICAL_DEBT_KEY, NEW_SQALE_DEBT_RATIO_KEY, NEW_MAINTAINABILITY_RATING_KEY),
+ arguments(NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT_KEY, NEW_SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO_KEY, NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY));
+ }
+
+ @ParameterizedTest
+ @MethodSource("metrics")
+ void project_has_new_measures(String remediationEffortKey, String debtRatioKey, String ratingKey) {
when(newLinesRepository.newLinesAvailable()).thenReturn(true);
treeRootHolder.setRoot(builder(PROJECT, ROOT_REF).build());
underTest.visit(treeRootHolder.getRoot());
- assertNewDebtRatioValues(ROOT_REF, 0);
- assertNewMaintainability(ROOT_REF, A);
+ assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 0);
+ assertNewRating(ratingKey, ROOT_REF, A);
}
- @Test
- public void project_has_no_measure_if_new_lines_not_available() {
+ @ParameterizedTest
+ @MethodSource("metrics")
+ void project_has_no_measure_if_new_lines_not_available(String remediationEffortKey, String debtRatioKey, String ratingKey) {
when(newLinesRepository.newLinesAvailable()).thenReturn(false);
treeRootHolder.setRoot(builder(PROJECT, ROOT_REF).build());
underTest.visit(treeRootHolder.getRoot());
- assertNoNewDebtRatioMeasure(ROOT_REF);
- assertNoNewMaintainability(ROOT_REF);
+ assertNoNewDebtRatioMeasure(debtRatioKey, ROOT_REF);
+ assertNoNewMaintainability(ratingKey, ROOT_REF);
}
- @Test
- public void file_has_no_new_debt_ratio_variation_if_new_lines_not_available() {
+ @ParameterizedTest
+ @MethodSource("metrics")
+ void file_has_no_new_debt_ratio_variation_if_new_lines_not_available(String remediationEffortKey, String debtRatioKey, String ratingKey) {
when(newLinesRepository.newLinesAvailable()).thenReturn(false);
- setupOneFileAloneInAProject(50, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.NO_NEW_LINES);
- measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(50));
+ setupOneFileAloneInAProject(remediationEffortKey,50, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.NO_NEW_LINES);
+ measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(50));
underTest.visit(treeRootHolder.getRoot());
- assertNoNewDebtRatioMeasure(LANGUAGE_1_FILE_REF);
- assertNoNewDebtRatioMeasure(ROOT_REF);
+ assertNoNewDebtRatioMeasure(debtRatioKey, LANGUAGE_1_FILE_REF);
+ assertNoNewDebtRatioMeasure(debtRatioKey, ROOT_REF);
}
- @Test
- public void file_has_0_new_debt_ratio_if_no_line_is_new() {
+ @ParameterizedTest
+ @MethodSource("metrics")
+ void file_has_0_new_debt_ratio_if_no_line_is_new(String remediationEffortKey, String debtRatioKey, String ratingKey) {
ReportComponent file = builder(FILE, LANGUAGE_1_FILE_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_1_KEY, 1)).build();
treeRootHolder.setRoot(
builder(PROJECT, ROOT_REF)
.addChildren(file)
.build());
- measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(50));
+ measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, remediationEffortKey, createNewDebtMeasure(50));
measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NCLOC_DATA_KEY, createNclocDataMeasure(2, 3, 4));
setNewLines(file);
underTest.visit(treeRootHolder.getRoot());
- assertNewDebtRatioValues(LANGUAGE_1_FILE_REF, 0);
- assertNewDebtRatioValues(ROOT_REF, 0);
+ assertNewDebtRatioValues(debtRatioKey, LANGUAGE_1_FILE_REF, 0);
+ assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 0);
}
- @Test
- public void file_has_new_debt_ratio_if_some_lines_are_new() {
+ @ParameterizedTest
+ @MethodSource("metrics")
+ void file_has_new_debt_ratio_if_some_lines_are_new(String remediationEffortKey, String debtRatioKey, String ratingKey) {
when(newLinesRepository.newLinesAvailable()).thenReturn(true);
- setupOneFileAloneInAProject(50, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.WITH_NEW_LINES);
- measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(50));
+ setupOneFileAloneInAProject(remediationEffortKey,50, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.WITH_NEW_LINES);
+ measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(50));
underTest.visit(treeRootHolder.getRoot());
- assertNewDebtRatioValues(LANGUAGE_1_FILE_REF, 83.33);
- assertNewDebtRatioValues(ROOT_REF, 83.33);
+ assertNewDebtRatioValues(debtRatioKey, LANGUAGE_1_FILE_REF, 83.33);
+ assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 83.33);
}
- @Test
- public void new_debt_ratio_changes_with_language_cost() {
+ @ParameterizedTest
+ @MethodSource("metrics")
+ void new_debt_ratio_changes_with_language_cost(String remediationEffortKey, String debtRatioKey, String ratingKey) {
when(ratingSettings.getDevCost()).thenReturn(DEV_COST * 10);
- setupOneFileAloneInAProject(50, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.WITH_NEW_LINES);
- measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(50));
+ setupOneFileAloneInAProject(remediationEffortKey,50, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.WITH_NEW_LINES);
+ measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(50));
underTest.visit(treeRootHolder.getRoot());
- assertNewDebtRatioValues(LANGUAGE_1_FILE_REF, 8.33);
- assertNewDebtRatioValues(ROOT_REF, 8.33);
+ assertNewDebtRatioValues(debtRatioKey, LANGUAGE_1_FILE_REF, 8.33);
+ assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 8.33);
}
- @Test
- public void new_debt_ratio_changes_with_new_technical_debt() {
- setupOneFileAloneInAProject(500, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.WITH_NEW_LINES);
- measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(500));
+ @ParameterizedTest
+ @MethodSource("metrics")
+ void new_debt_ratio_changes_with_new_technical_debt(String remediationEffortKey, String debtRatioKey, String ratingKey) {
+ setupOneFileAloneInAProject(remediationEffortKey, 500, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.WITH_NEW_LINES);
+ measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(500));
underTest.visit(treeRootHolder.getRoot());
- assertNewDebtRatioValues(LANGUAGE_1_FILE_REF, 833.33);
- assertNewDebtRatioValues(ROOT_REF, 833.33);
+ assertNewDebtRatioValues(debtRatioKey, LANGUAGE_1_FILE_REF, 833.33);
+ assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 833.33);
}
- @Test
- public void new_debt_ratio_on_non_file_level_is_based_on_new_technical_debt_of_that_level() {
- setupOneFileAloneInAProject(500, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.WITH_NEW_LINES);
- measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(1200));
+ @ParameterizedTest
+ @MethodSource("metrics")
+ void new_debt_ratio_on_non_file_level_is_based_on_new_technical_debt_of_that_level(String remediationEffortKey, String debtRatioKey, String ratingKey) {
+ setupOneFileAloneInAProject(remediationEffortKey, 500, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.WITH_NEW_LINES);
+ measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(1200));
underTest.visit(treeRootHolder.getRoot());
- assertNewDebtRatioValues(LANGUAGE_1_FILE_REF, 833.33);
- assertNewDebtRatioValues(ROOT_REF, 833.33);
+ assertNewDebtRatioValues(debtRatioKey, LANGUAGE_1_FILE_REF, 833.33);
+ assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 833.33);
}
- @Test
- public void new_debt_ratio_when_file_is_unit_test() {
- setupOneFileAloneInAProject(500, Flag.UT_FILE, Flag.WITH_NCLOC, Flag.WITH_NEW_LINES);
- measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(1200));
+ @ParameterizedTest
+ @MethodSource("metrics")
+ void new_debt_ratio_when_file_is_unit_test(String remediationEffortKey, String debtRatioKey, String ratingKey) {
+ setupOneFileAloneInAProject(remediationEffortKey, 500, Flag.UT_FILE, Flag.WITH_NCLOC, Flag.WITH_NEW_LINES);
+ measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(1200));
underTest.visit(treeRootHolder.getRoot());
- assertNewDebtRatioValues(LANGUAGE_1_FILE_REF, 833.33);
- assertNewDebtRatioValues(ROOT_REF, 833.33);
+ assertNewDebtRatioValues(debtRatioKey, LANGUAGE_1_FILE_REF, 833.33);
+ assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 833.33);
}
- @Test
- public void new_debt_ratio_is_0_when_file_has_no_new_lines() {
+ @ParameterizedTest
+ @MethodSource("metrics")
+ void new_debt_ratio_is_0_when_file_has_no_new_lines(String remediationEffortKey, String debtRatioKey, String ratingKey) {
when(newLinesRepository.newLinesAvailable()).thenReturn(true);
- setupOneFileAloneInAProject(50, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.NO_NEW_LINES);
- measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(50));
+ setupOneFileAloneInAProject(remediationEffortKey,50, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.NO_NEW_LINES);
+ measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(50));
underTest.visit(treeRootHolder.getRoot());
- assertNewDebtRatioValues(LANGUAGE_1_FILE_REF, 0);
- assertNewDebtRatioValues(ROOT_REF, 0);
+ assertNewDebtRatioValues(debtRatioKey, LANGUAGE_1_FILE_REF, 0);
+ assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 0);
}
- @Test
- public void new_debt_ratio_is_0_on_non_file_level_when_no_file_has_new_lines() {
+ @ParameterizedTest
+ @MethodSource("metrics")
+ void new_debt_ratio_is_0_on_non_file_level_when_no_file_has_new_lines(String remediationEffortKey, String debtRatioKey, String ratingKey) {
when(newLinesRepository.newLinesAvailable()).thenReturn(true);
- setupOneFileAloneInAProject(50, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.NO_NEW_LINES);
- measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(200));
+ setupOneFileAloneInAProject(remediationEffortKey,50, Flag.SRC_FILE, Flag.WITH_NCLOC, Flag.NO_NEW_LINES);
+ measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(200));
underTest.visit(treeRootHolder.getRoot());
- assertNewDebtRatioValues(LANGUAGE_1_FILE_REF, 0);
- assertNewDebtRatioValues(ROOT_REF, 0);
+ assertNewDebtRatioValues(debtRatioKey, LANGUAGE_1_FILE_REF, 0);
+ assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 0);
}
- @Test
- public void new_debt_ratio_is_0_when_there_is_no_ncloc_in_file() {
- setupOneFileAloneInAProject(50, Flag.SRC_FILE, Flag.NO_NCLOC, Flag.WITH_NEW_LINES);
- measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(50));
+ @ParameterizedTest
+ @MethodSource("metrics")
+ void new_debt_ratio_is_0_when_there_is_no_ncloc_in_file(String remediationEffortKey, String debtRatioKey, String ratingKey) {
+ setupOneFileAloneInAProject(remediationEffortKey, 50, Flag.SRC_FILE, Flag.NO_NCLOC, Flag.WITH_NEW_LINES);
+ measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(50));
underTest.visit(treeRootHolder.getRoot());
- assertNewDebtRatioValues(LANGUAGE_1_FILE_REF, 0);
- assertNewDebtRatioValues(ROOT_REF, 0);
+ assertNewDebtRatioValues(debtRatioKey, LANGUAGE_1_FILE_REF, 0);
+ assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 0);
}
- @Test
- public void new_debt_ratio_is_0_on_non_file_level_when_one_file_has_zero_new_debt_because_of_no_changeset() {
- setupOneFileAloneInAProject(50, Flag.SRC_FILE, Flag.NO_NCLOC, Flag.WITH_NEW_LINES);
- measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(200));
+ @ParameterizedTest
+ @MethodSource("metrics")
+ void new_debt_ratio_is_0_on_non_file_level_when_one_file_has_zero_new_debt_because_of_no_changeset(String remediationEffortKey, String debtRatioKey, String ratingKey) {
+ setupOneFileAloneInAProject(remediationEffortKey, 50, Flag.SRC_FILE, Flag.NO_NCLOC, Flag.WITH_NEW_LINES);
+ measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(200));
underTest.visit(treeRootHolder.getRoot());
- assertNewDebtRatioValues(LANGUAGE_1_FILE_REF, 0);
- assertNewDebtRatioValues(ROOT_REF, 0);
+ assertNewDebtRatioValues(debtRatioKey, LANGUAGE_1_FILE_REF, 0);
+ assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 0);
}
- @Test
- public void new_debt_ratio_is_0_when_ncloc_measure_is_missing() {
- setupOneFileAloneInAProject(50, Flag.SRC_FILE, Flag.MISSING_MEASURE_NCLOC, Flag.WITH_NEW_LINES);
- measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(50));
+ @ParameterizedTest
+ @MethodSource("metrics")
+ void new_debt_ratio_is_0_when_ncloc_measure_is_missing(String remediationEffortKey, String debtRatioKey, String ratingKey) {
+ setupOneFileAloneInAProject(remediationEffortKey, 50, Flag.SRC_FILE, Flag.MISSING_MEASURE_NCLOC, Flag.WITH_NEW_LINES);
+ measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(50));
underTest.visit(treeRootHolder.getRoot());
- assertNewDebtRatioValues(LANGUAGE_1_FILE_REF, 0);
- assertNewDebtRatioValues(ROOT_REF, 0);
+ assertNewDebtRatioValues(debtRatioKey, LANGUAGE_1_FILE_REF, 0);
+ assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 0);
}
- @Test
- public void leaf_components_always_have_a_measure_when_at_least_one_period_exist_and_ratio_is_computed_from_current_level_new_debt() {
+ @ParameterizedTest
+ @MethodSource("metrics")
+ void leaf_components_always_have_a_measure_when_at_least_one_period_exist_and_ratio_is_computed_from_current_level_new_debt(String remediationEffortKey, String debtRatioKey,
+ String ratingKey) {
Component file = builder(FILE, LANGUAGE_1_FILE_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_1_KEY, 1)).build();
treeRootHolder.setRoot(
builder(PROJECT, ROOT_REF)
@@ -275,22 +313,23 @@ public class NewMaintainabilityMeasuresVisitorTest {
.build());
Measure newDebtMeasure = createNewDebtMeasure(50);
- measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NEW_TECHNICAL_DEBT_KEY, newDebtMeasure);
- measureRepository.addRawMeasure(111, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(150));
- measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(250));
+ measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, remediationEffortKey, newDebtMeasure);
+ measureRepository.addRawMeasure(111, remediationEffortKey, createNewDebtMeasure(150));
+ measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(250));
// 4 lines file, only first one is not ncloc
measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NCLOC_DATA_KEY, createNclocDataMeasure(2, 3, 4));
// first 2 lines are before all snapshots, 2 last lines are after PERIOD 2's snapshot date
setNewLines(file, 3, 4);
underTest.visit(treeRootHolder.getRoot());
- assertNewDebtRatioValues(LANGUAGE_1_FILE_REF, 83.33);
- assertNewDebtRatioValues(111, 83.33);
- assertNewDebtRatioValues(ROOT_REF, 83.33);
+ assertNewDebtRatioValues(debtRatioKey, LANGUAGE_1_FILE_REF, 83.33);
+ assertNewDebtRatioValues(debtRatioKey, 111, 83.33);
+ assertNewDebtRatioValues(debtRatioKey, ROOT_REF, 83.33);
}
- @Test
- public void compute_new_maintainability_rating() {
+ @ParameterizedTest
+ @MethodSource("metrics")
+ void compute_new_maintainability_rating(String remediationEffortKey, String debtRatioKey, String ratingKey) {
ReportComponent file = builder(FILE, LANGUAGE_1_FILE_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_1_KEY, 1)).build();
treeRootHolder.setRoot(
builder(PROJECT, ROOT_REF)
@@ -301,9 +340,9 @@ public class NewMaintainabilityMeasuresVisitorTest {
.build());
Measure newDebtMeasure = createNewDebtMeasure(50);
- measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NEW_TECHNICAL_DEBT_KEY, newDebtMeasure);
- measureRepository.addRawMeasure(111, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(150));
- measureRepository.addRawMeasure(ROOT_REF, NEW_TECHNICAL_DEBT_KEY, createNewDebtMeasure(250));
+ measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, remediationEffortKey, newDebtMeasure);
+ measureRepository.addRawMeasure(111, remediationEffortKey, createNewDebtMeasure(150));
+ measureRepository.addRawMeasure(ROOT_REF, remediationEffortKey, createNewDebtMeasure(250));
// 4 lines file, only first one is not ncloc
measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NCLOC_DATA_KEY, createNclocDataMeasure(2, 3, 4));
// first 2 lines are before all snapshots, 2 last lines are after PERIOD 2's snapshot date
@@ -312,13 +351,40 @@ public class NewMaintainabilityMeasuresVisitorTest {
underTest.visit(treeRootHolder.getRoot());
- assertNewMaintainability(LANGUAGE_1_FILE_REF, D);
- assertNewMaintainability(111, D);
- assertNewMaintainability(ROOT_REF, D);
+ assertNewRating(ratingKey, LANGUAGE_1_FILE_REF, D);
+ assertNewRating(ratingKey, 111, D);
+ assertNewRating(ratingKey, ROOT_REF, D);
+ }
+
+ @ParameterizedTest
+ @MethodSource("metrics")
+ void compute_new_maintainability_rating_map_to_D(String remediationEffortKey, String debtRatioKey, String ratingKey) {
+ ReportComponent file = builder(FILE, LANGUAGE_1_FILE_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_1_KEY, 1)).build();
+ treeRootHolder.setRoot(
+ builder(PROJECT, ROOT_REF)
+ .addChildren(
+ builder(DIRECTORY, 111)
+ .addChildren(file)
+ .build())
+ .build());
+
+ Measure newDebtMeasure = createNewDebtMeasure(400);
+ measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, remediationEffortKey, newDebtMeasure);
+ measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NCLOC_DATA_KEY, createNclocDataMeasure(2, 3, 4));
+
+ setNewLines(file, 3, 4);
+
+ underTest.visit(treeRootHolder.getRoot());
+
+ if (ratingKey.equals(NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY)) {
+ assertNewRating(ratingKey, LANGUAGE_1_FILE_REF, D);
+ } else if (ratingKey.equals(NEW_MAINTAINABILITY_RATING_KEY)) {
+ assertNewRating(ratingKey, LANGUAGE_1_FILE_REF, E);
+ }
}
@Test
- public void compute_new_development_cost() {
+ void compute_new_development_cost() {
ReportComponent file1 = builder(FILE, LANGUAGE_1_FILE_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_1_KEY, 4)).build();
ReportComponent file2 = builder(FILE, 22_222).setFileAttributes(new FileAttributes(false, LANGUAGE_1_KEY, 6)).build();
treeRootHolder.setRoot(
@@ -346,8 +412,9 @@ public class NewMaintainabilityMeasuresVisitorTest {
assertNewDevelopmentCostValues(22_222, 3 * DEV_COST);
}
- @Test
- public void compute_new_maintainability_rating_to_A_when_no_debt() {
+ @ParameterizedTest
+ @MethodSource("metrics")
+ void compute_new_maintainability_rating_to_A_when_no_debt(String remediationEffortKey, String debtRatioKey, String ratingKey) {
when(newLinesRepository.newLinesAvailable()).thenReturn(true);
treeRootHolder.setRoot(
builder(PROJECT, ROOT_REF)
@@ -360,12 +427,12 @@ public class NewMaintainabilityMeasuresVisitorTest {
underTest.visit(treeRootHolder.getRoot());
- assertNewMaintainability(LANGUAGE_1_FILE_REF, A);
- assertNewMaintainability(111, A);
- assertNewMaintainability(ROOT_REF, A);
+ assertNewRating(ratingKey, LANGUAGE_1_FILE_REF, A);
+ assertNewRating(ratingKey, 111, A);
+ assertNewRating(ratingKey, ROOT_REF, A);
}
- private void setupOneFileAloneInAProject(int newDebt, Flag isUnitTest, Flag withNclocLines, Flag withNewLines) {
+ private void setupOneFileAloneInAProject(String remediationEffortKey, int newDebt, Flag isUnitTest, Flag withNclocLines, Flag withNewLines) {
checkArgument(isUnitTest == Flag.UT_FILE || isUnitTest == Flag.SRC_FILE);
checkArgument(withNclocLines == Flag.WITH_NCLOC || withNclocLines == Flag.NO_NCLOC || withNclocLines == Flag.MISSING_MEASURE_NCLOC);
checkArgument(withNewLines == Flag.WITH_NEW_LINES || withNewLines == Flag.NO_NEW_LINES);
@@ -377,7 +444,7 @@ public class NewMaintainabilityMeasuresVisitorTest {
.build());
Measure newDebtMeasure = createNewDebtMeasure(newDebt);
- measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NEW_TECHNICAL_DEBT_KEY, newDebtMeasure);
+ measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, remediationEffortKey, newDebtMeasure);
if (withNclocLines == Flag.WITH_NCLOC) {
// 4 lines file, only first one is not ncloc
measureRepository.addRawMeasure(LANGUAGE_1_FILE_REF, NCLOC_DATA_KEY, createNclocDataMeasure(2, 3, 4));
@@ -431,25 +498,25 @@ public class NewMaintainabilityMeasuresVisitorTest {
return newMeasureBuilder().create(KeyValueFormat.format(builder.build(), KeyValueFormat.newIntegerConverter(), KeyValueFormat.newIntegerConverter()));
}
- private void assertNoNewDebtRatioMeasure(int componentRef) {
- assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SQALE_DEBT_RATIO_KEY))
+ private void assertNoNewDebtRatioMeasure(String debtRatioKey, int componentRef) {
+ assertThat(measureRepository.getAddedRawMeasure(componentRef, debtRatioKey))
.isAbsent();
}
- private void assertNewDebtRatioValues(int componentRef, double expectedValue) {
- assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SQALE_DEBT_RATIO_KEY)).hasValue(expectedValue, VALUE_COMPARISON_OFFSET);
+ private void assertNewDebtRatioValues(String debtRatioKey, int componentRef, double expectedValue) {
+ assertThat(measureRepository.getAddedRawMeasure(componentRef, debtRatioKey)).hasValue(expectedValue, VALUE_COMPARISON_OFFSET);
}
private void assertNewDevelopmentCostValues(int componentRef, float expectedValue) {
assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_DEVELOPMENT_COST_KEY)).hasValue(expectedValue, VALUE_COMPARISON_OFFSET);
}
- private void assertNewMaintainability(int componentRef, Rating expectedValue) {
- assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_MAINTAINABILITY_RATING_KEY)).hasValue(expectedValue.getIndex());
+ private void assertNewRating(String ratingKey, int componentRef, Rating expectedValue) {
+ assertThat(measureRepository.getAddedRawMeasure(componentRef, ratingKey)).hasValue(expectedValue.getIndex());
}
- private void assertNoNewMaintainability(int componentRef) {
- assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_MAINTAINABILITY_RATING_KEY))
+ private void assertNoNewMaintainability(String ratingKey, int componentRef) {
+ assertThat(measureRepository.getAddedRawMeasure(componentRef, ratingKey))
.isAbsent();
}
}
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/measure/DebtRatingGrid.java b/server/sonar-server-common/src/main/java/org/sonar/server/measure/DebtRatingGrid.java
index 247a1829f98..4bbc2b54ac7 100644
--- a/server/sonar-server-common/src/main/java/org/sonar/server/measure/DebtRatingGrid.java
+++ b/server/sonar-server-common/src/main/java/org/sonar/server/measure/DebtRatingGrid.java
@@ -78,6 +78,17 @@ public class DebtRatingGrid {
.orElseThrow(() -> new IllegalArgumentException(format("Invalid value '%s'", value)));
}
+ /**
+ * Computes a rating from A to D, where E is converted to D.
+ */
+ public Rating getAToDRatingForDensity(double value) {
+ return ratingBounds.entrySet().stream()
+ .filter(e -> e.getValue().match(value))
+ .map(e -> e.getKey() == E ? D : e.getKey())
+ .findFirst()
+ .orElseThrow(() -> new IllegalArgumentException(format("Invalid value '%s'", value)));
+ }
+
public double getGradeLowerBound(Rating rating) {
if (rating.getIndex() > 1) {
return gridValues[rating.getIndex() - 2];
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/measure/DebtRatingGridTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/measure/DebtRatingGridTest.java
index 8a312cba599..6557e108815 100644
--- a/server/sonar-server-common/src/test/java/org/sonar/server/measure/DebtRatingGridTest.java
+++ b/server/sonar-server-common/src/test/java/org/sonar/server/measure/DebtRatingGridTest.java
@@ -55,6 +55,21 @@ public class DebtRatingGridTest {
}
@Test
+ public void getAToDRatingForDensity_returnsValueBetweenAAndD() {
+ assertThat(ratingGrid.getAToDRatingForDensity(0)).isEqualTo(A);
+ assertThat(ratingGrid.getAToDRatingForDensity(0.05)).isEqualTo(A);
+ assertThat(ratingGrid.getAToDRatingForDensity(0.09999999)).isEqualTo(A);
+ assertThat(ratingGrid.getAToDRatingForDensity(0.1)).isEqualTo(A);
+ assertThat(ratingGrid.getAToDRatingForDensity(0.15)).isEqualTo(B);
+ assertThat(ratingGrid.getAToDRatingForDensity(0.2)).isEqualTo(B);
+ assertThat(ratingGrid.getAToDRatingForDensity(0.25)).isEqualTo(C);
+ assertThat(ratingGrid.getAToDRatingForDensity(0.5)).isEqualTo(C);
+ assertThat(ratingGrid.getAToDRatingForDensity(0.65)).isEqualTo(D);
+ assertThat(ratingGrid.getAToDRatingForDensity(1)).isEqualTo(D);
+ assertThat(ratingGrid.getAToDRatingForDensity(1.01)).isEqualTo(D);
+ }
+
+ @Test
public void density_matching_exact_grid_values() {
assertThat(ratingGrid.getRatingForDensity(0.1)).isEqualTo(A);
assertThat(ratingGrid.getRatingForDensity(0.2)).isEqualTo(B);