From ff867f10ae2bd4955055b781ec68039cf28b3b37 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Thu, 3 Dec 2015 11:06:40 +0100 Subject: [PATCH] SONAR-7028 Update default value of sonar.technicalDebt.ratingGrid Default value is now "0.05,0.1,0.2,0.5", it was "0.1,0.2,0.5,1" --- .../java/it/debt/DebtConfigurationRule.java | 107 ++++++++++++++++++ .../java/it/debt/SqaleRatingMeasureTest.java | 32 ++---- .../TechnicalDebtInIssueChangelogTest.java | 13 +-- .../test/java/it/debt/TechnicalDebtTest.java | 18 ++- .../java/it/debt/TechnicalDebtWidgetTest.java | 6 + .../org/sonar/core/config/DebtProperties.java | 4 +- .../java/org/sonar/api/CoreProperties.java | 2 +- 7 files changed, 139 insertions(+), 43 deletions(-) create mode 100644 it/it-tests/src/test/java/it/debt/DebtConfigurationRule.java diff --git a/it/it-tests/src/test/java/it/debt/DebtConfigurationRule.java b/it/it-tests/src/test/java/it/debt/DebtConfigurationRule.java new file mode 100644 index 00000000000..8c728645b8e --- /dev/null +++ b/it/it-tests/src/test/java/it/debt/DebtConfigurationRule.java @@ -0,0 +1,107 @@ +package it.debt; + +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableSet; +import com.sonar.orchestrator.Orchestrator; +import java.util.Set; +import org.junit.rules.ExternalResource; + +import static com.google.common.base.Preconditions.checkState; +import static util.ItUtils.setServerProperty; + +/** + * This rule should be used when dealing with technical debt properties, in order to always be sure that the properties are correctly reset between each tests. + */ +public class DebtConfigurationRule extends ExternalResource { + + private static final String HOURS_IN_DAY_PROPERTY = "sonar.technicalDebt.hoursInDay"; + private static final String DEV_COST_PROPERTY = "sonar.technicalDebt.developmentCost"; + private static final String RATING_GRID_PROPERTY = "sonar.technicalDebt.ratingGrid"; + + private static final String DEV_COST_LANGUAGE_PROPERTY = "languageSpecificParameters"; + private static final String DEV_COST_LANGUAGE_NAME_PROPERTY = DEV_COST_LANGUAGE_PROPERTY + ".0.language"; + private static final String DEV_COST_LANGUAGE_COST_PROPERTY = DEV_COST_LANGUAGE_PROPERTY + ".0.man_days"; + + private static final Joiner COMA_JOINER = Joiner.on(","); + + private static final Set DEV_COST_PROPERTIES = ImmutableSet.of( + DEV_COST_PROPERTY, + DEV_COST_LANGUAGE_PROPERTY, + DEV_COST_LANGUAGE_NAME_PROPERTY, + DEV_COST_LANGUAGE_COST_PROPERTY, + RATING_GRID_PROPERTY); + + private final Orchestrator orchestrator; + + private DebtConfigurationRule(Orchestrator orchestrator) { + this.orchestrator = orchestrator; + } + + public static DebtConfigurationRule create(Orchestrator orchestrator) { + return new DebtConfigurationRule(orchestrator); + } + + @Override + protected void before() throws Throwable { + reset(); + } + + @Override + protected void after() { + reset(); + } + + public void reset() { + resetHoursInDay(); + resetDevelopmentCost(); + resetRatingGrid(); + } + + public DebtConfigurationRule updateHoursInDay(int hoursInDay) { + setProperty(HOURS_IN_DAY_PROPERTY, Integer.toString(hoursInDay)); + return this; + } + + public DebtConfigurationRule resetHoursInDay() { + resetProperty(HOURS_IN_DAY_PROPERTY); + return this; + } + + public DebtConfigurationRule updateDevelopmentCost(int developmentCost) { + setProperty(DEV_COST_PROPERTY, Integer.toString(developmentCost)); + return this; + } + + public DebtConfigurationRule updateLanguageDevelopmentCost(String language, int developmentCost) { + setServerProperty(orchestrator, DEV_COST_LANGUAGE_PROPERTY, "0"); + setServerProperty(orchestrator, DEV_COST_LANGUAGE_NAME_PROPERTY, language); + setServerProperty(orchestrator, DEV_COST_LANGUAGE_COST_PROPERTY, Integer.toString(developmentCost)); + return this; + } + + public void resetDevelopmentCost() { + for (String property : DEV_COST_PROPERTIES) { + resetProperty(property); + } + } + + public DebtConfigurationRule updateRatingGrid(Double... ratingGrid) { + checkState(ratingGrid.length == 4, "Rating grid must contains 4 values"); + setProperty(RATING_GRID_PROPERTY, COMA_JOINER.join(ratingGrid)); + return this; + } + + public DebtConfigurationRule resetRatingGrid() { + resetProperty(RATING_GRID_PROPERTY); + return this; + } + + private void setProperty(String property, String value) { + setServerProperty(orchestrator, property, value); + } + + private void resetProperty(String property) { + setProperty(property, null); + } + +} diff --git a/it/it-tests/src/test/java/it/debt/SqaleRatingMeasureTest.java b/it/it-tests/src/test/java/it/debt/SqaleRatingMeasureTest.java index da898fe4125..75c50d20340 100644 --- a/it/it-tests/src/test/java/it/debt/SqaleRatingMeasureTest.java +++ b/it/it-tests/src/test/java/it/debt/SqaleRatingMeasureTest.java @@ -19,14 +19,13 @@ */ package it.debt; -import com.google.common.collect.ImmutableSet; import com.sonar.orchestrator.Orchestrator; import com.sonar.orchestrator.build.SonarRunner; import com.sonar.orchestrator.locator.FileLocation; import it.Category2Suite; -import org.junit.AfterClass; import org.junit.Before; import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; import org.sonar.wsclient.services.Measure; import org.sonar.wsclient.services.Resource; @@ -34,7 +33,6 @@ import org.sonar.wsclient.services.ResourceQuery; import static org.assertj.core.api.Assertions.assertThat; import static util.ItUtils.projectDir; -import static util.ItUtils.setServerProperty; /** * SONAR-4715 @@ -46,26 +44,19 @@ public class SqaleRatingMeasureTest { private static final String SUB_MODULE = "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1"; private static final String DIRECTORY = "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1"; private static final String FILE = "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo"; + @ClassRule public static Orchestrator orchestrator = Category2Suite.ORCHESTRATOR; - private static void resetDevelopmentCost() { - for (String property : ImmutableSet.of("sonar.technicalDebt.developmentCost", "sonar.technicalDebt.sizeMetric", - "languageSpecificParameters", "languageSpecificParameters.0.language", "languageSpecificParameters.0.man_days", "languageSpecificParameters.0.size_metric", - "ratingGrid")) { - setServerProperty(orchestrator, property, null); - } - } - - @AfterClass - public static void reset() { - resetDevelopmentCost(); - } + @Rule + public DebtConfigurationRule debtConfiguration = DebtConfigurationRule.create(orchestrator); @Before public void init() { - resetDevelopmentCost(); orchestrator.resetData(); + + // Set rating grid values to not depend from default value + debtConfiguration.updateRatingGrid(0.1d, 0.2d, 0.5d, 1d); } @Test @@ -119,7 +110,7 @@ public class SqaleRatingMeasureTest { assertThat(rating.getIntValue()).isEqualTo(1); assertThat(rating.getData()).isEqualTo("A"); - setServerProperty(orchestrator, "sonar.technicalDebt.developmentCost", "2"); + debtConfiguration.updateDevelopmentCost(2); orchestrator.executeBuild(SonarRunner.create(projectDir("shared/xoo-sample"))); rating = getMeasure("sample", "sqale_rating"); @@ -139,10 +130,7 @@ public class SqaleRatingMeasureTest { assertThat(rating.getIntValue()).isEqualTo(1); assertThat(rating.getData()).isEqualTo("A"); - setServerProperty(orchestrator, "languageSpecificParameters", "0"); - setServerProperty(orchestrator, "languageSpecificParameters.0.language", "xoo"); - setServerProperty(orchestrator, "languageSpecificParameters.0.man_days", "1"); - setServerProperty(orchestrator, "languageSpecificParameters.0.size_metric", "ncloc"); + debtConfiguration.updateLanguageDevelopmentCost("xoo", 1); orchestrator.executeBuild( SonarRunner.create(projectDir("shared/xoo-multi-modules-sample")) .setProfile("one-issue-per-line")); @@ -164,7 +152,7 @@ public class SqaleRatingMeasureTest { assertThat(rating.getIntValue()).isEqualTo(1); assertThat(rating.getData()).isEqualTo("A"); - setServerProperty(orchestrator, "ratingGrid", "0.001,0.005,0.010,0.015"); + debtConfiguration.updateRatingGrid(0.001d, 0.005d, 0.01d, 0.015d); orchestrator.executeBuild(SonarRunner.create(projectDir("shared/xoo-sample"))); rating = getMeasure("sample", "sqale_rating"); diff --git a/it/it-tests/src/test/java/it/debt/TechnicalDebtInIssueChangelogTest.java b/it/it-tests/src/test/java/it/debt/TechnicalDebtInIssueChangelogTest.java index 30f1ebf6ab5..9b405dd902b 100644 --- a/it/it-tests/src/test/java/it/debt/TechnicalDebtInIssueChangelogTest.java +++ b/it/it-tests/src/test/java/it/debt/TechnicalDebtInIssueChangelogTest.java @@ -24,9 +24,9 @@ import com.sonar.orchestrator.build.SonarRunner; import com.sonar.orchestrator.locator.FileLocation; import it.Category2Suite; import java.util.List; -import org.junit.AfterClass; import org.junit.Before; import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; import org.sonar.wsclient.issue.Issue; import org.sonar.wsclient.issue.IssueChange; @@ -36,7 +36,6 @@ import org.sonar.wsclient.issue.IssueQuery; import static org.assertj.core.api.Assertions.assertThat; import static util.ItUtils.projectDir; -import static util.ItUtils.setServerProperty; /** * SONAR-4834 @@ -46,17 +45,15 @@ public class TechnicalDebtInIssueChangelogTest { @ClassRule public static Orchestrator orchestrator = Category2Suite.ORCHESTRATOR; - @AfterClass - public static void resetHoursInDay() throws Exception { - setServerProperty(orchestrator, "sonar.technicalDebt.hoursInDay", null); - } + @Rule + public DebtConfigurationRule debtConfiguration = DebtConfigurationRule.create(orchestrator); @Before public void deleteAnalysisData() { orchestrator.resetData(); // Set hours in day property to 8 - setServerProperty(orchestrator, "sonar.technicalDebt.hoursInDay", "8"); + debtConfiguration.updateHoursInDay(8); } @Test @@ -96,7 +93,7 @@ public class TechnicalDebtInIssueChangelogTest { orchestrator.executeBuild(SonarRunner.create(projectDir("shared/xoo-sample"))); // One day -> 10 hours - setServerProperty(orchestrator, "sonar.technicalDebt.hoursInDay", "10"); + debtConfiguration.updateHoursInDay(10); orchestrator.executeBuild(SonarRunner.create(projectDir("shared/xoo-sample")) // As OneIssuePerFile has a debt of 10 minutes, we multiply it by 72 to have 1 day and 2 hours of technical debtn diff --git a/it/it-tests/src/test/java/it/debt/TechnicalDebtTest.java b/it/it-tests/src/test/java/it/debt/TechnicalDebtTest.java index 9522ee9458f..933a698ae6a 100644 --- a/it/it-tests/src/test/java/it/debt/TechnicalDebtTest.java +++ b/it/it-tests/src/test/java/it/debt/TechnicalDebtTest.java @@ -24,9 +24,9 @@ import com.sonar.orchestrator.build.SonarRunner; import com.sonar.orchestrator.locator.FileLocation; import it.Category2Suite; import java.util.List; -import org.junit.AfterClass; import org.junit.Before; import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; import org.sonar.wsclient.issue.Issue; import org.sonar.wsclient.issue.IssueClient; @@ -34,23 +34,21 @@ import org.sonar.wsclient.issue.IssueQuery; import static org.assertj.core.api.Assertions.assertThat; import static util.ItUtils.projectDir; -import static util.ItUtils.setServerProperty; public class TechnicalDebtTest { @ClassRule public static Orchestrator orchestrator = Category2Suite.ORCHESTRATOR; - @AfterClass - public static void resetHoursInDay() throws Exception { - setServerProperty(orchestrator, "sonar.technicalDebt.hoursInDay", null); - } + @Rule + public DebtConfigurationRule debtConfiguration = DebtConfigurationRule.create(orchestrator); @Before public void deleteAnalysisData() { orchestrator.resetData(); + // Set hours in day property to 8 - setServerProperty(orchestrator, "sonar.technicalDebt.hoursInDay", "8"); + debtConfiguration.updateHoursInDay(8); } /** @@ -80,7 +78,7 @@ public class TechnicalDebtTest { orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-file"); // One day -> 10 hours - setServerProperty(orchestrator, "sonar.technicalDebt.hoursInDay", "10"); + debtConfiguration.updateHoursInDay(10); orchestrator.executeBuild(SonarRunner.create(projectDir("shared/xoo-sample")) // As OneIssuePerFile has a debt of 10 minutes, we multiply it by 72 to have 1 day and 2 hours of technical debt @@ -100,13 +98,13 @@ public class TechnicalDebtTest { orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-day-debt-per-file"); // One day -> 10 hours : debt will be stored as 360.000 seconds (1 day * 10 hours per day * 60 * 60) - setServerProperty(orchestrator, "sonar.technicalDebt.hoursInDay", "10"); + debtConfiguration.updateHoursInDay(10); orchestrator.executeBuild(SonarRunner.create(projectDir("shared/xoo-sample"))); // Issue debt was 1 day during analysis but will be displayed as 1 day and 2 hours (hours in day property was set // to 10 during analysis but is now 8) - setServerProperty(orchestrator, "sonar.technicalDebt.hoursInDay", "8"); + debtConfiguration.updateHoursInDay(8); IssueClient issueClient = orchestrator.getServer().wsClient().issueClient(); Issue issue = issueClient.find(IssueQuery.create()).list().get(0); diff --git a/it/it-tests/src/test/java/it/debt/TechnicalDebtWidgetTest.java b/it/it-tests/src/test/java/it/debt/TechnicalDebtWidgetTest.java index a9d9df0f6e7..4d15720fa1f 100644 --- a/it/it-tests/src/test/java/it/debt/TechnicalDebtWidgetTest.java +++ b/it/it-tests/src/test/java/it/debt/TechnicalDebtWidgetTest.java @@ -36,10 +36,16 @@ public class TechnicalDebtWidgetTest { @ClassRule public static Orchestrator orchestrator = Category2Suite.ORCHESTRATOR; + @ClassRule + public static DebtConfigurationRule debtConfiguration = DebtConfigurationRule.create(orchestrator); + @BeforeClass public static void init() { orchestrator.resetData(); + // Set rating grid values to not depend from default value + debtConfiguration.updateRatingGrid(0.1d, 0.2d, 0.5d, 1d); + orchestrator.getServer().restoreProfile(FileLocation.ofClasspath("/debt/with-many-rules.xml")); orchestrator.getServer().provisionProject("com.sonarsource.it.samples:multi-modules-sample", "com.sonarsource.it.samples:multi-modules-sample"); orchestrator.getServer().associateProjectToQualityProfile("com.sonarsource.it.samples:multi-modules-sample", "xoo", "with-many-rules"); diff --git a/sonar-core/src/main/java/org/sonar/core/config/DebtProperties.java b/sonar-core/src/main/java/org/sonar/core/config/DebtProperties.java index 95008f6d659..68cfd50399a 100644 --- a/sonar-core/src/main/java/org/sonar/core/config/DebtProperties.java +++ b/sonar-core/src/main/java/org/sonar/core/config/DebtProperties.java @@ -57,9 +57,9 @@ class DebtProperties { .name("Rating grid") .description("SQALE ratings range from A (very good) to E (very bad). The rating is determined by the value of " + "the Technical Debt Ratio, which compares the technical debt on a project to the cost it would take to rewrite " + - "the code from scratch. The default values for A through D are 0.1,0.2,0.5,1. Anything over 1 is an E. " + + "the code from scratch. The default values for A through D are 0.05,0.1,0.2,0.5. Anything over 0.5 is an E. " + "Example: assuming the development cost is 30 minutes, a project with a technical debt of 24,000 minutes for " + - "2,500 LOC will have a technical debt ratio of 24000/(30 * 2,500) = 0.32. That yields a SQALE rating of C.") + "2,500 LOC will have a technical debt ratio of 24000/(30 * 2,500) = 0.32. That yields a SQALE rating of D.") .category(CoreProperties.CATEGORY_TECHNICAL_DEBT) .deprecatedKey("ratingGrid") .build(), diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java b/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java index c1bbad7271b..a9a017f3c1a 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java @@ -499,7 +499,7 @@ public interface CoreProperties { /** * @since 4.5 */ - String RATING_GRID_DEF_VALUES = "0.1,0.2,0.5,1"; + String RATING_GRID_DEF_VALUES = "0.05,0.1,0.2,0.5"; /** * @since 4.5 -- 2.39.5