import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_REVIEWED;
import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_STATUS;
import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_TO_REVIEW_STATUS;
+import static org.sonar.api.measures.CoreMetrics.TECHNICAL_DEBT;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.EFFORT_TO_REACH_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_A;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_RELIABILITY_RATING;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_RELIABILITY_REMEDIATION_EFFORT;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_RATING;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_REMEDIATION_EFFORT;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_REVIEW_RATING;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_RATING;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_RATING;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_REMEDIATION_EFFORT;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_RATING;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REMEDIATION_EFFORT;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REVIEW_RATING;
import static org.sonar.server.measure.Rating.RATING_BY_SEVERITY;
+import static org.sonar.server.measure.Rating.RATING_BY_SOFTWARE_QUALITY_SEVERITY;
import static org.sonar.server.metric.IssueCountMetrics.PRIORITIZED_RULE_ISSUES;
+import static org.sonar.server.security.SecurityReviewRating.computeAToDRating;
import static org.sonar.server.security.SecurityReviewRating.computePercent;
import static org.sonar.server.security.SecurityReviewRating.computeRating;
(context, issues) -> context.setValue(issues.sumEffortOfUnresolved(RuleType.VULNERABILITY, false))),
new MeasureUpdateFormula(CoreMetrics.SQALE_DEBT_RATIO, false, false,
- (context, formula) -> context.setValue(100.0 * debtDensity(context)),
- (context, issues) -> context.setValue(100.0 * debtDensity(context)),
+ (context, formula) -> context.setValue(100.0 * debtDensity(TECHNICAL_DEBT, context)),
+ (context, issues) -> context.setValue(100.0 * debtDensity(TECHNICAL_DEBT, context)),
asList(CoreMetrics.TECHNICAL_DEBT, CoreMetrics.DEVELOPMENT_COST)),
new MeasureUpdateFormula(CoreMetrics.SQALE_RATING, false, false,
- (context, issues) -> context.setValue(context.getDebtRatingGrid().getRatingForDensity(debtDensity(context))),
- (context, issues) -> context.setValue(context.getDebtRatingGrid().getRatingForDensity(debtDensity(context))),
+ (context, issues) -> context.setValue(context.getDebtRatingGrid().getRatingForDensity(debtDensity(TECHNICAL_DEBT, context))),
+ (context, issues) -> context.setValue(context.getDebtRatingGrid().getRatingForDensity(debtDensity(TECHNICAL_DEBT, context))),
asList(CoreMetrics.TECHNICAL_DEBT, CoreMetrics.DEVELOPMENT_COST)),
new MeasureUpdateFormula(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, false, false,
- (context, formula) -> context.setValue(effortToReachMaintainabilityRatingA(context)),
- (context, issues) -> context.setValue(effortToReachMaintainabilityRatingA(context)), asList(CoreMetrics.TECHNICAL_DEBT, CoreMetrics.DEVELOPMENT_COST)),
+ (context, formula) -> context.setValue(effortToReachMaintainabilityRatingA(CoreMetrics.TECHNICAL_DEBT, context)),
+ (context, issues) -> context.setValue(effortToReachMaintainabilityRatingA(CoreMetrics.TECHNICAL_DEBT, context)),
+ asList(CoreMetrics.TECHNICAL_DEBT, CoreMetrics.DEVELOPMENT_COST)),
new MeasureUpdateFormula(CoreMetrics.RELIABILITY_RATING, false, new MaxRatingChildren(),
(context, issues) -> context.setValue(RATING_BY_SEVERITY.get(issues.getHighestSeverityOfUnresolved(RuleType.BUG, false).orElse(Severity.INFO)))),
}),
new MeasureUpdateFormula(CoreMetrics.NEW_SQALE_DEBT_RATIO, true, false,
- (context, formula) -> context.setValue(100.0D * newDebtDensity(context)),
- (context, issues) -> context.setValue(100.0D * newDebtDensity(context)),
+ (context, formula) -> context.setValue(100.0D * newDebtDensity(CoreMetrics.NEW_TECHNICAL_DEBT, context)),
+ (context, issues) -> context.setValue(100.0D * newDebtDensity(CoreMetrics.NEW_TECHNICAL_DEBT, context)),
asList(CoreMetrics.NEW_TECHNICAL_DEBT, CoreMetrics.NEW_DEVELOPMENT_COST)),
new MeasureUpdateFormula(CoreMetrics.NEW_MAINTAINABILITY_RATING, true, false,
- (context, formula) -> context.setValue(context.getDebtRatingGrid().getRatingForDensity(newDebtDensity(context))),
- (context, issues) -> context.setValue(context.getDebtRatingGrid().getRatingForDensity(newDebtDensity(context))),
- asList(CoreMetrics.NEW_TECHNICAL_DEBT, CoreMetrics.NEW_DEVELOPMENT_COST)));
+ (context, formula) -> context.setValue(context.getDebtRatingGrid().getRatingForDensity(newDebtDensity(CoreMetrics.NEW_TECHNICAL_DEBT, context))),
+ (context, issues) -> context.setValue(context.getDebtRatingGrid().getRatingForDensity(newDebtDensity(CoreMetrics.NEW_TECHNICAL_DEBT, context))),
+ asList(CoreMetrics.NEW_TECHNICAL_DEBT, CoreMetrics.NEW_DEVELOPMENT_COST)),
+
+ // Metrics based on Software Qualities
+ new MeasureUpdateFormula(SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, false, true, new AddChildren(),
+ (context, issues) -> context.setValue(issues.sumEffortOfUnresolvedBySoftwareQuality(SoftwareQuality.MAINTAINABILITY, false))),
+
+ new MeasureUpdateFormula(SOFTWARE_QUALITY_RELIABILITY_REMEDIATION_EFFORT, false, true, new AddChildren(),
+ (context, issues) -> context.setValue(issues.sumEffortOfUnresolvedBySoftwareQuality(SoftwareQuality.RELIABILITY, false))),
+
+ new MeasureUpdateFormula(SOFTWARE_QUALITY_SECURITY_REMEDIATION_EFFORT, false, true, new AddChildren(),
+ (context, issues) -> context.setValue(issues.sumEffortOfUnresolvedBySoftwareQuality(SoftwareQuality.SECURITY, false))),
+
+ new MeasureUpdateFormula(NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, true, true, new AddChildren(),
+ (context, issues) -> context.setValue(issues.sumEffortOfUnresolvedBySoftwareQuality(SoftwareQuality.MAINTAINABILITY, true))),
+
+ new MeasureUpdateFormula(NEW_SOFTWARE_QUALITY_RELIABILITY_REMEDIATION_EFFORT, true, true, new AddChildren(),
+ (context, issues) -> context.setValue(issues.sumEffortOfUnresolvedBySoftwareQuality(SoftwareQuality.RELIABILITY, true))),
+
+ new MeasureUpdateFormula(NEW_SOFTWARE_QUALITY_SECURITY_REMEDIATION_EFFORT, true, true, new AddChildren(),
+ (context, issues) -> context.setValue(issues.sumEffortOfUnresolvedBySoftwareQuality(SoftwareQuality.SECURITY, true))),
+
+ new MeasureUpdateFormula(SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO, false, true,
+ (context, formula) -> context.setValue(100.0 * debtDensity(SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, context)),
+ (context, issues) -> context.setValue(100.0 * debtDensity(SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, context)),
+ asList(SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, CoreMetrics.DEVELOPMENT_COST)),
+
+ new MeasureUpdateFormula(NEW_SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO, true, true,
+ (context, formula) -> context.setValue(100.0D * newDebtDensity(NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, context)),
+ (context, issues) -> context.setValue(100.0D * newDebtDensity(NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, context)),
+ asList(NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, CoreMetrics.NEW_DEVELOPMENT_COST)),
+
+ new MeasureUpdateFormula(SOFTWARE_QUALITY_MAINTAINABILITY_RATING, false, true,
+ (context, issues) -> context.setValue(context.getDebtRatingGrid().getAToDRatingForDensity(debtDensity(SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, context))),
+ (context, issues) -> context.setValue(context.getDebtRatingGrid().getAToDRatingForDensity(debtDensity(SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, context))),
+ asList(SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, CoreMetrics.DEVELOPMENT_COST)),
+
+ new MeasureUpdateFormula(NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING, true, true,
+ (context, formula) -> context.setValue(context.getDebtRatingGrid().getAToDRatingForDensity(newDebtDensity(NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, context))),
+ (context, issues) -> context.setValue(context.getDebtRatingGrid().getAToDRatingForDensity(newDebtDensity(NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, context))),
+ asList(NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, CoreMetrics.NEW_DEVELOPMENT_COST)),
+
+ new MeasureUpdateFormula(EFFORT_TO_REACH_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_A, false, true,
+ (context, formula) -> context.setValue(effortToReachMaintainabilityRatingA(SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, context)),
+ (context, issues) -> context.setValue(effortToReachMaintainabilityRatingA(SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, context)),
+ asList(SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, CoreMetrics.DEVELOPMENT_COST)),
+
+ new MeasureUpdateFormula(SOFTWARE_QUALITY_RELIABILITY_RATING, false, true, new MaxRatingChildren(),
+ (context, issues) -> {
+ Rating rating = issues.getHighestSeverityOfUnresolved(SoftwareQuality.RELIABILITY, false)
+ .map(RATING_BY_SOFTWARE_QUALITY_SEVERITY::get)
+ .orElse(Rating.A);
+ context.setValue(rating);
+ }),
+
+ new MeasureUpdateFormula(NEW_SOFTWARE_QUALITY_RELIABILITY_RATING, true, true, new MaxRatingChildren(),
+ (context, issues) -> {
+ Rating rating = issues.getHighestSeverityOfUnresolved(SoftwareQuality.RELIABILITY, true)
+ .map(RATING_BY_SOFTWARE_QUALITY_SEVERITY::get)
+ .orElse(Rating.A);
+ context.setValue(rating);
+ }),
+
+ new MeasureUpdateFormula(SOFTWARE_QUALITY_SECURITY_RATING, false, true, new MaxRatingChildren(),
+ (context, issues) -> {
+ Rating rating = issues.getHighestSeverityOfUnresolved(SoftwareQuality.SECURITY, false)
+ .map(RATING_BY_SOFTWARE_QUALITY_SEVERITY::get)
+ .orElse(Rating.A);
+ context.setValue(rating);
+ }),
+
+ new MeasureUpdateFormula(NEW_SOFTWARE_QUALITY_SECURITY_RATING, true, true, new MaxRatingChildren(),
+ (context, issues) -> {
+ Rating rating = issues.getHighestSeverityOfUnresolved(SoftwareQuality.SECURITY, true)
+ .map(RATING_BY_SOFTWARE_QUALITY_SEVERITY::get)
+ .orElse(Rating.A);
+ context.setValue(rating);
+ }),
+
+ new MeasureUpdateFormula(SOFTWARE_QUALITY_SECURITY_REVIEW_RATING, false, true,
+ (context, formula) -> context.setValue(computeAToDRating(context.getValue(SECURITY_HOTSPOTS_REVIEWED).orElse(null))),
+ (context, issues) -> {
+ Optional<Double> percent = computePercent(issues.countHotspotsByStatus(Issue.STATUS_TO_REVIEW, false), issues.countHotspotsByStatus(Issue.STATUS_REVIEWED, false));
+ context.setValue(computeAToDRating(percent.orElse(null)));
+ }),
+
+ new MeasureUpdateFormula(NEW_SOFTWARE_QUALITY_SECURITY_REVIEW_RATING, true, true,
+ (context, formula) -> context.setValue(computeAToDRating(context.getValue(NEW_SECURITY_HOTSPOTS_REVIEWED).orElse(null))),
+ (context, issues) -> {
+ Optional<Double> percent = computePercent(issues.countHotspotsByStatus(Issue.STATUS_TO_REVIEW, true), issues.countHotspotsByStatus(Issue.STATUS_REVIEWED, true));
+ context.setValue(computeAToDRating(percent.orElse(null)));
+ }));
private static final Set<Metric> FORMULA_METRICS = MeasureUpdateFormulaFactory.extractMetrics(FORMULAS);
- private static double debtDensity(MeasureUpdateFormula.Context context) {
- double debt = Math.max(context.getValue(CoreMetrics.TECHNICAL_DEBT).orElse(0.0D), 0.0D);
+ private static double debtDensity(Metric<?> maintainabilityRemediationEffortMetric, MeasureUpdateFormula.Context context) {
+ double debt = Math.max(context.getValue(maintainabilityRemediationEffortMetric).orElse(0.0D), 0.0D);
Optional<Double> devCost = context.getText(CoreMetrics.DEVELOPMENT_COST).map(Double::parseDouble);
if (devCost.isPresent() && Double.doubleToRawLongBits(devCost.get()) > 0L) {
return debt / devCost.get();
return 0.0D;
}
- private static double newDebtDensity(MeasureUpdateFormula.Context context) {
- double debt = Math.max(context.getValue(CoreMetrics.NEW_TECHNICAL_DEBT).orElse(0.0D), 0.0D);
+ private static double newDebtDensity(Metric<?> maintainabilityRemediationEffortMetric, MeasureUpdateFormula.Context context) {
+ double debt = Math.max(context.getValue(maintainabilityRemediationEffortMetric).orElse(0.0D), 0.0D);
Optional<Double> devCost = context.getValue(CoreMetrics.NEW_DEVELOPMENT_COST);
if (devCost.isPresent() && Double.doubleToRawLongBits(devCost.get()) > 0L) {
return debt / devCost.get();
return 0.0D;
}
- private static double effortToReachMaintainabilityRatingA(MeasureUpdateFormula.Context context) {
+ private static double effortToReachMaintainabilityRatingA(Metric<?> maintainabilityRemediationEffortMetric, MeasureUpdateFormula.Context context) {
double developmentCost = context.getText(CoreMetrics.DEVELOPMENT_COST).map(Double::parseDouble).orElse(0.0D);
- double effort = context.getValue(CoreMetrics.TECHNICAL_DEBT).orElse(0.0D);
+ double effort = context.getValue(maintainabilityRemediationEffortMetric).orElse(0.0D);
double upperGradeCost = context.getDebtRatingGrid().getGradeLowerBound(Rating.B) * developmentCost;
return upperGradeCost < effort ? (effort - upperGradeCost) : 0.0D;
}
import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.stream.Stream;
import javax.annotation.Nullable;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import org.sonar.api.issue.Issue;
import org.sonar.api.issue.impact.SoftwareQuality;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Metric;
import org.sonar.api.rule.Severity;
import org.sonar.api.rules.RuleType;
+import org.sonar.core.metric.SoftwareQualitiesMetrics;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.issue.IssueGroupDto;
import org.sonar.db.issue.IssueImpactGroupDto;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.params.provider.Arguments.arguments;
import static org.sonar.api.issue.impact.Severity.HIGH;
import static org.sonar.api.issue.impact.Severity.LOW;
import static org.sonar.api.issue.impact.Severity.MEDIUM;
import static org.sonar.api.issue.impact.SoftwareQuality.MAINTAINABILITY;
import static org.sonar.api.issue.impact.SoftwareQuality.RELIABILITY;
import static org.sonar.api.issue.impact.SoftwareQuality.SECURITY;
+import static org.sonar.api.measures.CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A;
+import static org.sonar.api.measures.CoreMetrics.NEW_MAINTAINABILITY_RATING_KEY;
import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED;
import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS;
import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS;
import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_STATUS;
import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_TO_REVIEW_STATUS;
import static org.sonar.api.measures.CoreMetrics.SECURITY_REVIEW_RATING;
+import static org.sonar.api.measures.CoreMetrics.SQALE_DEBT_RATIO;
+import static org.sonar.api.measures.CoreMetrics.SQALE_RATING;
+import static org.sonar.api.measures.CoreMetrics.SQALE_RATING_KEY;
+import static org.sonar.api.measures.CoreMetrics.TECHNICAL_DEBT;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT;
import static org.sonar.server.metric.IssueCountMetrics.PRIORITIZED_RULE_ISSUES;
import static org.sonar.test.JsonAssert.assertJson;
.expectedRating(Rating.E);
}
+ @Test
+ void computeHierarchy_shouldRecomputeSoftwareQualityMetricsCombiningOtherMetrics() {
+ new HierarchyTester(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REVIEW_RATING)
+ .withValue(SECURITY_HOTSPOTS_REVIEWED, 0d)
+ .expectedRating(Rating.D);
+ new HierarchyTester(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_REVIEW_RATING)
+ .withValue(NEW_SECURITY_HOTSPOTS_REVIEWED, 0d)
+ .expectedRating(Rating.D);
+ new HierarchyTester(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO)
+ .withValue(SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, 10d)
+ .withValue(CoreMetrics.DEVELOPMENT_COST, "40")
+ .expectedResult(25d);
+ new HierarchyTester(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO)
+ .withValue(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, 10d)
+ .withValue(CoreMetrics.NEW_DEVELOPMENT_COST, 40d)
+ .expectedResult(25d);
+
+ new HierarchyTester(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_RATING)
+ .withValue(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, 10d)
+ .withValue(CoreMetrics.DEVELOPMENT_COST, "40")
+ .expectedRating(Rating.D);
+
+ new HierarchyTester(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING)
+ .withValue(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, 10d)
+ .withValue(CoreMetrics.NEW_DEVELOPMENT_COST, 40d)
+ .expectedRating(Rating.D);
+
+ new HierarchyTester(SoftwareQualitiesMetrics.EFFORT_TO_REACH_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_A)
+ .withValue(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, 10d)
+ .withValue(CoreMetrics.DEVELOPMENT_COST, "40")
+ .expectedResult(8d);
+ }
+
+ static List<Metric<?>> softwareQualityRatingMetric() {
+ return List.of(
+ SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_RATING,
+ SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_RELIABILITY_RATING,
+ SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_RATING,
+ SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_RATING);
+ }
+
+ @MethodSource("softwareQualityRatingMetric")
+ @ParameterizedTest
+ void computeHierarchy_shoudRecomputeSoftwareQualityMetricsBasedOnRating(Metric<?> ratingMetric) {
+ new HierarchyTester(ratingMetric)
+ .withValue(1d)
+ .withChildrenValues(2d, 3d)
+ .expectedRating(Rating.C);
+ }
+
+ static List<Metric<?>> softwareQualitySummingMetric() {
+ return List.of(
+ SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT,
+ SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_REMEDIATION_EFFORT,
+ SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REMEDIATION_EFFORT,
+ SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT,
+ SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_RELIABILITY_REMEDIATION_EFFORT,
+ SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_REMEDIATION_EFFORT);
+ }
+
+ @MethodSource("softwareQualitySummingMetric")
+ @ParameterizedTest
+ void computeHierarchy_shoudRecomputeSoftwareQualityMetricsBasedOnSumming(Metric<?> summingMetric) {
+ new HierarchyTester(summingMetric)
+ .withValue(1d)
+ .withChildrenValues(2d, 3d)
+ .expectedResult(6d);
+ }
+
@Test
void test_violations() {
withNoIssues().assertThatValueIs(CoreMetrics.VIOLATIONS, 0);
newResolvedGroup(RuleType.BUG).setCount(7),
// not bugs
newGroup(RuleType.CODE_SMELL).setCount(11))
- .assertThatValueIs(CoreMetrics.BUGS, 3 + 5);
+ .assertThatValueIs(CoreMetrics.BUGS, 3 + 5);
}
@Test
newResolvedGroup(RuleType.CODE_SMELL).setCount(7),
// not code smells
newGroup(RuleType.BUG).setCount(11))
- .assertThatValueIs(CoreMetrics.CODE_SMELLS, 3 + 5);
+ .assertThatValueIs(CoreMetrics.CODE_SMELLS, 3 + 5);
}
@Test
newResolvedGroup(RuleType.VULNERABILITY).setCount(7),
// not vulnerabilities
newGroup(RuleType.BUG).setCount(11))
- .assertThatValueIs(CoreMetrics.VULNERABILITIES, 3 + 5);
+ .assertThatValueIs(CoreMetrics.VULNERABILITIES, 3 + 5);
}
@Test
newResolvedGroup(RuleType.SECURITY_HOTSPOT).setCount(7),
// not hotspots
newGroup(RuleType.BUG).setCount(11))
- .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS, 3 + 5);
+ .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS, 3 + 5);
}
@Test
- void test_security_review_rating() {
+ void test_security_review_ratings() {
with(
newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3),
newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1))
- .assertThatValueIs(SECURITY_REVIEW_RATING, Rating.B);
+ .assertThatValueIs(SECURITY_REVIEW_RATING, Rating.B)
+ .assertThatValueIs(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REVIEW_RATING, Rating.B);
withNoIssues()
- .assertThatValueIs(SECURITY_REVIEW_RATING, Rating.A);
+ .assertThatValueIs(SECURITY_REVIEW_RATING, Rating.A)
+ .assertThatValueIs(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REVIEW_RATING, Rating.A);
+
+ with(
+ newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(3).setInLeak(true),
+ newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1).setInLeak(true))
+ .assertThatValueIs(SECURITY_REVIEW_RATING, Rating.E)
+ .assertThatValueIs(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REVIEW_RATING, Rating.D);
}
@Test
with(
newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3),
newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1))
- .assertThatValueIs(SECURITY_HOTSPOTS_REVIEWED, 75.0);
+ .assertThatValueIs(SECURITY_HOTSPOTS_REVIEWED, 75.0);
withNoIssues()
.assertNoValue(SECURITY_HOTSPOTS_REVIEWED);
with(
newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3),
newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1))
- .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_STATUS, 3.0);
+ .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_STATUS, 3.0);
withNoIssues()
.assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_STATUS, 0.0);
with(
newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3),
newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1))
- .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 1.0);
+ .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 1.0);
withNoIssues()
.assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 0.0);
newResolvedGroup(RuleType.VULNERABILITY).setSeverity(Severity.INFO).setCount(17),
newResolvedGroup(RuleType.BUG).setSeverity(Severity.MAJOR).setCount(19),
newResolvedGroup(RuleType.SECURITY_HOTSPOT).setSeverity(Severity.INFO).setCount(21))
- .assertThatValueIs(CoreMetrics.BLOCKER_VIOLATIONS, 11 + 13)
- .assertThatValueIs(CoreMetrics.CRITICAL_VIOLATIONS, 7)
- .assertThatValueIs(CoreMetrics.MAJOR_VIOLATIONS, 3 + 5)
- .assertThatValueIs(CoreMetrics.MINOR_VIOLATIONS, 0)
- .assertThatValueIs(CoreMetrics.INFO_VIOLATIONS, 0);
+ .assertThatValueIs(CoreMetrics.BLOCKER_VIOLATIONS, 11 + 13)
+ .assertThatValueIs(CoreMetrics.CRITICAL_VIOLATIONS, 7)
+ .assertThatValueIs(CoreMetrics.MAJOR_VIOLATIONS, 3 + 5)
+ .assertThatValueIs(CoreMetrics.MINOR_VIOLATIONS, 0)
+ .assertThatValueIs(CoreMetrics.INFO_VIOLATIONS, 0);
}
@Test
// exclude unresolved
newGroup(RuleType.VULNERABILITY).setCount(17),
newGroup(RuleType.BUG).setCount(19))
- .assertThatValueIs(CoreMetrics.FALSE_POSITIVE_ISSUES, 5)
- .assertThatValueIs(CoreMetrics.ACCEPTED_ISSUES, 7 + 11);
+ .assertThatValueIs(CoreMetrics.FALSE_POSITIVE_ISSUES, 5)
+ .assertThatValueIs(CoreMetrics.ACCEPTED_ISSUES, 7 + 11);
}
@Test
// exclude security hotspot
newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_OPEN).setCount(12),
newResolvedGroup(Issue.RESOLUTION_FALSE_POSITIVE, Issue.STATUS_CLOSED).setCount(13))
- .assertThatValueIs(CoreMetrics.CONFIRMED_ISSUES, 3 + 5)
- .assertThatValueIs(CoreMetrics.OPEN_ISSUES, 9 + 11)
- .assertThatValueIs(CoreMetrics.REOPENED_ISSUES, 7);
+ .assertThatValueIs(CoreMetrics.CONFIRMED_ISSUES, 3 + 5)
+ .assertThatValueIs(CoreMetrics.OPEN_ISSUES, 9 + 11)
+ .assertThatValueIs(CoreMetrics.REOPENED_ISSUES, 7);
}
@Test
newGroup(RuleType.BUG).setEffort(7.0),
// exclude resolved
newResolvedGroup(RuleType.CODE_SMELL).setEffort(17.0))
- .assertThatValueIs(CoreMetrics.TECHNICAL_DEBT, 3.0 + 5.0);
+ .assertThatValueIs(CoreMetrics.TECHNICAL_DEBT, 3.0 + 5.0);
}
@Test
newGroup(RuleType.CODE_SMELL).setEffort(7.0),
// exclude resolved
newResolvedGroup(RuleType.BUG).setEffort(17.0))
- .assertThatValueIs(CoreMetrics.RELIABILITY_REMEDIATION_EFFORT, 3.0 + 5.0);
+ .assertThatValueIs(CoreMetrics.RELIABILITY_REMEDIATION_EFFORT, 3.0 + 5.0);
}
@Test
newGroup(RuleType.CODE_SMELL).setEffort(7.0),
// exclude resolved
newResolvedGroup(RuleType.VULNERABILITY).setEffort(17.0))
- .assertThatValueIs(CoreMetrics.SECURITY_REMEDIATION_EFFORT, 3.0 + 5.0);
+ .assertThatValueIs(CoreMetrics.SECURITY_REMEDIATION_EFFORT, 3.0 + 5.0);
}
- @Test
- void test_sqale_debt_ratio_and_sqale_rating() {
+ private static Stream<Arguments> maintainabilityMetrics() {
+ return Stream.of(
+ arguments(TECHNICAL_DEBT, SQALE_DEBT_RATIO, SQALE_RATING),
+ arguments(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO,
+ SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_RATING));
+ }
+
+ @ParameterizedTest
+ @MethodSource("maintainabilityMetrics")
+ void test_sqale_debt_ratio_and_sqale_rating(Metric<?> maintainabilityRemediationEffortMetric, Metric<?> maintainabilityDebtRatioMetric, Metric<?> maintainabilityRatingMetric) {
withNoIssues()
- .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0)
- .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
+ .assertThatValueIs(maintainabilityDebtRatioMetric, 0)
+ .assertThatValueIs(maintainabilityRatingMetric, Rating.A);
// technical_debt not computed
with(CoreMetrics.DEVELOPMENT_COST, "0")
- .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0)
- .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
+ .assertThatValueIs(maintainabilityDebtRatioMetric, 0)
+ .assertThatValueIs(maintainabilityRatingMetric, Rating.A);
with(CoreMetrics.DEVELOPMENT_COST, "20")
- .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0)
- .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
+ .assertThatValueIs(maintainabilityDebtRatioMetric, 0)
+ .assertThatValueIs(maintainabilityRatingMetric, Rating.A);
// development_cost not computed
- with(CoreMetrics.TECHNICAL_DEBT, 0)
- .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0)
- .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
- with(CoreMetrics.TECHNICAL_DEBT, 20)
- .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0)
- .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
+ with(maintainabilityRemediationEffortMetric, 0)
+ .assertThatValueIs(maintainabilityDebtRatioMetric, 0)
+ .assertThatValueIs(maintainabilityRatingMetric, Rating.A);
+ with(maintainabilityRemediationEffortMetric, 20)
+ .assertThatValueIs(maintainabilityDebtRatioMetric, 0)
+ .assertThatValueIs(maintainabilityRatingMetric, Rating.A);
// input measures are available
- with(CoreMetrics.TECHNICAL_DEBT, 20.0)
+ with(maintainabilityRemediationEffortMetric, 20.0)
.andText(CoreMetrics.DEVELOPMENT_COST, "0")
- .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0.0)
- .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
+ .assertThatValueIs(maintainabilityDebtRatioMetric, 0.0)
+ .assertThatValueIs(maintainabilityRatingMetric, Rating.A);
- with(CoreMetrics.TECHNICAL_DEBT, 20.0)
+ with(maintainabilityRemediationEffortMetric, 20.0)
.andText(CoreMetrics.DEVELOPMENT_COST, "160")
- .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 12.5)
- .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.C);
+ .assertThatValueIs(maintainabilityDebtRatioMetric, 12.5)
+ .assertThatValueIs(maintainabilityRatingMetric, Rating.C);
- with(CoreMetrics.TECHNICAL_DEBT, 20.0)
+ Verifier verifier = with(maintainabilityRemediationEffortMetric, 20.0)
.andText(CoreMetrics.DEVELOPMENT_COST, "10")
- .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 200.0)
- .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.E);
+ .assertThatValueIs(maintainabilityDebtRatioMetric, 200.0);
+ switch (maintainabilityRatingMetric.key()) {
+ case SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY -> verifier.assertThatValueIs(maintainabilityRatingMetric, Rating.D);
+ case SQALE_RATING_KEY -> verifier.assertThatValueIs(maintainabilityRatingMetric, Rating.E);
+ default -> throw new IllegalArgumentException("Unexpected metric: " + maintainabilityRatingMetric.key());
+ }
// A is 5% --> min debt is exactly 200*0.05=10
with(CoreMetrics.DEVELOPMENT_COST, "200")
- .and(CoreMetrics.TECHNICAL_DEBT, 10.0)
- .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 5.0)
- .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
+ .and(maintainabilityRemediationEffortMetric, 10.0)
+ .assertThatValueIs(maintainabilityDebtRatioMetric, 5.0)
+ .assertThatValueIs(maintainabilityRatingMetric, Rating.A);
- with(CoreMetrics.TECHNICAL_DEBT, 0.0)
+ with(maintainabilityRemediationEffortMetric, 0.0)
.andText(CoreMetrics.DEVELOPMENT_COST, "0")
- .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0.0)
- .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
+ .assertThatValueIs(maintainabilityDebtRatioMetric, 0.0)
+ .assertThatValueIs(maintainabilityRatingMetric, Rating.A);
- with(CoreMetrics.TECHNICAL_DEBT, 0.0)
+ with(maintainabilityRemediationEffortMetric, 0.0)
.andText(CoreMetrics.DEVELOPMENT_COST, "80")
- .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0.0);
+ .assertThatValueIs(maintainabilityDebtRatioMetric, 0.0);
- with(CoreMetrics.TECHNICAL_DEBT, -20.0)
+ with(maintainabilityRemediationEffortMetric, -20.0)
.andText(CoreMetrics.DEVELOPMENT_COST, "0")
- .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0.0)
- .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
+ .assertThatValueIs(maintainabilityDebtRatioMetric, 0.0)
+ .assertThatValueIs(maintainabilityRatingMetric, Rating.A);
// bug, debt can't be negative
- with(CoreMetrics.TECHNICAL_DEBT, -20.0)
+ with(maintainabilityRemediationEffortMetric, -20.0)
.andText(CoreMetrics.DEVELOPMENT_COST, "80")
- .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0.0)
- .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
+ .assertThatValueIs(maintainabilityDebtRatioMetric, 0.0)
+ .assertThatValueIs(maintainabilityRatingMetric, Rating.A);
// bug, cost can't be negative
- with(CoreMetrics.TECHNICAL_DEBT, 20.0)
+ with(maintainabilityRemediationEffortMetric, 20.0)
.andText(CoreMetrics.DEVELOPMENT_COST, "-80")
- .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0.0)
- .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
+ .assertThatValueIs(maintainabilityDebtRatioMetric, 0.0)
+ .assertThatValueIs(maintainabilityRatingMetric, Rating.A);
}
- @Test
- void test_effort_to_reach_maintainability_rating_A() {
+ private static Stream<Arguments> effortToReachAMetrics() {
+ return Stream.of(
+ arguments(TECHNICAL_DEBT, EFFORT_TO_REACH_MAINTAINABILITY_RATING_A),
+ arguments(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT,
+ SoftwareQualitiesMetrics.EFFORT_TO_REACH_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_A));
+ }
+
+ @ParameterizedTest
+ @MethodSource("effortToReachAMetrics")
+ void test_effort_to_reach_maintainability_rating_A(Metric<?> maintainabilityRemediationEffortMetric, Metric<?> effortToReachAMetric) {
withNoIssues()
- .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 0.0);
+ .assertThatValueIs(effortToReachAMetric, 0.0);
// technical_debt not computed
with(CoreMetrics.DEVELOPMENT_COST, 0.0)
- .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 0.0);
+ .assertThatValueIs(effortToReachAMetric, 0.0);
with(CoreMetrics.DEVELOPMENT_COST, 20.0)
- .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 0.0);
+ .assertThatValueIs(effortToReachAMetric, 0.0);
// development_cost not computed
- with(CoreMetrics.TECHNICAL_DEBT, 0.0)
- .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 0.0);
- with(CoreMetrics.TECHNICAL_DEBT, 20.0)
+ with(maintainabilityRemediationEffortMetric, 0.0)
+ .assertThatValueIs(effortToReachAMetric, 0.0);
+ with(maintainabilityRemediationEffortMetric, 20.0)
// development cost is considered as zero, so the effort is to reach... zero
- .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 20.0);
+ .assertThatValueIs(effortToReachAMetric, 20.0);
// B to A
with(CoreMetrics.DEVELOPMENT_COST, "200")
- .and(CoreMetrics.TECHNICAL_DEBT, 40.0)
+ .and(maintainabilityRemediationEffortMetric, 40.0)
// B is 5% --> goal is to reach 200*0.05=10 --> effort is 40-10=30
- .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 40.0 - (200.0 * 0.05));
+ .assertThatValueIs(effortToReachAMetric, 40.0 - (200.0 * 0.05));
// E to A
with(CoreMetrics.DEVELOPMENT_COST, "200")
- .and(CoreMetrics.TECHNICAL_DEBT, 180.0)
+ .and(maintainabilityRemediationEffortMetric, 180.0)
// B is 5% --> goal is to reach 200*0.05=10 --> effort is 180-10=170
- .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 180.0 - (200.0 * 0.05));
+ .assertThatValueIs(effortToReachAMetric, 180.0 - (200.0 * 0.05));
// already A
with(CoreMetrics.DEVELOPMENT_COST, "200")
- .and(CoreMetrics.TECHNICAL_DEBT, 8.0)
+ .and(maintainabilityRemediationEffortMetric, 8.0)
// B is 5% --> goal is to reach 200*0.05=10 --> debt is already at 8 --> effort to reach A is zero
- .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 0.0);
+ .assertThatValueIs(effortToReachAMetric, 0.0);
// exactly lower range of B
with(CoreMetrics.DEVELOPMENT_COST, "200")
- .and(CoreMetrics.TECHNICAL_DEBT, 10.0)
+ .and(maintainabilityRemediationEffortMetric, 10.0)
// B is 5% --> goal is to reach 200*0.05=10 --> debt is 10 --> effort to reach A is zero
// FIXME need zero to reach A but effective rating is B !
- .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 0.0);
+ .assertThatValueIs(effortToReachAMetric, 0.0);
}
@Test
newGroup(RuleType.BUG).setSeverity(Severity.MINOR).setCount(5),
// excluded, not a bug
newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setCount(3))
- // highest severity of bugs is CRITICAL --> D
- .assertThatValueIs(CoreMetrics.RELIABILITY_RATING, Rating.D);
+ // highest severity of bugs is CRITICAL --> D
+ .assertThatValueIs(CoreMetrics.RELIABILITY_RATING, Rating.D);
with(
newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MAJOR).setCount(3),
newGroup(RuleType.VULNERABILITY).setSeverity(Severity.CRITICAL).setCount(5))
- // no bugs --> A
- .assertThatValueIs(CoreMetrics.RELIABILITY_RATING, Rating.A);
+ // no bugs --> A
+ .assertThatValueIs(CoreMetrics.RELIABILITY_RATING, Rating.A);
+ }
+
+ @Test
+ void test_software_quality_reliability_rating() {
+ withNoIssues()
+ .assertThatValueIs(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_RATING, Rating.A);
+
+ with(
+ newImpactGroup(MAINTAINABILITY, HIGH, 1),
+ newImpactGroup(RELIABILITY, MEDIUM, 1),
+ newImpactGroup(RELIABILITY, LOW, 1),
+ newImpactGroup(SECURITY, MEDIUM, 1))
+ .assertThatValueIs(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_RATING, Rating.C);
+
+ with(
+ newImpactGroup(RELIABILITY, LOW, 1))
+ .assertThatValueIs(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_RATING, Rating.B);
+ }
+
+ @Test
+ void test_software_quality_new_reliability_rating() {
+ withNoIssues()
+ .assertThatLeakValueIs(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_RELIABILITY_RATING, Rating.A);
+
+ with(
+ newImpactGroup(MAINTAINABILITY, HIGH, 1, true),
+ newImpactGroup(RELIABILITY, MEDIUM, 1, true),
+ newImpactGroup(RELIABILITY, LOW, 1, true),
+ newImpactGroup(RELIABILITY, HIGH, 1, false),
+ newImpactGroup(SECURITY, HIGH, 1, true))
+ .assertThatLeakValueIs(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_RELIABILITY_RATING, Rating.C);
+
+ with(
+ newImpactGroup(RELIABILITY, LOW, 1, true),
+ newImpactGroup(RELIABILITY, MEDIUM, 1, false))
+ .assertThatLeakValueIs(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_RELIABILITY_RATING, Rating.B);
}
@Test
newGroup(RuleType.VULNERABILITY).setSeverity(Severity.MINOR).setCount(5),
// excluded, not a vulnerability
newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setCount(3))
- // highest severity of vulnerabilities is CRITICAL --> D
- .assertThatValueIs(CoreMetrics.SECURITY_RATING, Rating.D);
+ // highest severity of vulnerabilities is CRITICAL --> D
+ .assertThatValueIs(CoreMetrics.SECURITY_RATING, Rating.D);
with(
newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MAJOR).setCount(3),
newGroup(RuleType.BUG).setSeverity(Severity.CRITICAL).setCount(5))
- // no vulnerabilities --> A
- .assertThatValueIs(CoreMetrics.SECURITY_RATING, Rating.A);
+ // no vulnerabilities --> A
+ .assertThatValueIs(CoreMetrics.SECURITY_RATING, Rating.A);
+ }
+
+ @Test
+ void test_software_quality_security_rating() {
+ withNoIssues()
+ .assertThatValueIs(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_RATING, Rating.A);
+
+ with(
+ newImpactGroup(MAINTAINABILITY, HIGH, 1),
+ newImpactGroup(SECURITY, MEDIUM, 1),
+ newImpactGroup(SECURITY, LOW, 1),
+ newImpactGroup(RELIABILITY, MEDIUM, 1))
+ .assertThatValueIs(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_RATING, Rating.C);
+
+ with(
+ newImpactGroup(SECURITY, LOW, 1))
+ .assertThatValueIs(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_RATING, Rating.B);
+ }
+
+ @Test
+ void test_software_quality_new_security_rating() {
+ withNoIssues()
+ .assertThatLeakValueIs(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_RATING, Rating.A);
+
+ with(
+ newImpactGroup(MAINTAINABILITY, HIGH, 1, true),
+ newImpactGroup(SECURITY, MEDIUM, 1, true),
+ newImpactGroup(SECURITY, LOW, 1, true),
+ newImpactGroup(SECURITY, HIGH, 1, false),
+ newImpactGroup(RELIABILITY, HIGH, 1, true))
+ .assertThatLeakValueIs(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_RATING, Rating.C);
+
+ with(
+ newImpactGroup(SECURITY, LOW, 1, true),
+ newImpactGroup(SECURITY, MEDIUM, 1, false))
+ .assertThatLeakValueIs(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_RATING, Rating.B);
}
@Test
// not bugs
newGroup(RuleType.CODE_SMELL).setInLeak(true).setCount(9),
newGroup(RuleType.VULNERABILITY).setInLeak(true).setCount(11))
- .assertThatLeakValueIs(CoreMetrics.NEW_BUGS, 5 + 7);
+ .assertThatLeakValueIs(CoreMetrics.NEW_BUGS, 5 + 7);
}
// not code smells
newGroup(RuleType.BUG).setInLeak(true).setCount(9),
newGroup(RuleType.VULNERABILITY).setInLeak(true).setCount(11))
- .assertThatLeakValueIs(CoreMetrics.NEW_CODE_SMELLS, 5 + 7);
+ .assertThatLeakValueIs(CoreMetrics.NEW_CODE_SMELLS, 5 + 7);
}
@Test
// not vulnerabilities
newGroup(RuleType.BUG).setInLeak(true).setCount(9),
newGroup(RuleType.CODE_SMELL).setInLeak(true).setCount(11))
- .assertThatLeakValueIs(CoreMetrics.NEW_VULNERABILITIES, 5 + 7);
+ .assertThatLeakValueIs(CoreMetrics.NEW_VULNERABILITIES, 5 + 7);
}
@Test
// not hotspots
newGroup(RuleType.BUG).setInLeak(true).setCount(9),
newGroup(RuleType.CODE_SMELL).setInLeak(true).setCount(11))
- .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS, 5 + 7);
+ .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS, 5 + 7);
}
@Test
newGroup(RuleType.BUG).setInLeak(false).setCount(11),
newGroup(RuleType.CODE_SMELL).setInLeak(false).setCount(13),
newGroup(RuleType.VULNERABILITY).setInLeak(false).setCount(17))
- .assertThatLeakValueIs(CoreMetrics.NEW_VIOLATIONS, 5 + 7 + 9);
+ .assertThatLeakValueIs(CoreMetrics.NEW_VIOLATIONS, 5 + 7 + 9);
}
@Test
// not in leak
newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setInLeak(false).setCount(11),
newGroup(RuleType.BUG).setSeverity(Severity.BLOCKER).setInLeak(false).setCount(13))
- .assertThatLeakValueIs(CoreMetrics.NEW_BLOCKER_VIOLATIONS, 3 + 5 + 7);
+ .assertThatLeakValueIs(CoreMetrics.NEW_BLOCKER_VIOLATIONS, 3 + 5 + 7);
}
@Test
// not in leak
newGroup(RuleType.CODE_SMELL).setSeverity(Severity.CRITICAL).setInLeak(false).setCount(11),
newGroup(RuleType.BUG).setSeverity(Severity.CRITICAL).setInLeak(false).setCount(13))
- .assertThatLeakValueIs(CoreMetrics.NEW_CRITICAL_VIOLATIONS, 3 + 5 + 7);
+ .assertThatLeakValueIs(CoreMetrics.NEW_CRITICAL_VIOLATIONS, 3 + 5 + 7);
}
@Test
// not in leak
newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MAJOR).setInLeak(false).setCount(11),
newGroup(RuleType.BUG).setSeverity(Severity.MAJOR).setInLeak(false).setCount(13))
- .assertThatLeakValueIs(CoreMetrics.NEW_MAJOR_VIOLATIONS, 3 + 5 + 7);
+ .assertThatLeakValueIs(CoreMetrics.NEW_MAJOR_VIOLATIONS, 3 + 5 + 7);
}
@Test
// not in leak
newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MINOR).setInLeak(false).setCount(11),
newGroup(RuleType.BUG).setSeverity(Severity.MINOR).setInLeak(false).setCount(13))
- .assertThatLeakValueIs(CoreMetrics.NEW_MINOR_VIOLATIONS, 3 + 5 + 7);
+ .assertThatLeakValueIs(CoreMetrics.NEW_MINOR_VIOLATIONS, 3 + 5 + 7);
}
@Test
// not in leak
newGroup(RuleType.CODE_SMELL).setSeverity(Severity.INFO).setInLeak(false).setCount(11),
newGroup(RuleType.BUG).setSeverity(Severity.INFO).setInLeak(false).setCount(13))
- .assertThatLeakValueIs(CoreMetrics.NEW_INFO_VIOLATIONS, 3 + 5 + 7);
+ .assertThatLeakValueIs(CoreMetrics.NEW_INFO_VIOLATIONS, 3 + 5 + 7);
}
@Test
// not in leak
newGroup(RuleType.CODE_SMELL).setResolution(Issue.RESOLUTION_WONT_FIX).setInLeak(false).setCount(5),
newGroup(RuleType.BUG).setResolution(Issue.RESOLUTION_WONT_FIX).setInLeak(false).setCount(50))
- .assertThatLeakValueIs(CoreMetrics.NEW_ACCEPTED_ISSUES, 4 + 40);
+ .assertThatLeakValueIs(CoreMetrics.NEW_ACCEPTED_ISSUES, 4 + 40);
}
@Test
newGroup(RuleType.BUG).setEffort(7.0).setInLeak(true),
// exclude resolved
newResolvedGroup(RuleType.CODE_SMELL).setEffort(17.0).setInLeak(true))
- .assertThatLeakValueIs(CoreMetrics.NEW_TECHNICAL_DEBT, 3.0);
+ .assertThatLeakValueIs(CoreMetrics.NEW_TECHNICAL_DEBT, 3.0);
}
@Test
newGroup(RuleType.CODE_SMELL).setEffort(7.0).setInLeak(true),
// exclude resolved
newResolvedGroup(RuleType.BUG).setEffort(17.0).setInLeak(true))
- .assertThatLeakValueIs(CoreMetrics.NEW_RELIABILITY_REMEDIATION_EFFORT, 3.0);
+ .assertThatLeakValueIs(CoreMetrics.NEW_RELIABILITY_REMEDIATION_EFFORT, 3.0);
}
@Test
newGroup(RuleType.CODE_SMELL).setEffort(7.0).setInLeak(true),
// exclude resolved
newResolvedGroup(RuleType.VULNERABILITY).setEffort(17.0).setInLeak(true))
- .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_REMEDIATION_EFFORT, 3.0);
+ .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_REMEDIATION_EFFORT, 3.0);
}
@Test
newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setInLeak(true),
// exclude resolved
newResolvedGroup(RuleType.BUG).setSeverity(Severity.BLOCKER).setInLeak(true))
- // highest severity of bugs on leak period is minor -> B
- .assertThatLeakValueIs(CoreMetrics.NEW_RELIABILITY_RATING, Rating.B);
+ // highest severity of bugs on leak period is minor -> B
+ .assertThatLeakValueIs(CoreMetrics.NEW_RELIABILITY_RATING, Rating.B);
}
@Test
newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setInLeak(true),
// exclude resolved
newResolvedGroup(RuleType.VULNERABILITY).setSeverity(Severity.BLOCKER).setInLeak(true))
- // highest severity of bugs on leak period is minor -> B
- .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_RATING, Rating.B);
+ // highest severity of bugs on leak period is minor -> B
+ .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_RATING, Rating.B);
}
@Test
newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1).setInLeak(true),
// not in leak
newGroup(RuleType.SECURITY_HOTSPOT).setSeverity(Issue.STATUS_TO_REVIEW).setInLeak(false))
- .assertThatLeakValueIs(NEW_SECURITY_REVIEW_RATING, Rating.B);
+ .assertThatLeakValueIs(NEW_SECURITY_REVIEW_RATING, Rating.B)
+ .assertThatLeakValueIs(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_REVIEW_RATING, Rating.B);
withNoIssues()
- .assertThatLeakValueIs(NEW_SECURITY_REVIEW_RATING, Rating.A);
+ .assertThatLeakValueIs(NEW_SECURITY_REVIEW_RATING, Rating.A)
+ .assertThatLeakValueIs(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_REVIEW_RATING, Rating.A);
+
+ with(
+ newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(3).setInLeak(true),
+ newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1).setInLeak(true),
+ // not in leak
+ newGroup(RuleType.SECURITY_HOTSPOT).setSeverity(Issue.STATUS_TO_REVIEW).setInLeak(false))
+ .assertThatLeakValueIs(NEW_SECURITY_REVIEW_RATING, Rating.E)
+ .assertThatLeakValueIs(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_REVIEW_RATING, Rating.D);
}
@Test
newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1).setInLeak(true),
// not in leak
newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(5).setInLeak(false))
- .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED, 75.0);
+ .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED, 75.0);
withNoIssues()
.assertNoLeakValue(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED);
newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1).setInLeak(true),
// not in leak
newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(5).setInLeak(false))
- .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS, 3.0);
+ .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS, 3.0);
withNoIssues()
.assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS, 0.0);
newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1).setInLeak(true),
// not in leak
newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(5).setInLeak(false))
- .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 1.0);
+ .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 1.0);
withNoIssues()
.assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 0.0);
}
- @Test
- void test_new_sqale_debt_ratio_and_new_maintainability_rating() {
+ private static Stream<Arguments> newMaintainabilityMetrics() {
+ return Stream.of(
+ arguments(CoreMetrics.NEW_TECHNICAL_DEBT, CoreMetrics.NEW_SQALE_DEBT_RATIO, CoreMetrics.NEW_MAINTAINABILITY_RATING),
+ arguments(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO,
+ SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING));
+ }
+
+ @ParameterizedTest
+ @MethodSource("newMaintainabilityMetrics")
+ void test_new_sqale_debt_ratio_and_new_maintainability_rating(Metric<?> newMaintainabilityRemediationEffortMetric, Metric<?> newMaintainabilityDebtRatioMetric,
+ Metric<?> newMaintainabilityRatingMetric) {
withNoIssues()
- .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0)
- .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
+ .assertThatLeakValueIs(newMaintainabilityDebtRatioMetric, 0)
+ .assertThatLeakValueIs(newMaintainabilityRatingMetric, Rating.A);
// technical_debt not computed
with(CoreMetrics.NEW_DEVELOPMENT_COST, 0)
- .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0)
- .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
+ .assertThatLeakValueIs(newMaintainabilityDebtRatioMetric, 0)
+ .assertThatLeakValueIs(newMaintainabilityRatingMetric, Rating.A);
with(CoreMetrics.NEW_DEVELOPMENT_COST, 20)
- .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0)
- .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
+ .assertThatLeakValueIs(newMaintainabilityDebtRatioMetric, 0)
+ .assertThatLeakValueIs(newMaintainabilityRatingMetric, Rating.A);
// development_cost not computed
- with(CoreMetrics.NEW_TECHNICAL_DEBT, 0)
- .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0)
- .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
- with(CoreMetrics.NEW_TECHNICAL_DEBT, 20)
- .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0)
- .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
+ with(newMaintainabilityRemediationEffortMetric, 0)
+ .assertThatLeakValueIs(newMaintainabilityDebtRatioMetric, 0)
+ .assertThatLeakValueIs(newMaintainabilityRatingMetric, Rating.A);
+ with(newMaintainabilityRemediationEffortMetric, 20)
+ .assertThatLeakValueIs(newMaintainabilityDebtRatioMetric, 0)
+ .assertThatLeakValueIs(newMaintainabilityRatingMetric, Rating.A);
// input measures are available
- with(CoreMetrics.NEW_TECHNICAL_DEBT, 20.0)
+ with(newMaintainabilityRemediationEffortMetric, 20.0)
.and(CoreMetrics.NEW_DEVELOPMENT_COST, 0.0)
- .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0.0)
- .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
+ .assertThatLeakValueIs(newMaintainabilityDebtRatioMetric, 0.0)
+ .assertThatLeakValueIs(newMaintainabilityRatingMetric, Rating.A);
- with(CoreMetrics.NEW_TECHNICAL_DEBT, 20.0)
+ with(newMaintainabilityRemediationEffortMetric, 20.0)
.and(CoreMetrics.NEW_DEVELOPMENT_COST, 160.0)
- .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 12.5)
- .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.C);
+ .assertThatLeakValueIs(newMaintainabilityDebtRatioMetric, 12.5)
+ .assertThatLeakValueIs(newMaintainabilityRatingMetric, Rating.C);
- with(CoreMetrics.NEW_TECHNICAL_DEBT, 20.0)
+ Verifier verifier = with(newMaintainabilityRemediationEffortMetric, 20.0)
.and(CoreMetrics.NEW_DEVELOPMENT_COST, 10.0D)
- .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 200.0)
- .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.E);
+ .assertThatLeakValueIs(newMaintainabilityDebtRatioMetric, 200.0);
+ switch (newMaintainabilityRatingMetric.key()) {
+ case NEW_MAINTAINABILITY_RATING_KEY -> verifier.assertThatLeakValueIs(newMaintainabilityRatingMetric, Rating.E);
+ case SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY -> verifier.assertThatLeakValueIs(newMaintainabilityRatingMetric, Rating.D);
+ default -> throw new IllegalArgumentException("Unexpected metric: " + newMaintainabilityRatingMetric.key());
+ }
// A is 5% --> min debt is exactly 200*0.05=10
with(CoreMetrics.NEW_DEVELOPMENT_COST, 200.0)
- .and(CoreMetrics.NEW_TECHNICAL_DEBT, 10.0)
- .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 5.0)
- .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
+ .and(newMaintainabilityRemediationEffortMetric, 10.0)
+ .assertThatLeakValueIs(newMaintainabilityDebtRatioMetric, 5.0)
+ .assertThatLeakValueIs(newMaintainabilityRatingMetric, Rating.A);
- with(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0)
+ with(newMaintainabilityRemediationEffortMetric, 0.0)
.and(CoreMetrics.NEW_DEVELOPMENT_COST, 0.0)
- .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0.0)
- .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
+ .assertThatLeakValueIs(newMaintainabilityDebtRatioMetric, 0.0)
+ .assertThatLeakValueIs(newMaintainabilityRatingMetric, Rating.A);
- with(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0)
+ with(newMaintainabilityRemediationEffortMetric, 0.0)
.and(CoreMetrics.NEW_DEVELOPMENT_COST, 80.0)
- .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0.0);
+ .assertThatLeakValueIs(newMaintainabilityDebtRatioMetric, 0.0);
- with(CoreMetrics.NEW_TECHNICAL_DEBT, -20.0)
+ with(newMaintainabilityRemediationEffortMetric, -20.0)
.and(CoreMetrics.NEW_DEVELOPMENT_COST, 0.0)
- .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0.0)
- .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
+ .assertThatLeakValueIs(newMaintainabilityDebtRatioMetric, 0.0)
+ .assertThatLeakValueIs(newMaintainabilityRatingMetric, Rating.A);
// bug, debt can't be negative
- with(CoreMetrics.NEW_TECHNICAL_DEBT, -20.0)
+ with(newMaintainabilityRemediationEffortMetric, -20.0)
.and(CoreMetrics.NEW_DEVELOPMENT_COST, 80.0)
- .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0.0)
- .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
+ .assertThatLeakValueIs(newMaintainabilityDebtRatioMetric, 0.0)
+ .assertThatLeakValueIs(newMaintainabilityRatingMetric, Rating.A);
// bug, cost can't be negative
- with(CoreMetrics.NEW_TECHNICAL_DEBT, 20.0)
+ with(newMaintainabilityRemediationEffortMetric, 20.0)
.and(CoreMetrics.NEW_DEVELOPMENT_COST, -80.0)
- .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0.0)
- .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
+ .assertThatLeakValueIs(newMaintainabilityDebtRatioMetric, 0.0)
+ .assertThatLeakValueIs(newMaintainabilityRatingMetric, Rating.A);
}
@Test
newImpactGroup(SECURITY, LOW, Issue.STATUS_RESOLVED, Issue.RESOLUTION_WONT_FIX, 6),
newImpactGroup(SECURITY, HIGH, Issue.STATUS_RESOLVED, Issue.RESOLUTION_FALSE_POSITIVE, 7),
newImpactGroup(RELIABILITY, HIGH, Issue.STATUS_RESOLVED, Issue.RESOLUTION_WONT_FIX, 8))
- .assertThatValueIs(CoreMetrics.HIGH_IMPACT_ACCEPTED_ISSUES, 4 + 8);
+ .assertThatValueIs(CoreMetrics.HIGH_IMPACT_ACCEPTED_ISSUES, 4 + 8);
+ }
+
+ @Test
+ void compute_shouldComputeRemediationEffortBasedOnSoftwareQuality() {
+ withNoIssues()
+ .assertThatValueIs(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, 0)
+ .assertThatValueIs(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REMEDIATION_EFFORT, 0)
+ .assertThatValueIs(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_REMEDIATION_EFFORT, 0)
+ .assertThatLeakValueIs(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, 0d)
+ .assertThatLeakValueIs(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_RELIABILITY_REMEDIATION_EFFORT, 0d)
+ .assertThatLeakValueIs(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_REMEDIATION_EFFORT, 0d);
+
+ with(
+ newImpactGroup(RELIABILITY, HIGH, 3, 1d),
+ newImpactGroup(RELIABILITY, MEDIUM, 1, 2d, true),
+ newImpactGroup(SECURITY, MEDIUM, 1, 1d),
+ newImpactGroup(MAINTAINABILITY, MEDIUM, 1, 1d),
+ newImpactGroup(MAINTAINABILITY, HIGH, 1, 2d, true),
+ newImpactGroup(SECURITY, HIGH, Issue.STATUS_RESOLVED, Issue.RESOLUTION_WONT_FIX, 4, 1d, false),
+ newImpactGroup(RELIABILITY, HIGH, Issue.STATUS_RESOLVED, Issue.RESOLUTION_WONT_FIX, 8, 1d, false),
+ newImpactGroup(MAINTAINABILITY, MEDIUM, Issue.STATUS_RESOLVED, Issue.RESOLUTION_WONT_FIX, 8, 1d, false))
+ .assertThatValueIs(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, 1d + 2d)
+ .assertThatValueIs(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_REMEDIATION_EFFORT, 1d + 2d)
+ .assertThatValueIs(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REMEDIATION_EFFORT, 1d)
+ .assertThatLeakValueIs(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT, 2d)
+ .assertThatLeakValueIs(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_RELIABILITY_REMEDIATION_EFFORT, 2d)
+ .assertThatLeakValueIs(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_REMEDIATION_EFFORT, 0d);
}
@Test
newImpactGroup(MAINTAINABILITY, MEDIUM, 10),
newImpactGroup(MAINTAINABILITY, LOW, 11),
newImpactGroup(SECURITY, HIGH, 3))
- .assertThatJsonValueIs(CoreMetrics.RELIABILITY_ISSUES, impactMeasureToJson(8, 3, 4, 1))
- .assertThatJsonValueIs(CoreMetrics.MAINTAINABILITY_ISSUES, impactMeasureToJson(21, 0, 10, 11))
- .assertThatJsonValueIs(CoreMetrics.SECURITY_ISSUES, impactMeasureToJson(3, 3, 0, 0));
+ .assertThatJsonValueIs(CoreMetrics.RELIABILITY_ISSUES, impactMeasureToJson(8, 3, 4, 1))
+ .assertThatJsonValueIs(CoreMetrics.MAINTAINABILITY_ISSUES, impactMeasureToJson(21, 0, 10, 11))
+ .assertThatJsonValueIs(CoreMetrics.SECURITY_ISSUES, impactMeasureToJson(3, 3, 0, 0));
}
@Test
}
private static IssueImpactGroupDto newImpactGroup(SoftwareQuality softwareQuality, org.sonar.api.issue.impact.Severity severity,
- String status, @Nullable String resolution, long count) {
+ String status, @Nullable String resolution, long count, double effort, boolean inLeak) {
IssueImpactGroupDto dto = new IssueImpactGroupDto();
dto.setSoftwareQuality(softwareQuality);
dto.setSeverity(severity);
dto.setStatus(status);
dto.setResolution(resolution);
dto.setCount(count);
+ dto.setEffort(effort);
+ dto.setInLeak(inLeak);
return dto;
}
+ private static IssueImpactGroupDto newImpactGroup(SoftwareQuality softwareQuality, org.sonar.api.issue.impact.Severity severity,
+ String status, @Nullable String resolution, long count) {
+ return newImpactGroup(softwareQuality, severity, status, resolution, count, 0, false);
+ }
+
private static IssueImpactGroupDto newImpactGroup(SoftwareQuality softwareQuality, org.sonar.api.issue.impact.Severity severity, long count) {
- return newImpactGroup(softwareQuality, severity, Issue.STATUS_OPEN, null, count);
+ return newImpactGroup(softwareQuality, severity, Issue.STATUS_OPEN, null, count, 0, false);
+ }
+
+ private static IssueImpactGroupDto newImpactGroup(SoftwareQuality softwareQuality, org.sonar.api.issue.impact.Severity severity, long count, boolean inLeak) {
+ return newImpactGroup(softwareQuality, severity, Issue.STATUS_OPEN, null, count, 0, inLeak);
+ }
+
+ private static IssueImpactGroupDto newImpactGroup(SoftwareQuality softwareQuality, org.sonar.api.issue.impact.Severity severity, long count, double effort) {
+ return newImpactGroup(softwareQuality, severity, Issue.STATUS_OPEN, null, count, effort, false);
+ }
+
+ private static IssueImpactGroupDto newImpactGroup(SoftwareQuality softwareQuality, org.sonar.api.issue.impact.Severity severity, long count, double effort, boolean inLeak) {
+ return newImpactGroup(softwareQuality, severity, Issue.STATUS_OPEN, null, count, effort, inLeak);
}
private static IssueGroupDto newResolvedGroup(RuleType ruleType) {