aboutsummaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2014-03-11 08:09:01 +0100
committerJulien Lancelot <julien.lancelot@sonarsource.com>2014-03-11 08:09:01 +0100
commitdce23fcf9ac907f6621ab0c11c397febff280ebc (patch)
treef819d4a7216d35389a3063b0f0a96cde49cb62db /plugins
parent1ffa320fb3e44cdaf635678a04c473ca4f348514 (diff)
downloadsonarqube-dce23fcf9ac907f6621ab0c11c397febff280ebc.tar.gz
sonarqube-dce23fcf9ac907f6621ab0c11c397febff280ebc.zip
SONAR-5056 Read debt from rule during analysis
Diffstat (limited to 'plugins')
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecorator.java91
-rw-r--r--plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecoratorTest.java151
2 files changed, 128 insertions, 114 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecorator.java
index 8d4c893f436..359f348cc7c 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecorator.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecorator.java
@@ -24,10 +24,12 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ListMultimap;
-import org.slf4j.LoggerFactory;
import org.sonar.api.CoreProperties;
import org.sonar.api.PropertyType;
import org.sonar.api.batch.*;
+import org.sonar.api.batch.rule.Rule;
+import org.sonar.api.batch.rule.Rules;
+import org.sonar.api.batch.rule.internal.DefaultRule;
import org.sonar.api.component.ResourcePerspectives;
import org.sonar.api.config.PropertyDefinition;
import org.sonar.api.issue.Issuable;
@@ -37,10 +39,13 @@ import org.sonar.api.measures.*;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.resources.ResourceUtils;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rules.RulePriority;
import org.sonar.api.technicaldebt.batch.Characteristic;
-import org.sonar.api.technicaldebt.batch.Requirement;
import org.sonar.api.technicaldebt.batch.TechnicalDebtModel;
+import javax.annotation.Nullable;
+
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
@@ -57,10 +62,12 @@ public final class TechnicalDebtDecorator implements Decorator {
private final ResourcePerspectives perspectives;
private final TechnicalDebtModel model;
+ private final Rules rules;
- public TechnicalDebtDecorator(ResourcePerspectives perspectives, TechnicalDebtModel model) {
+ public TechnicalDebtDecorator(ResourcePerspectives perspectives, TechnicalDebtModel model, Rules rules) {
this.perspectives = perspectives;
this.model = model;
+ this.rules = rules;
}
public boolean shouldExecuteOnProject(Project project) {
@@ -81,25 +88,29 @@ public final class TechnicalDebtDecorator implements Decorator {
}
private void saveMeasures(DecoratorContext context, List<Issue> issues) {
- // group issues by requirement
- ListMultimap<Requirement, Issue> issuesByRequirement = issuesByRequirement(issues);
+ // group issues by rules
+ ListMultimap<Rule, Issue> issuesByRule = issuesByRule(issues);
double total = 0.0;
Map<Characteristic, Double> characteristicCosts = newHashMap();
- Map<Requirement, Double> requirementCosts = newHashMap();
-
- for (Requirement requirement : model.requirements()) {
- List<Issue> requirementIssues = issuesByRequirement.get(requirement);
- double value = computeTechnicalDebt(CoreMetrics.TECHNICAL_DEBT, context, requirement, requirementIssues);
-
- requirementCosts.put(requirement, value);
- total += value;
- propagateTechnicalDebtInParents(requirement.characteristic(), value, characteristicCosts);
+ Map<Rule, Double> ruleDebtCosts = newHashMap();
+
+ for (Rule rule : rules.findAll()) {
+ String characteristicKey = rule.characteristic();
+ if (characteristicKey != null) {
+ List<Issue> requirementIssues = issuesByRule.get(rule);
+ double value = computeTechnicalDebt(CoreMetrics.TECHNICAL_DEBT, context, rule, requirementIssues);
+
+ ruleDebtCosts.put(rule, value);
+ total += value;
+ Characteristic characteristic = model.characteristicByKey(characteristicKey);
+ propagateTechnicalDebtInParents(characteristic, value, characteristicCosts);
+ }
}
context.saveMeasure(CoreMetrics.TECHNICAL_DEBT, total);
saveOnCharacteristic(context, characteristicCosts);
- saveOnRequirement(context, requirementCosts);
+ saveOnRequirement(context, ruleDebtCosts);
}
private void saveOnCharacteristic(DecoratorContext context, Map<Characteristic, Double> characteristicCosts) {
@@ -108,8 +119,8 @@ public final class TechnicalDebtDecorator implements Decorator {
}
}
- private void saveOnRequirement(DecoratorContext context, Map<Requirement, Double> requirementCosts) {
- for (Map.Entry<Requirement, Double> entry : requirementCosts.entrySet()) {
+ private void saveOnRequirement(DecoratorContext context, Map<Rule, Double> requirementCosts) {
+ for (Map.Entry<Rule, Double> entry : requirementCosts.entrySet()) {
saveTechnicalDebt(context, entry.getKey(), entry.getValue(), ResourceUtils.isEntity(context.getResource()));
}
}
@@ -126,17 +137,17 @@ public final class TechnicalDebtDecorator implements Decorator {
}
@VisibleForTesting
- void saveTechnicalDebt(DecoratorContext context, Requirement requirement, Double value, boolean inMemory) {
+ void saveTechnicalDebt(DecoratorContext context, Rule rule, Double value, boolean inMemory) {
// we need the value on projects (root or module) even if value==0 in order to display correctly the SQALE history chart (see SQALE-122)
// BUT we don't want to save zero-values for non top-characteristics (see SQALE-147)
if (value > 0.0) {
- Measure measure = new Measure(CoreMetrics.TECHNICAL_DEBT);
- measure.setRequirement(requirement);
+ org.sonar.api.rules.Rule oldRule = toOldRule(rule);
+ RuleMeasure measure = new RuleMeasure(CoreMetrics.TECHNICAL_DEBT, oldRule, oldRule.getSeverity(), null);
saveMeasure(context, measure, value, inMemory);
}
}
- private void saveMeasure(DecoratorContext context, Measure measure, Double value, boolean inMemory){
+ private void saveMeasure(DecoratorContext context, Measure measure, Double value, boolean inMemory) {
measure.setValue(value);
if (inMemory) {
measure.setPersistenceMode(PersistenceMode.MEMORY);
@@ -145,22 +156,17 @@ public final class TechnicalDebtDecorator implements Decorator {
}
@VisibleForTesting
- ListMultimap<Requirement, Issue> issuesByRequirement(List<Issue> issues) {
- ListMultimap<Requirement, Issue> issuesByRequirement = ArrayListMultimap.create();
+ ListMultimap<Rule, Issue> issuesByRule(List<Issue> issues) {
+ ListMultimap<Rule, Issue> result = ArrayListMultimap.create();
for (Issue issue : issues) {
- String repositoryKey = issue.ruleKey().repository();
- String key = issue.ruleKey().rule();
- Requirement requirement = model.requirementsByRule(issue.ruleKey());
- if (requirement == null) {
- LoggerFactory.getLogger(getClass()).debug("No technical debt requirement for: " + repositoryKey + "/" + key);
- } else {
- issuesByRequirement.put(requirement, issue);
- }
+ RuleKey key = issue.ruleKey();
+ Rule rule = rules.find(key);
+ result.put(rule, issue);
}
- return issuesByRequirement;
+ return result;
}
- private double computeTechnicalDebt(Metric metric, DecoratorContext context, Requirement requirement, Collection<Issue> issues) {
+ private double computeTechnicalDebt(Metric metric, DecoratorContext context, Rule rule, Collection<Issue> issues) {
long debt = 0L;
if (issues != null) {
for (Issue issue : issues) {
@@ -171,16 +177,18 @@ public final class TechnicalDebtDecorator implements Decorator {
}
}
- for (Measure measure : context.getChildrenMeasures(MeasuresFilters.requirement(metric, requirement))) {
- Requirement measureRequirement = measure.getRequirement();
- if (measureRequirement != null && measureRequirement.equals(requirement) && measure.getValue() != null) {
+ org.sonar.api.rules.Rule oldRule = toOldRule(rule);
+ for (Measure measure : context.getChildrenMeasures(MeasuresFilters.rule(metric, oldRule))) {
+ // Comparison on rule is only used for unit test, otherwise no need to do this check
+ RuleMeasure ruleMeasure = (RuleMeasure) measure;
+ if (measure != null && ruleMeasure.getRule().equals(oldRule) && measure.getValue() != null) {
debt += measure.getValue();
}
}
return debt;
}
- private void propagateTechnicalDebtInParents(Characteristic characteristic, double value, Map<Characteristic, Double> characteristicCosts) {
+ private void propagateTechnicalDebtInParents(@Nullable Characteristic characteristic, double value, Map<Characteristic, Double> characteristicCosts) {
if (characteristic != null) {
Double parentCost = characteristicCosts.get(characteristic);
if (parentCost == null) {
@@ -207,4 +215,13 @@ public final class TechnicalDebtDecorator implements Decorator {
.build()
);
}
+
+ private org.sonar.api.rules.Rule toOldRule(Rule rule) {
+ DefaultRule defaultRule = (DefaultRule) rule;
+ org.sonar.api.rules.Rule oldRule = org.sonar.api.rules.Rule.create(rule.key().repository(), rule.key().rule());
+ oldRule.setSeverity(RulePriority.valueOf(rule.severity()));
+ oldRule.setId(defaultRule.id());
+ return oldRule;
+ }
+
}
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecoratorTest.java
index 248e2921192..cc98836f049 100644
--- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecoratorTest.java
+++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecoratorTest.java
@@ -32,23 +32,21 @@ import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.sonar.api.batch.DecoratorContext;
+import org.sonar.api.batch.rule.Rule;
+import org.sonar.api.batch.rule.Rules;
+import org.sonar.api.batch.rule.internal.RulesBuilder;
import org.sonar.api.component.ResourcePerspectives;
import org.sonar.api.issue.Issuable;
import org.sonar.api.issue.Issue;
import org.sonar.api.issue.internal.DefaultIssue;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.MeasuresFilter;
-import org.sonar.api.measures.Metric;
+import org.sonar.api.measures.*;
import org.sonar.api.resources.File;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.technicaldebt.batch.Characteristic;
-import org.sonar.api.technicaldebt.batch.Requirement;
import org.sonar.api.technicaldebt.batch.TechnicalDebtModel;
import org.sonar.api.technicaldebt.batch.internal.DefaultCharacteristic;
-import org.sonar.api.technicaldebt.batch.internal.DefaultRequirement;
import org.sonar.api.test.IsMeasure;
import org.sonar.api.utils.Duration;
@@ -78,14 +76,24 @@ public class TechnicalDebtDecoratorTest {
@Mock
Issuable issuable;
+ @Mock
+ ResourcePerspectives perspectives;
+
+ RuleKey ruleKey1 = RuleKey.of("repo1", "rule1");
+ RuleKey ruleKey2 = RuleKey.of("repo2", "rule2");
+ Rules rules;
+
TechnicalDebtDecorator decorator;
@Before
public void before() throws Exception {
- ResourcePerspectives perspectives = mock(ResourcePerspectives.class);
when(perspectives.as(Issuable.class, resource)).thenReturn(issuable);
+ RulesBuilder rulesBuilder = new RulesBuilder();
+ rulesBuilder.add(ruleKey1).setName("rule1").setCharacteristic("MEMORY_EFFICIENCY");
+ rulesBuilder.add(ruleKey2).setName("rule2").setCharacteristic("MODULARITY");
+ rules = rulesBuilder.build();
- decorator = new TechnicalDebtDecorator(perspectives, defaultTechnicalDebtModel);
+ decorator = new TechnicalDebtDecorator(perspectives, defaultTechnicalDebtModel, rules);
}
@Test
@@ -109,24 +117,17 @@ public class TechnicalDebtDecoratorTest {
@Test
public void group_issues_by_requirement() throws Exception {
- Requirement requirement1 = mock(Requirement.class);
- Requirement requirement2 = mock(Requirement.class);
-
Issue issue1 = createIssue("rule1", "repo1");
Issue issue2 = createIssue("rule1", "repo1");
Issue issue3 = createIssue("rule2", "repo2");
- Issue issue4 = createIssue("unmatchable", "repo2");
-
- List<Issue> issues = newArrayList(issue1, issue2, issue3, issue4);
- when(defaultTechnicalDebtModel.requirementsByRule(RuleKey.of("repo1", "rule1"))).thenReturn(requirement1);
- when(defaultTechnicalDebtModel.requirementsByRule(RuleKey.of("repo2", "rule2"))).thenReturn(requirement2);
+ List<Issue> issues = newArrayList(issue1, issue2, issue3);
- ListMultimap<Requirement, Issue> result = decorator.issuesByRequirement(issues);
+ ListMultimap<Rule, Issue> result = decorator.issuesByRule(issues);
assertThat(result.keySet().size()).isEqualTo(2);
- assertThat(result.get(requirement1)).containsExactly(issue1, issue2);
- assertThat(result.get(requirement2)).containsExactly(issue3);
+ assertThat(result.get(rules.find(ruleKey1))).containsExactly(issue1, issue2);
+ assertThat(result.get(rules.find(ruleKey2))).containsExactly(issue3);
}
@Test
@@ -134,14 +135,10 @@ public class TechnicalDebtDecoratorTest {
Issue issue = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES));
when(issuable.issues()).thenReturn(newArrayList(issue));
- Requirement requirement = mock(Requirement.class);
- when(defaultTechnicalDebtModel.requirementsByRule(RuleKey.of("repo1", "rule1"))).thenReturn(requirement);
- doReturn(newArrayList(requirement)).when(defaultTechnicalDebtModel).requirements();
-
decorator.decorate(resource, context);
verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, ONE_DAY_IN_MINUTES.doubleValue());
- verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, null, requirement, ONE_DAY_IN_MINUTES.doubleValue())));
+ verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, ONE_DAY_IN_MINUTES.doubleValue())));
}
@Test
@@ -149,10 +146,6 @@ public class TechnicalDebtDecoratorTest {
Issue issue = createIssue("rule1", "repo1").setDebt(null);
when(issuable.issues()).thenReturn(newArrayList(issue));
- Requirement requirement = mock(Requirement.class);
- when(defaultTechnicalDebtModel.requirementsByRule(RuleKey.of("repo1", "rule1"))).thenReturn(requirement);
- doReturn(newArrayList(requirement)).when(defaultTechnicalDebtModel).requirements();
-
decorator.decorate(resource, context);
verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 0.0);
@@ -163,20 +156,16 @@ public class TechnicalDebtDecoratorTest {
Issue issue = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES));
when(issuable.issues()).thenReturn(newArrayList(issue));
- DefaultCharacteristic parentCharacteristic = new DefaultCharacteristic().setKey("parentCharacteristic");
- DefaultCharacteristic characteristic = new DefaultCharacteristic().setKey("characteristic").setParent(parentCharacteristic);
- RuleKey ruleKey = RuleKey.of("repo1", "rule1");
- DefaultRequirement requirement = new DefaultRequirement().setCharacteristic(characteristic).setRuleKey(ruleKey);
-
- when(defaultTechnicalDebtModel.requirementsByRule(ruleKey)).thenReturn(requirement);
- doReturn(newArrayList(requirement)).when(defaultTechnicalDebtModel).requirements();
+ DefaultCharacteristic parentCharacteristic = new DefaultCharacteristic().setKey("EFFICIENCY");
+ DefaultCharacteristic characteristic = new DefaultCharacteristic().setKey("MEMORY_EFFICIENCY").setParent(parentCharacteristic);
+ when(defaultTechnicalDebtModel.characteristicByKey("MEMORY_EFFICIENCY")).thenReturn(characteristic);
decorator.decorate(resource, context);
verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, ONE_DAY_IN_MINUTES.doubleValue());
verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, parentCharacteristic, ONE_DAY_IN_MINUTES.doubleValue())));
verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, characteristic, ONE_DAY_IN_MINUTES.doubleValue())));
- verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, requirement, ONE_DAY_IN_MINUTES.doubleValue())));
+ verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, ONE_DAY_IN_MINUTES.doubleValue())));
}
@Test
@@ -190,22 +179,20 @@ public class TechnicalDebtDecoratorTest {
Issue issue4 = createIssue("rule2", "repo2").setDebt(Duration.create(technicalDebt2));
when(issuable.issues()).thenReturn(newArrayList(issue1, issue2, issue3, issue4));
- DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic().setKey("rootCharacteristic");
- DefaultCharacteristic characteristic = new DefaultCharacteristic().setKey("characteristic").setParent(rootCharacteristic);
- RuleKey ruleKey1 = RuleKey.of("repo1", "rule1");
- DefaultRequirement requirement1 = new DefaultRequirement().setRuleKey(ruleKey1).setCharacteristic(characteristic);
- RuleKey ruleKey2 = RuleKey.of("repo2", "rule2");
- DefaultRequirement requirement2 = new DefaultRequirement().setRuleKey(ruleKey2).setCharacteristic(characteristic);
-
- when(defaultTechnicalDebtModel.requirementsByRule(ruleKey1)).thenReturn(requirement1);
- when(defaultTechnicalDebtModel.requirementsByRule(ruleKey2)).thenReturn(requirement2);
- doReturn(newArrayList(requirement1, requirement2)).when(defaultTechnicalDebtModel).requirements();
+ when(defaultTechnicalDebtModel.characteristicByKey("MEMORY_EFFICIENCY")).thenReturn(
+ new DefaultCharacteristic().setKey("MEMORY_EFFICIENCY").setParent(
+ new DefaultCharacteristic().setKey("EFFICIENCY")
+ ),
+ new DefaultCharacteristic().setKey("MODULARITY").setParent(
+ new DefaultCharacteristic().setKey("REUSABILITY")
+ )
+ );
decorator.decorate(resource, context);
verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 6d * ONE_DAY_IN_MINUTES);
- verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, requirement1, 2d * ONE_DAY_IN_MINUTES)));
- verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, requirement2, 4d * ONE_DAY_IN_MINUTES)));
+ verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, 2d * ONE_DAY_IN_MINUTES)));
+ verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey2, 4d * ONE_DAY_IN_MINUTES)));
}
@Test
@@ -214,21 +201,20 @@ public class TechnicalDebtDecoratorTest {
Issue issue2 = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES));
when(issuable.issues()).thenReturn(newArrayList(issue1, issue2));
- DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic().setKey("rootCharacteristic");
- DefaultCharacteristic characteristic = new DefaultCharacteristic().setKey("characteristic").setParent(rootCharacteristic);
- RuleKey ruleKey1 = RuleKey.of("repo1", "rule1");
- DefaultRequirement requirement = new DefaultRequirement().setRuleKey(ruleKey1).setCharacteristic(characteristic);
+ when(defaultTechnicalDebtModel.characteristicByKey("MEMORY_EFFICIENCY")).thenReturn(
+ new DefaultCharacteristic().setKey("MEMORY_EFFICIENCY").setParent(
+ new DefaultCharacteristic().setKey("EFFICIENCY")
+ )
+ );
- when(defaultTechnicalDebtModel.requirementsByRule(ruleKey1)).thenReturn(requirement);
- doReturn(newArrayList(requirement)).when(defaultTechnicalDebtModel).requirements();
-
- Measure measure = new Measure().setRequirement(requirement).setValue(5d * ONE_DAY_IN_MINUTES);
+ org.sonar.api.rules.Rule oldRule = org.sonar.api.rules.Rule.create(ruleKey1.repository(), ruleKey1.rule());
+ Measure measure = new RuleMeasure(CoreMetrics.TECHNICAL_DEBT, oldRule, null, null).setValue(5d * ONE_DAY_IN_MINUTES);
when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(newArrayList(measure));
decorator.decorate(resource, context);
verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 7d * ONE_DAY_IN_MINUTES);
- verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, requirement, 7d * ONE_DAY_IN_MINUTES)));
+ verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, 7d * ONE_DAY_IN_MINUTES)));
}
@Test
@@ -265,8 +251,8 @@ public class TechnicalDebtDecoratorTest {
DecoratorContext context = mock(DecoratorContext.class);
when(context.getResource()).thenReturn(new Project("foo"));
- DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic().setKey("rootCharacteristic");
- DefaultCharacteristic characteristic = new DefaultCharacteristic().setKey("characteristic").setParent(rootCharacteristic);
+ DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic().setKey("EFFICIENCY");
+ DefaultCharacteristic characteristic = new DefaultCharacteristic().setKey("MEMORY_EFFICIENCY").setParent(rootCharacteristic);
decorator.saveTechnicalDebt(context, characteristic, 0.0, true);
verify(context, never()).saveMeasure(any(Measure.class));
@@ -293,34 +279,17 @@ public class TechnicalDebtDecoratorTest {
class IsCharacteristicMeasure extends ArgumentMatcher<Measure> {
Metric metric = null;
Characteristic characteristic = null;
- Requirement requirement = null;
Double value = null;
- public IsCharacteristicMeasure(Metric metric, Characteristic characteristic, Requirement requirement, Double value) {
- this.metric = metric;
- this.characteristic = characteristic;
- this.requirement = requirement;
- this.value = value;
- }
-
public IsCharacteristicMeasure(Metric metric, Characteristic characteristic, Double value) {
this.metric = metric;
this.characteristic = characteristic;
- this.requirement = null;
- this.value = value;
- }
-
- public IsCharacteristicMeasure(Metric metric, Requirement requirement, Double value) {
- this.metric = metric;
- this.characteristic = null;
- this.requirement = requirement;
this.value = value;
}
public IsCharacteristicMeasure(Metric metric, Double value) {
this.metric = metric;
this.characteristic = null;
- this.requirement = null;
this.value = value;
}
@@ -332,7 +301,35 @@ public class TechnicalDebtDecoratorTest {
Measure m = (Measure) o;
return ObjectUtils.equals(metric, m.getMetric()) &&
ObjectUtils.equals(characteristic, m.getCharacteristic()) &&
- ObjectUtils.equals(requirement, m.getRequirement()) &&
+ ObjectUtils.equals(value, m.getValue());
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE));
+ }
+ }
+
+ class IsRuleMeasure extends ArgumentMatcher<RuleMeasure> {
+ Metric metric = null;
+ RuleKey ruleKey = null;
+ Double value = null;
+
+ public IsRuleMeasure(Metric metric, RuleKey ruleKey, Double value) {
+ this.metric = metric;
+ this.ruleKey = ruleKey;
+ this.value = value;
+ }
+
+ @Override
+ public boolean matches(Object o) {
+ if (!(o instanceof RuleMeasure)) {
+ return false;
+ }
+ RuleMeasure m = (RuleMeasure) o;
+ return ObjectUtils.equals(metric, m.getMetric()) &&
+ ObjectUtils.equals(ruleKey.repository(), m.getRule().getRepositoryKey()) &&
+ ObjectUtils.equals(ruleKey.rule(), m.getRule().getKey()) &&
ObjectUtils.equals(value, m.getValue());
}