3 * Copyright (C) 2009-2024 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.server.measure.live;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.LinkedList;
27 import java.util.List;
29 import java.util.Optional;
31 import javax.annotation.Nullable;
32 import org.junit.Test;
33 import org.sonar.api.issue.Issue;
34 import org.sonar.api.measures.CoreMetrics;
35 import org.sonar.api.measures.Metric;
36 import org.sonar.api.rule.Severity;
37 import org.sonar.api.rules.RuleType;
38 import org.sonar.db.component.ComponentDto;
39 import org.sonar.db.issue.IssueGroupDto;
40 import org.sonar.server.measure.DebtRatingGrid;
41 import org.sonar.server.measure.Rating;
43 import static java.util.Arrays.asList;
44 import static org.assertj.core.api.Assertions.assertThat;
45 import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED;
46 import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS;
47 import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS;
48 import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_REVIEW_RATING;
49 import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_REVIEWED;
50 import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_STATUS;
51 import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_TO_REVIEW_STATUS;
52 import static org.sonar.api.measures.CoreMetrics.SECURITY_REVIEW_RATING;
54 public class MeasureUpdateFormulaFactoryImplTest {
56 private final MeasureUpdateFormulaFactoryImpl underTest = new MeasureUpdateFormulaFactoryImpl();
59 public void getFormulaMetrics_include_the_dependent_metrics() {
60 for (MeasureUpdateFormula formula : underTest.getFormulas()) {
61 assertThat(underTest.getFormulaMetrics()).contains(formula.getMetric());
62 for (Metric<?> dependentMetric : formula.getDependentMetrics()) {
63 assertThat(underTest.getFormulaMetrics()).contains(dependentMetric);
69 public void hierarchy_adding_numbers() {
70 new HierarchyTester(CoreMetrics.VIOLATIONS)
72 .withChildrenValues(2d, 3d)
75 new HierarchyTester(CoreMetrics.BUGS)
77 .withChildrenValues(2d, 3d)
80 new HierarchyTester(CoreMetrics.NEW_BUGS)
86 public void hierarchy_highest_rating() {
87 new HierarchyTester(CoreMetrics.RELIABILITY_RATING)
89 .withChildrenValues(2d, 3d)
90 .expectedRating(Rating.C);
92 // if no children, no need to set a value
93 new HierarchyTester(CoreMetrics.SECURITY_RATING)
95 .expectedResult(null);
97 new HierarchyTester(CoreMetrics.NEW_RELIABILITY_RATING)
99 .withChildrenValues(2d, 3d)
100 .expectedRating(Rating.E);
104 public void hierarchy_combining_other_metrics() {
105 new HierarchyTester(SECURITY_HOTSPOTS_TO_REVIEW_STATUS)
106 .withValue(SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 1d)
107 .withChildrenHotspotsCounts(10, 10, 2, 10)
110 new HierarchyTester(SECURITY_HOTSPOTS_REVIEWED_STATUS)
111 .withValue(SECURITY_HOTSPOTS_REVIEWED_STATUS, 1d)
112 .withChildrenHotspotsCounts(2, 10, 10, 10)
115 new HierarchyTester(NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS)
116 .withValue(NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 1d)
117 .withChildrenHotspotsCounts(10, 10, 10, 2)
120 new HierarchyTester(NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS)
121 .withValue(NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS, 1d)
122 .withChildrenHotspotsCounts(10, 2, 10, 10)
125 new HierarchyTester(CoreMetrics.SECURITY_HOTSPOTS_REVIEWED)
126 .withValue(SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 1d)
127 .withValue(SECURITY_HOTSPOTS_REVIEWED_STATUS, 1d)
128 .expectedResult(50d);
129 new HierarchyTester(CoreMetrics.SECURITY_REVIEW_RATING)
130 .withValue(SECURITY_HOTSPOTS_REVIEWED, 100d)
131 .expectedRating(Rating.A);
133 new HierarchyTester(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED)
134 .withValue(NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 1d)
135 .withValue(NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS, 1d)
136 .expectedResult(50d);
137 new HierarchyTester(CoreMetrics.NEW_SECURITY_REVIEW_RATING)
138 .withValue(NEW_SECURITY_HOTSPOTS_REVIEWED, 0d)
139 .expectedRating(Rating.E);
143 public void test_violations() {
144 withNoIssues().assertThatValueIs(CoreMetrics.VIOLATIONS, 0);
145 with(newGroup(), newGroup().setCount(4)).assertThatValueIs(CoreMetrics.VIOLATIONS, 5);
148 IssueGroupDto resolved = newResolvedGroup(Issue.RESOLUTION_FIXED, Issue.STATUS_RESOLVED);
149 with(newGroup(), newGroup(), resolved).assertThatValueIs(CoreMetrics.VIOLATIONS, 2);
151 // include issues on leak
152 IssueGroupDto onLeak = newGroup().setCount(11).setInLeak(true);
153 with(newGroup(), newGroup(), onLeak).assertThatValueIs(CoreMetrics.VIOLATIONS, 1 + 1 + 11);
157 public void test_bugs() {
158 withNoIssues().assertThatValueIs(CoreMetrics.BUGS, 0);
160 newGroup(RuleType.BUG).setSeverity(Severity.MAJOR).setCount(3),
161 newGroup(RuleType.BUG).setSeverity(Severity.CRITICAL).setCount(5),
163 newResolvedGroup(RuleType.BUG).setCount(7),
165 newGroup(RuleType.CODE_SMELL).setCount(11))
166 .assertThatValueIs(CoreMetrics.BUGS, 3 + 5);
170 public void test_code_smells() {
171 withNoIssues().assertThatValueIs(CoreMetrics.CODE_SMELLS, 0);
173 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MAJOR).setCount(3),
174 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.CRITICAL).setCount(5),
176 newResolvedGroup(RuleType.CODE_SMELL).setCount(7),
178 newGroup(RuleType.BUG).setCount(11))
179 .assertThatValueIs(CoreMetrics.CODE_SMELLS, 3 + 5);
183 public void test_vulnerabilities() {
184 withNoIssues().assertThatValueIs(CoreMetrics.VULNERABILITIES, 0);
186 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.MAJOR).setCount(3),
187 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.CRITICAL).setCount(5),
189 newResolvedGroup(RuleType.VULNERABILITY).setCount(7),
190 // not vulnerabilities
191 newGroup(RuleType.BUG).setCount(11))
192 .assertThatValueIs(CoreMetrics.VULNERABILITIES, 3 + 5);
196 public void test_security_hotspots() {
197 withNoIssues().assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS, 0);
199 newGroup(RuleType.SECURITY_HOTSPOT).setSeverity(Severity.MAJOR).setCount(3),
200 newGroup(RuleType.SECURITY_HOTSPOT).setSeverity(Severity.CRITICAL).setCount(5),
202 newResolvedGroup(RuleType.SECURITY_HOTSPOT).setCount(7),
204 newGroup(RuleType.BUG).setCount(11))
205 .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS, 3 + 5);
209 public void test_security_review_rating() {
211 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3),
212 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1))
213 .assertThatValueIs(SECURITY_REVIEW_RATING, Rating.B);
216 .assertThatValueIs(SECURITY_REVIEW_RATING, Rating.A);
220 public void test_security_hotspots_reviewed() {
222 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3),
223 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1))
224 .assertThatValueIs(SECURITY_HOTSPOTS_REVIEWED, 75.0);
227 .assertNoValue(SECURITY_HOTSPOTS_REVIEWED);
231 public void test_security_hotspots_reviewed_status() {
233 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3),
234 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1))
235 .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_STATUS, 3.0);
238 .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_STATUS, 0.0);
242 public void test_security_hotspots_to_review_status() {
244 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3),
245 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1))
246 .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 1.0);
249 .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 0.0);
253 public void count_unresolved_by_severity() {
255 .assertThatValueIs(CoreMetrics.BLOCKER_VIOLATIONS, 0)
256 .assertThatValueIs(CoreMetrics.CRITICAL_VIOLATIONS, 0)
257 .assertThatValueIs(CoreMetrics.MAJOR_VIOLATIONS, 0)
258 .assertThatValueIs(CoreMetrics.MINOR_VIOLATIONS, 0)
259 .assertThatValueIs(CoreMetrics.INFO_VIOLATIONS, 0);
262 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.MAJOR).setCount(3),
263 newGroup(RuleType.BUG).setSeverity(Severity.MAJOR).setCount(5),
264 newGroup(RuleType.BUG).setSeverity(Severity.CRITICAL).setCount(7),
265 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setCount(11),
266 // exclude security hotspot
267 newGroup(RuleType.SECURITY_HOTSPOT).setSeverity(Severity.CRITICAL).setCount(15),
269 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setInLeak(true).setCount(13),
271 newResolvedGroup(RuleType.VULNERABILITY).setSeverity(Severity.INFO).setCount(17),
272 newResolvedGroup(RuleType.BUG).setSeverity(Severity.MAJOR).setCount(19),
273 newResolvedGroup(RuleType.SECURITY_HOTSPOT).setSeverity(Severity.INFO).setCount(21))
274 .assertThatValueIs(CoreMetrics.BLOCKER_VIOLATIONS, 11 + 13)
275 .assertThatValueIs(CoreMetrics.CRITICAL_VIOLATIONS, 7)
276 .assertThatValueIs(CoreMetrics.MAJOR_VIOLATIONS, 3 + 5)
277 .assertThatValueIs(CoreMetrics.MINOR_VIOLATIONS, 0)
278 .assertThatValueIs(CoreMetrics.INFO_VIOLATIONS, 0);
282 public void count_resolved() {
284 .assertThatValueIs(CoreMetrics.FALSE_POSITIVE_ISSUES, 0)
285 .assertThatValueIs(CoreMetrics.ACCEPTED_ISSUES, 0);
288 newResolvedGroup(Issue.RESOLUTION_FIXED, Issue.STATUS_RESOLVED).setCount(3),
289 newResolvedGroup(Issue.RESOLUTION_FALSE_POSITIVE, Issue.STATUS_CLOSED).setCount(5),
290 newResolvedGroup(Issue.RESOLUTION_WONT_FIX, Issue.STATUS_CLOSED).setSeverity(Severity.MAJOR).setCount(7),
291 newResolvedGroup(Issue.RESOLUTION_WONT_FIX, Issue.STATUS_CLOSED).setSeverity(Severity.BLOCKER).setCount(11),
292 newResolvedGroup(Issue.RESOLUTION_REMOVED, Issue.STATUS_CLOSED).setCount(13),
293 // exclude security hotspot
294 newResolvedGroup(Issue.RESOLUTION_WONT_FIX, Issue.STATUS_RESOLVED).setCount(15).setRuleType(RuleType.SECURITY_HOTSPOT.getDbConstant()),
295 // exclude unresolved
296 newGroup(RuleType.VULNERABILITY).setCount(17),
297 newGroup(RuleType.BUG).setCount(19))
298 .assertThatValueIs(CoreMetrics.FALSE_POSITIVE_ISSUES, 5)
299 .assertThatValueIs(CoreMetrics.ACCEPTED_ISSUES, 7 + 11);
303 public void count_by_status() {
305 .assertThatValueIs(CoreMetrics.CONFIRMED_ISSUES, 0)
306 .assertThatValueIs(CoreMetrics.OPEN_ISSUES, 0)
307 .assertThatValueIs(CoreMetrics.REOPENED_ISSUES, 0);
310 newGroup().setStatus(Issue.STATUS_CONFIRMED).setSeverity(Severity.BLOCKER).setCount(3),
311 newGroup().setStatus(Issue.STATUS_CONFIRMED).setSeverity(Severity.INFO).setCount(5),
312 newGroup().setStatus(Issue.STATUS_REOPENED).setCount(7),
313 newGroup(RuleType.CODE_SMELL).setStatus(Issue.STATUS_OPEN).setCount(9),
314 newGroup(RuleType.BUG).setStatus(Issue.STATUS_OPEN).setCount(11),
315 // exclude security hotspot
316 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_OPEN).setCount(12),
317 newResolvedGroup(Issue.RESOLUTION_FALSE_POSITIVE, Issue.STATUS_CLOSED).setCount(13))
318 .assertThatValueIs(CoreMetrics.CONFIRMED_ISSUES, 3 + 5)
319 .assertThatValueIs(CoreMetrics.OPEN_ISSUES, 9 + 11)
320 .assertThatValueIs(CoreMetrics.REOPENED_ISSUES, 7);
324 public void test_high_impact_accepted_issues() {
326 .assertThatValueIs(CoreMetrics.HIGH_IMPACT_ACCEPTED_ISSUES, 0);
329 newGroup(RuleType.CODE_SMELL).setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_FALSE_POSITIVE)
330 .setHasHighImpactSeverity(true).setCount(3),
331 newGroup(RuleType.CODE_SMELL).setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_WONT_FIX)
332 .setHasHighImpactSeverity(true).setCount(4),
333 newGroup(RuleType.CODE_SMELL).setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_WONT_FIX)
334 .setHasHighImpactSeverity(false).setCount(5),
335 newGroup(RuleType.BUG).setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_FALSE_POSITIVE)
336 .setHasHighImpactSeverity(true).setCount(30),
337 newGroup(RuleType.BUG).setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_WONT_FIX)
338 .setHasHighImpactSeverity(true).setCount(40),
339 newGroup(RuleType.BUG).setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_WONT_FIX)
340 .setHasHighImpactSeverity(false).setCount(50),
341 // exclude security hotspot
342 newGroup(RuleType.SECURITY_HOTSPOT).setResolution(Issue.RESOLUTION_WONT_FIX).setHasHighImpactSeverity(true).setCount(40))
343 .assertThatValueIs(CoreMetrics.HIGH_IMPACT_ACCEPTED_ISSUES, 4 + 40);
347 public void test_technical_debt() {
348 withNoIssues().assertThatValueIs(CoreMetrics.TECHNICAL_DEBT, 0);
351 newGroup(RuleType.CODE_SMELL).setEffort(3.0).setInLeak(false),
352 newGroup(RuleType.CODE_SMELL).setEffort(5.0).setInLeak(true),
353 // exclude security hotspot
354 newGroup(RuleType.SECURITY_HOTSPOT).setEffort(9).setInLeak(true),
355 newGroup(RuleType.SECURITY_HOTSPOT).setEffort(11).setInLeak(false),
357 newGroup(RuleType.BUG).setEffort(7.0),
359 newResolvedGroup(RuleType.CODE_SMELL).setEffort(17.0))
360 .assertThatValueIs(CoreMetrics.TECHNICAL_DEBT, 3.0 + 5.0);
364 public void test_reliability_remediation_effort() {
365 withNoIssues().assertThatValueIs(CoreMetrics.RELIABILITY_REMEDIATION_EFFORT, 0);
368 newGroup(RuleType.BUG).setEffort(3.0),
369 newGroup(RuleType.BUG).setEffort(5.0).setSeverity(Severity.BLOCKER),
371 newGroup(RuleType.CODE_SMELL).setEffort(7.0),
373 newResolvedGroup(RuleType.BUG).setEffort(17.0))
374 .assertThatValueIs(CoreMetrics.RELIABILITY_REMEDIATION_EFFORT, 3.0 + 5.0);
378 public void test_security_remediation_effort() {
379 withNoIssues().assertThatValueIs(CoreMetrics.SECURITY_REMEDIATION_EFFORT, 0);
382 newGroup(RuleType.VULNERABILITY).setEffort(3.0),
383 newGroup(RuleType.VULNERABILITY).setEffort(5.0).setSeverity(Severity.BLOCKER),
385 newGroup(RuleType.CODE_SMELL).setEffort(7.0),
387 newResolvedGroup(RuleType.VULNERABILITY).setEffort(17.0))
388 .assertThatValueIs(CoreMetrics.SECURITY_REMEDIATION_EFFORT, 3.0 + 5.0);
392 public void test_sqale_debt_ratio_and_sqale_rating() {
394 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0)
395 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
397 // technical_debt not computed
398 with(CoreMetrics.DEVELOPMENT_COST, "0")
399 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0)
400 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
401 with(CoreMetrics.DEVELOPMENT_COST, "20")
402 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0)
403 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
405 // development_cost not computed
406 with(CoreMetrics.TECHNICAL_DEBT, 0)
407 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0)
408 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
409 with(CoreMetrics.TECHNICAL_DEBT, 20)
410 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0)
411 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
413 // input measures are available
414 with(CoreMetrics.TECHNICAL_DEBT, 20.0)
415 .andText(CoreMetrics.DEVELOPMENT_COST, "0")
416 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0.0)
417 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
419 with(CoreMetrics.TECHNICAL_DEBT, 20.0)
420 .andText(CoreMetrics.DEVELOPMENT_COST, "160")
421 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 12.5)
422 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.C);
424 with(CoreMetrics.TECHNICAL_DEBT, 20.0)
425 .andText(CoreMetrics.DEVELOPMENT_COST, "10")
426 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 200.0)
427 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.E);
429 // A is 5% --> min debt is exactly 200*0.05=10
430 with(CoreMetrics.DEVELOPMENT_COST, "200")
431 .and(CoreMetrics.TECHNICAL_DEBT, 10.0)
432 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 5.0)
433 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
435 with(CoreMetrics.TECHNICAL_DEBT, 0.0)
436 .andText(CoreMetrics.DEVELOPMENT_COST, "0")
437 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0.0)
438 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
440 with(CoreMetrics.TECHNICAL_DEBT, 0.0)
441 .andText(CoreMetrics.DEVELOPMENT_COST, "80")
442 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0.0);
444 with(CoreMetrics.TECHNICAL_DEBT, -20.0)
445 .andText(CoreMetrics.DEVELOPMENT_COST, "0")
446 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0.0)
447 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
449 // bug, debt can't be negative
450 with(CoreMetrics.TECHNICAL_DEBT, -20.0)
451 .andText(CoreMetrics.DEVELOPMENT_COST, "80")
452 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0.0)
453 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
455 // bug, cost can't be negative
456 with(CoreMetrics.TECHNICAL_DEBT, 20.0)
457 .andText(CoreMetrics.DEVELOPMENT_COST, "-80")
458 .assertThatValueIs(CoreMetrics.SQALE_DEBT_RATIO, 0.0)
459 .assertThatValueIs(CoreMetrics.SQALE_RATING, Rating.A);
463 public void test_effort_to_reach_maintainability_rating_A() {
465 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 0.0);
467 // technical_debt not computed
468 with(CoreMetrics.DEVELOPMENT_COST, 0.0)
469 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 0.0);
470 with(CoreMetrics.DEVELOPMENT_COST, 20.0)
471 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 0.0);
473 // development_cost not computed
474 with(CoreMetrics.TECHNICAL_DEBT, 0.0)
475 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 0.0);
476 with(CoreMetrics.TECHNICAL_DEBT, 20.0)
477 // development cost is considered as zero, so the effort is to reach... zero
478 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 20.0);
481 with(CoreMetrics.DEVELOPMENT_COST, "200")
482 .and(CoreMetrics.TECHNICAL_DEBT, 40.0)
483 // B is 5% --> goal is to reach 200*0.05=10 --> effort is 40-10=30
484 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 40.0 - (200.0 * 0.05));
487 with(CoreMetrics.DEVELOPMENT_COST, "200")
488 .and(CoreMetrics.TECHNICAL_DEBT, 180.0)
489 // B is 5% --> goal is to reach 200*0.05=10 --> effort is 180-10=170
490 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 180.0 - (200.0 * 0.05));
493 with(CoreMetrics.DEVELOPMENT_COST, "200")
494 .and(CoreMetrics.TECHNICAL_DEBT, 8.0)
495 // B is 5% --> goal is to reach 200*0.05=10 --> debt is already at 8 --> effort to reach A is zero
496 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 0.0);
498 // exactly lower range of B
499 with(CoreMetrics.DEVELOPMENT_COST, "200")
500 .and(CoreMetrics.TECHNICAL_DEBT, 10.0)
501 // B is 5% --> goal is to reach 200*0.05=10 --> debt is 10 --> effort to reach A is zero
502 // FIXME need zero to reach A but effective rating is B !
503 .assertThatValueIs(CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A, 0.0);
507 public void test_reliability_rating() {
509 .assertThatValueIs(CoreMetrics.RELIABILITY_RATING, Rating.A);
512 newGroup(RuleType.BUG).setSeverity(Severity.CRITICAL).setCount(1),
513 newGroup(RuleType.BUG).setSeverity(Severity.MINOR).setCount(5),
514 // excluded, not a bug
515 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setCount(3))
516 // highest severity of bugs is CRITICAL --> D
517 .assertThatValueIs(CoreMetrics.RELIABILITY_RATING, Rating.D);
520 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MAJOR).setCount(3),
521 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.CRITICAL).setCount(5))
523 .assertThatValueIs(CoreMetrics.RELIABILITY_RATING, Rating.A);
527 public void test_security_rating() {
529 .assertThatValueIs(CoreMetrics.SECURITY_RATING, Rating.A);
532 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.CRITICAL).setCount(1),
533 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.MINOR).setCount(5),
534 // excluded, not a vulnerability
535 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setCount(3))
536 // highest severity of vulnerabilities is CRITICAL --> D
537 .assertThatValueIs(CoreMetrics.SECURITY_RATING, Rating.D);
540 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MAJOR).setCount(3),
541 newGroup(RuleType.BUG).setSeverity(Severity.CRITICAL).setCount(5))
542 // no vulnerabilities --> A
543 .assertThatValueIs(CoreMetrics.SECURITY_RATING, Rating.A);
547 public void test_new_bugs() {
548 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_BUGS, 0.0);
551 newGroup(RuleType.BUG).setInLeak(false).setSeverity(Severity.MAJOR).setCount(3),
552 newGroup(RuleType.BUG).setInLeak(true).setSeverity(Severity.CRITICAL).setCount(5),
553 newGroup(RuleType.BUG).setInLeak(true).setSeverity(Severity.MINOR).setCount(7),
555 newGroup(RuleType.CODE_SMELL).setInLeak(true).setCount(9),
556 newGroup(RuleType.VULNERABILITY).setInLeak(true).setCount(11))
557 .assertThatLeakValueIs(CoreMetrics.NEW_BUGS, 5 + 7);
562 public void test_new_code_smells() {
563 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_CODE_SMELLS, 0.0);
566 newGroup(RuleType.CODE_SMELL).setInLeak(false).setSeverity(Severity.MAJOR).setCount(3),
567 newGroup(RuleType.CODE_SMELL).setInLeak(true).setSeverity(Severity.CRITICAL).setCount(5),
568 newGroup(RuleType.CODE_SMELL).setInLeak(true).setSeverity(Severity.MINOR).setCount(7),
570 newGroup(RuleType.BUG).setInLeak(true).setCount(9),
571 newGroup(RuleType.VULNERABILITY).setInLeak(true).setCount(11))
572 .assertThatLeakValueIs(CoreMetrics.NEW_CODE_SMELLS, 5 + 7);
576 public void test_new_vulnerabilities() {
577 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_VULNERABILITIES, 0.0);
580 newGroup(RuleType.VULNERABILITY).setInLeak(false).setSeverity(Severity.MAJOR).setCount(3),
581 newGroup(RuleType.VULNERABILITY).setInLeak(true).setSeverity(Severity.CRITICAL).setCount(5),
582 newGroup(RuleType.VULNERABILITY).setInLeak(true).setSeverity(Severity.MINOR).setCount(7),
583 // not vulnerabilities
584 newGroup(RuleType.BUG).setInLeak(true).setCount(9),
585 newGroup(RuleType.CODE_SMELL).setInLeak(true).setCount(11))
586 .assertThatLeakValueIs(CoreMetrics.NEW_VULNERABILITIES, 5 + 7);
590 public void test_new_security_hotspots() {
591 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS, 0);
594 newGroup(RuleType.SECURITY_HOTSPOT).setInLeak(false).setSeverity(Severity.MAJOR).setCount(3),
595 newGroup(RuleType.SECURITY_HOTSPOT).setInLeak(true).setSeverity(Severity.CRITICAL).setCount(5),
596 newGroup(RuleType.SECURITY_HOTSPOT).setInLeak(true).setSeverity(Severity.MINOR).setCount(7),
598 newGroup(RuleType.BUG).setInLeak(true).setCount(9),
599 newGroup(RuleType.CODE_SMELL).setInLeak(true).setCount(11))
600 .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS, 5 + 7);
604 public void test_new_violations() {
605 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_VIOLATIONS, 0.0);
608 newGroup(RuleType.BUG).setInLeak(true).setCount(5),
609 newGroup(RuleType.CODE_SMELL).setInLeak(true).setCount(7),
610 newGroup(RuleType.VULNERABILITY).setInLeak(true).setCount(9),
612 newGroup(RuleType.BUG).setInLeak(false).setCount(11),
613 newGroup(RuleType.CODE_SMELL).setInLeak(false).setCount(13),
614 newGroup(RuleType.VULNERABILITY).setInLeak(false).setCount(17))
615 .assertThatLeakValueIs(CoreMetrics.NEW_VIOLATIONS, 5 + 7 + 9);
619 public void test_new_blocker_violations() {
621 .assertThatLeakValueIs(CoreMetrics.NEW_BLOCKER_VIOLATIONS, 0.0);
624 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setInLeak(true).setCount(3),
625 newGroup(RuleType.BUG).setSeverity(Severity.BLOCKER).setInLeak(true).setCount(5),
626 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.BLOCKER).setInLeak(true).setCount(7),
628 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.CRITICAL).setInLeak(true).setCount(9),
630 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setInLeak(false).setCount(11),
631 newGroup(RuleType.BUG).setSeverity(Severity.BLOCKER).setInLeak(false).setCount(13))
632 .assertThatLeakValueIs(CoreMetrics.NEW_BLOCKER_VIOLATIONS, 3 + 5 + 7);
636 public void test_new_critical_violations() {
638 .assertThatLeakValueIs(CoreMetrics.NEW_CRITICAL_VIOLATIONS, 0.0);
641 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.CRITICAL).setInLeak(true).setCount(3),
642 newGroup(RuleType.BUG).setSeverity(Severity.CRITICAL).setInLeak(true).setCount(5),
643 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.CRITICAL).setInLeak(true).setCount(7),
645 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MAJOR).setInLeak(true).setCount(9),
647 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.CRITICAL).setInLeak(false).setCount(11),
648 newGroup(RuleType.BUG).setSeverity(Severity.CRITICAL).setInLeak(false).setCount(13))
649 .assertThatLeakValueIs(CoreMetrics.NEW_CRITICAL_VIOLATIONS, 3 + 5 + 7);
653 public void test_new_major_violations() {
655 .assertThatLeakValueIs(CoreMetrics.NEW_MAJOR_VIOLATIONS, 0.0);
658 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MAJOR).setInLeak(true).setCount(3),
659 newGroup(RuleType.BUG).setSeverity(Severity.MAJOR).setInLeak(true).setCount(5),
660 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.MAJOR).setInLeak(true).setCount(7),
662 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.CRITICAL).setInLeak(true).setCount(9),
664 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MAJOR).setInLeak(false).setCount(11),
665 newGroup(RuleType.BUG).setSeverity(Severity.MAJOR).setInLeak(false).setCount(13))
666 .assertThatLeakValueIs(CoreMetrics.NEW_MAJOR_VIOLATIONS, 3 + 5 + 7);
670 public void test_new_minor_violations() {
672 .assertThatLeakValueIs(CoreMetrics.NEW_MINOR_VIOLATIONS, 0.0);
675 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MINOR).setInLeak(true).setCount(3),
676 newGroup(RuleType.BUG).setSeverity(Severity.MINOR).setInLeak(true).setCount(5),
677 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.MINOR).setInLeak(true).setCount(7),
679 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.CRITICAL).setInLeak(true).setCount(9),
681 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.MINOR).setInLeak(false).setCount(11),
682 newGroup(RuleType.BUG).setSeverity(Severity.MINOR).setInLeak(false).setCount(13))
683 .assertThatLeakValueIs(CoreMetrics.NEW_MINOR_VIOLATIONS, 3 + 5 + 7);
687 public void test_new_info_violations() {
689 .assertThatLeakValueIs(CoreMetrics.NEW_INFO_VIOLATIONS, 0.0);
692 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.INFO).setInLeak(true).setCount(3),
693 newGroup(RuleType.BUG).setSeverity(Severity.INFO).setInLeak(true).setCount(5),
694 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.INFO).setInLeak(true).setCount(7),
696 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.CRITICAL).setInLeak(true).setCount(9),
698 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.INFO).setInLeak(false).setCount(11),
699 newGroup(RuleType.BUG).setSeverity(Severity.INFO).setInLeak(false).setCount(13))
700 .assertThatLeakValueIs(CoreMetrics.NEW_INFO_VIOLATIONS, 3 + 5 + 7);
704 public void test_new_accepted_issues() {
706 .assertThatLeakValueIs(CoreMetrics.NEW_ACCEPTED_ISSUES, 0);
709 newGroup(RuleType.CODE_SMELL).setResolution(Issue.RESOLUTION_FALSE_POSITIVE).setInLeak(true).setCount(3),
710 newGroup(RuleType.CODE_SMELL).setResolution(Issue.RESOLUTION_WONT_FIX).setInLeak(true).setCount(4),
711 newGroup(RuleType.BUG).setResolution(Issue.RESOLUTION_FALSE_POSITIVE).setInLeak(true).setCount(30),
712 newGroup(RuleType.BUG).setResolution(Issue.RESOLUTION_WONT_FIX).setInLeak(true).setCount(40),
714 newGroup(RuleType.CODE_SMELL).setResolution(Issue.RESOLUTION_WONT_FIX).setInLeak(false).setCount(5),
715 newGroup(RuleType.BUG).setResolution(Issue.RESOLUTION_WONT_FIX).setInLeak(false).setCount(50))
716 .assertThatLeakValueIs(CoreMetrics.NEW_ACCEPTED_ISSUES, 4 + 40);
720 public void test_new_technical_debt() {
721 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0);
724 newGroup(RuleType.CODE_SMELL).setEffort(3.0).setInLeak(true),
726 newGroup(RuleType.CODE_SMELL).setEffort(5.0).setInLeak(false),
728 newGroup(RuleType.SECURITY_HOTSPOT).setEffort(9.0).setInLeak(true),
729 newGroup(RuleType.BUG).setEffort(7.0).setInLeak(true),
731 newResolvedGroup(RuleType.CODE_SMELL).setEffort(17.0).setInLeak(true))
732 .assertThatLeakValueIs(CoreMetrics.NEW_TECHNICAL_DEBT, 3.0);
736 public void test_new_reliability_remediation_effort() {
737 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_RELIABILITY_REMEDIATION_EFFORT, 0.0);
740 newGroup(RuleType.BUG).setEffort(3.0).setInLeak(true),
742 newGroup(RuleType.BUG).setEffort(5.0).setInLeak(false),
744 newGroup(RuleType.CODE_SMELL).setEffort(7.0).setInLeak(true),
746 newResolvedGroup(RuleType.BUG).setEffort(17.0).setInLeak(true))
747 .assertThatLeakValueIs(CoreMetrics.NEW_RELIABILITY_REMEDIATION_EFFORT, 3.0);
751 public void test_new_security_remediation_effort() {
752 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_REMEDIATION_EFFORT, 0.0);
755 newGroup(RuleType.VULNERABILITY).setEffort(3.0).setInLeak(true),
757 newGroup(RuleType.VULNERABILITY).setEffort(5.0).setInLeak(false),
759 newGroup(RuleType.CODE_SMELL).setEffort(7.0).setInLeak(true),
761 newResolvedGroup(RuleType.VULNERABILITY).setEffort(17.0).setInLeak(true))
762 .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_REMEDIATION_EFFORT, 3.0);
766 public void test_new_reliability_rating() {
767 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_RELIABILITY_RATING, Rating.A);
770 newGroup(RuleType.BUG).setSeverity(Severity.INFO).setCount(3).setInLeak(true),
771 newGroup(RuleType.BUG).setSeverity(Severity.MINOR).setCount(1).setInLeak(true),
773 newGroup(RuleType.BUG).setSeverity(Severity.BLOCKER).setInLeak(false),
775 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setInLeak(true),
777 newResolvedGroup(RuleType.BUG).setSeverity(Severity.BLOCKER).setInLeak(true))
778 // highest severity of bugs on leak period is minor -> B
779 .assertThatLeakValueIs(CoreMetrics.NEW_RELIABILITY_RATING, Rating.B);
783 public void test_new_security_rating() {
784 withNoIssues().assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_RATING, Rating.A);
787 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.INFO).setCount(3).setInLeak(true),
788 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.MINOR).setCount(1).setInLeak(true),
790 newGroup(RuleType.VULNERABILITY).setSeverity(Severity.BLOCKER).setInLeak(false),
792 newGroup(RuleType.CODE_SMELL).setSeverity(Severity.BLOCKER).setInLeak(true),
794 newResolvedGroup(RuleType.VULNERABILITY).setSeverity(Severity.BLOCKER).setInLeak(true))
795 // highest severity of bugs on leak period is minor -> B
796 .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_RATING, Rating.B);
800 public void test_new_security_review_rating() {
802 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3).setInLeak(true),
803 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1).setInLeak(true),
805 newGroup(RuleType.SECURITY_HOTSPOT).setSeverity(Issue.STATUS_TO_REVIEW).setInLeak(false))
806 .assertThatLeakValueIs(NEW_SECURITY_REVIEW_RATING, Rating.B);
809 .assertThatLeakValueIs(NEW_SECURITY_REVIEW_RATING, Rating.A);
813 public void test_new_security_hotspots_reviewed() {
815 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3).setInLeak(true),
816 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1).setInLeak(true),
818 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(5).setInLeak(false))
819 .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED, 75.0);
822 .assertNoLeakValue(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED);
826 public void test_new_security_hotspots_reviewed_status() {
828 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3).setInLeak(true),
829 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1).setInLeak(true),
831 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(5).setInLeak(false))
832 .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS, 3.0);
835 .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS, 0.0);
839 public void test_new_security_hotspots_to_review_status() {
841 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3).setInLeak(true),
842 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1).setInLeak(true),
844 newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(5).setInLeak(false))
845 .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 1.0);
848 .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 0.0);
852 public void test_new_sqale_debt_ratio_and_new_maintainability_rating() {
854 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0)
855 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
857 // technical_debt not computed
858 with(CoreMetrics.NEW_DEVELOPMENT_COST, 0)
859 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0)
860 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
861 with(CoreMetrics.NEW_DEVELOPMENT_COST, 20)
862 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0)
863 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
865 // development_cost not computed
866 with(CoreMetrics.NEW_TECHNICAL_DEBT, 0)
867 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0)
868 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
869 with(CoreMetrics.NEW_TECHNICAL_DEBT, 20)
870 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0)
871 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
873 // input measures are available
874 with(CoreMetrics.NEW_TECHNICAL_DEBT, 20.0)
875 .and(CoreMetrics.NEW_DEVELOPMENT_COST, 0.0)
876 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0.0)
877 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
879 with(CoreMetrics.NEW_TECHNICAL_DEBT, 20.0)
880 .and(CoreMetrics.NEW_DEVELOPMENT_COST, 160.0)
881 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 12.5)
882 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.C);
884 with(CoreMetrics.NEW_TECHNICAL_DEBT, 20.0)
885 .and(CoreMetrics.NEW_DEVELOPMENT_COST, 10.0D)
886 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 200.0)
887 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.E);
889 // A is 5% --> min debt is exactly 200*0.05=10
890 with(CoreMetrics.NEW_DEVELOPMENT_COST, 200.0)
891 .and(CoreMetrics.NEW_TECHNICAL_DEBT, 10.0)
892 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 5.0)
893 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
895 with(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0)
896 .and(CoreMetrics.NEW_DEVELOPMENT_COST, 0.0)
897 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0.0)
898 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
900 with(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0)
901 .and(CoreMetrics.NEW_DEVELOPMENT_COST, 80.0)
902 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0.0);
904 with(CoreMetrics.NEW_TECHNICAL_DEBT, -20.0)
905 .and(CoreMetrics.NEW_DEVELOPMENT_COST, 0.0)
906 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0.0)
907 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
909 // bug, debt can't be negative
910 with(CoreMetrics.NEW_TECHNICAL_DEBT, -20.0)
911 .and(CoreMetrics.NEW_DEVELOPMENT_COST, 80.0)
912 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0.0)
913 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
915 // bug, cost can't be negative
916 with(CoreMetrics.NEW_TECHNICAL_DEBT, 20.0)
917 .and(CoreMetrics.NEW_DEVELOPMENT_COST, -80.0)
918 .assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0.0)
919 .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
922 private Verifier with(IssueGroupDto... groups) {
923 return new Verifier(groups);
926 private Verifier withNoIssues() {
927 return new Verifier(new IssueGroupDto[0]);
930 private Verifier with(Metric metric, double value) {
931 return new Verifier(new IssueGroupDto[0]).and(metric, value);
934 private Verifier with(Metric metric, String value) {
935 return new Verifier(new IssueGroupDto[0]).andText(metric, value);
938 private class Verifier {
939 private final IssueGroupDto[] groups;
940 private final InitialValues initialValues = new InitialValues();
942 private Verifier(IssueGroupDto[] groups) {
943 this.groups = groups;
946 Verifier and(Metric metric, double value) {
947 this.initialValues.values.put(metric, value);
951 Verifier andText(Metric metric, String value) {
952 this.initialValues.text.put(metric, value);
956 Verifier assertThatValueIs(Metric metric, double expectedValue) {
957 TestContext context = run(metric, false);
958 assertThat(context.doubleValue).isNotNull().isEqualTo(expectedValue);
962 Verifier assertThatLeakValueIs(Metric metric, double expectedValue) {
963 TestContext context = run(metric, true);
964 assertThat(context.doubleValue).isNotNull().isEqualTo(expectedValue);
968 Verifier assertThatLeakValueIs(Metric metric, Rating expectedRating) {
969 TestContext context = run(metric, true);
970 assertThat(context.ratingValue).isNotNull().isEqualTo(expectedRating);
974 Verifier assertNoLeakValue(Metric metric) {
975 TestContext context = run(metric, true);
976 assertThat(context.ratingValue).isNull();
980 Verifier assertThatValueIs(Metric metric, Rating expectedValue) {
981 TestContext context = run(metric, false);
982 assertThat(context.ratingValue).isNotNull().isEqualTo(expectedValue);
986 Verifier assertNoValue(Metric metric) {
987 TestContext context = run(metric, false);
988 assertThat(context.ratingValue).isNull();
992 private TestContext run(Metric metric, boolean expectLeakFormula) {
993 MeasureUpdateFormula formula = underTest.getFormulas().stream()
994 .filter(f -> f.getMetric().getKey().equals(metric.getKey()))
997 assertThat(formula.isOnLeak()).isEqualTo(expectLeakFormula);
998 TestContext context = new TestContext(formula.getDependentMetrics(), initialValues);
999 formula.compute(context, newIssueCounter(groups));
1004 private static IssueCounter newIssueCounter(IssueGroupDto... issues) {
1005 return new IssueCounter(asList(issues));
1008 private static IssueGroupDto newGroup() {
1009 return newGroup(RuleType.CODE_SMELL);
1012 private static IssueGroupDto newGroup(RuleType ruleType) {
1013 IssueGroupDto dto = new IssueGroupDto();
1014 // set non-null fields
1015 dto.setRuleType(ruleType.getDbConstant());
1018 dto.setSeverity(Severity.INFO);
1019 dto.setStatus(Issue.STATUS_OPEN);
1020 dto.setInLeak(false);
1024 private static IssueGroupDto newResolvedGroup(RuleType ruleType) {
1025 return newGroup(ruleType).setResolution(Issue.RESOLUTION_FALSE_POSITIVE).setStatus(Issue.STATUS_CLOSED);
1028 private static IssueGroupDto newResolvedGroup(String resolution, String status) {
1029 return newGroup().setResolution(resolution).setStatus(status);
1032 private static class TestContext implements MeasureUpdateFormula.Context {
1033 private final Set<Metric> dependentMetrics;
1034 private final InitialValues initialValues;
1035 private Double doubleValue;
1036 private Rating ratingValue;
1038 private TestContext(Collection<Metric> dependentMetrics, InitialValues initialValues) {
1039 this.dependentMetrics = new HashSet<>(dependentMetrics);
1040 this.initialValues = initialValues;
1044 public List<Double> getChildrenValues() {
1045 return initialValues.childrenValues;
1049 public long getChildrenHotspotsReviewed() {
1050 return initialValues.childrenHotspotsReviewed;
1054 public long getChildrenHotspotsToReview() {
1055 return initialValues.childrenHotspotsToReview;
1059 public long getChildrenNewHotspotsReviewed() {
1060 return initialValues.childrenNewHotspotsReviewed;
1064 public long getChildrenNewHotspotsToReview() {
1065 return initialValues.childrenNewHotspotsToReview;
1069 public ComponentDto getComponent() {
1070 throw new UnsupportedOperationException();
1074 public DebtRatingGrid getDebtRatingGrid() {
1075 return new DebtRatingGrid(new double[] {0.05, 0.1, 0.2, 0.5});
1079 public Optional<Double> getValue(Metric metric) {
1080 if (!dependentMetrics.contains(metric)) {
1081 throw new IllegalStateException("Metric " + metric.getKey() + " is not declared as a dependency");
1083 if (initialValues.values.containsKey(metric)) {
1084 return Optional.of(initialValues.values.get(metric));
1086 return Optional.empty();
1090 public Optional<String> getText(Metric metric) {
1091 if (initialValues.text.containsKey(metric)) {
1092 return Optional.of(initialValues.text.get(metric));
1094 return Optional.empty();
1098 public void setValue(double value) {
1099 this.doubleValue = value;
1103 public void setValue(Rating value) {
1104 this.ratingValue = value;
1108 private class InitialValues {
1109 private final Map<Metric, Double> values = new HashMap<>();
1110 private final List<Double> childrenValues = new ArrayList<>();
1111 private final Map<Metric, String> text = new HashMap<>();
1112 private long childrenHotspotsReviewed = 0;
1113 private long childrenNewHotspotsReviewed = 0;
1114 private long childrenHotspotsToReview = 0;
1115 private long childrenNewHotspotsToReview = 0;
1119 private class HierarchyTester {
1120 private final Metric metric;
1121 private final InitialValues initialValues;
1122 private final MeasureUpdateFormula formula;
1124 public HierarchyTester(Metric metric) {
1125 this.metric = metric;
1126 this.initialValues = new InitialValues();
1127 this.formula = underTest.getFormulas().stream().filter(f -> f.getMetric().equals(metric)).findAny().get();
1130 public HierarchyTester withValue(Metric metric, Double value) {
1131 this.initialValues.values.put(metric, value);
1135 public HierarchyTester withChildrenHotspotsCounts(long childrenHotspotsReviewed, long childrenNewHotspotsReviewed, long childrenHotspotsToReview,
1136 long childrenNewHotspotsToReview) {
1137 this.initialValues.childrenHotspotsReviewed = childrenHotspotsReviewed;
1138 this.initialValues.childrenNewHotspotsReviewed = childrenNewHotspotsReviewed;
1139 this.initialValues.childrenHotspotsToReview = childrenHotspotsToReview;
1140 this.initialValues.childrenNewHotspotsToReview = childrenNewHotspotsToReview;
1144 public HierarchyTester withValue(Double value) {
1145 return withValue(metric, value);
1148 public HierarchyTester withChildrenValues(Double... values) {
1149 this.initialValues.childrenValues.addAll(asList(values));
1153 public HierarchyTester expectedResult(@Nullable Double expected) {
1154 TestContext ctx = run();
1155 assertThat(ctx.doubleValue).isEqualTo(expected);
1159 public HierarchyTester expectedRating(@Nullable Rating rating) {
1160 TestContext ctx = run();
1161 assertThat(ctx.ratingValue).isEqualTo(rating);
1165 private TestContext run() {
1166 List<Metric> deps = new LinkedList<>(formula.getDependentMetrics());
1167 deps.add(formula.getMetric());
1168 deps.addAll(initialValues.values.keySet());
1169 deps.addAll(initialValues.text.keySet());
1170 TestContext context = new TestContext(deps, initialValues);
1171 formula.computeHierarchy(context);