Avoid decreasing code coverage by tests of types
Runs only in diff mode (baseline defined) and when coverage data is imported. Warns when a type's covered lines decreased since baseline (for refactored types, accounting for lines of code added).
This can mean tests were removed, but more often that changes haven't been properly covered by tests.
To visualize changes, right-click a matched type and select:
- Compare older and newer versions of source file
- or Compare older and newer versions decompiled with Reflector
This can mean tests were removed, but more often that changes haven't been properly covered by tests.
To visualize changes, right-click a matched type and select:
- Compare older and newer versions of source file
- or Compare older and newer versions decompiled with Reflector
How to fix
Write more unit-tests covering the changes. Hard-to-test code signals a design needing refactoring.
Estimated Debt: linear from 15 minutes to 3 hours with the number of lines no longer covered. Severity varies from High to Critical likewise: fix these issues now, before such code gets released in production.
Estimated Debt: linear from 15 minutes to 3 hours with the number of lines no longer covered. Severity varies from High to Critical likewise: fix these issues now, before such code gets released in production.
CQLinq source
This rule is written in CQLinq, C# LINQ over the NDepend code model. It ships with every new NDepend project: you can read it, adapt it, or use it as a starting point for your own custom rules.
// <Name>Avoid decreasing code coverage by tests of types</Name>
// <Id>ND1103:AvoidDecreasingCodeCoverageByTestsOfTypes</Id>
warnif count > 0
from t in JustMyCode.Types where
t.IsPresentInBothBuilds() && t.CoverageDataAvailable && t.OlderVersion().CoverageDataAvailable
&& t.NbLinesOfCode.HasValue && t.OlderVersion().NbLinesOfCode.HasValue
let locDiff = (int)t.NbLinesOfCode.Value - (int)t.OlderVersion().NbLinesOfCode.Value
where locDiff >= 0
let uncoveredLoc = (int)t.NbLinesOfCodeNotCovered.Value - ((int)t.OlderVersion().NbLinesOfCodeNotCovered.Value + locDiff)
where uncoveredLoc > 0
orderby uncoveredLoc descending
select new {
t,
OldCoveragePercent = t.OlderVersion().PercentageCoverage,
NewCoveragePercent = t.PercentageCoverage,
OldLoc = t.OlderVersion().NbLinesOfCode,
NewLoc = t.NbLinesOfCode,
uncoveredLoc,
Debt = uncoveredLoc.Linear(1, 15, 100, 3*60).ToMinutes().ToDebt(),
// The annual interest varies linearly from interest for severity High for one line of code that is not covered by tests anymore
// to interest for severity Critical for 50 lines of code that are not covered by tests anymore
AnnualInterest = uncoveredLoc.Linear(1, Severity.High.AnnualInterestThreshold().Value.TotalMinutes,
50, 2*Severity.Critical.AnnualInterestThreshold().Value.TotalMinutes).ToMinutes().ToAnnualInterest()
}
//<Expl>
// The *{0}* used to be {1}% covered by tests in the baseline and is
// now {2}% covered, with {5} new statement{5?:s} not being covered.
// Write additional unit tests to cover changes.
// Identifying *hard-to-test* code often indicates *poor design*
// that needs refactoring.
//</Expl>
//<Desc>
// Runs only in *diff mode* (baseline defined) and when coverage data is
// imported. Warns when a type's covered lines decreased since baseline (for
// refactored types, accounting for lines of code added).
//
// This can mean tests were removed, but more often that changes haven't been
// properly covered by tests.
//
// To visualize changes, right-click a matched type and select:
//
// - Compare older and newer versions of source file
//
// - or Compare older and newer versions decompiled with Reflector
//</Desc>
//<HowToFix>
// Write more unit-tests covering the changes. *Hard-to-test code* signals a
// design needing refactoring.
//
// Estimated Debt: linear from 15 minutes to 3 hours with the number of lines
// no longer covered. Severity varies from **High** to **Critical** likewise:
// fix these issues **now**, before such code gets released in production.
//</HowToFix>
Open in the interactive Rules Explorer · All default rules
Code Smells Regression: all 9 items
- From now, all types added should respect basic quality principles ND1100
- From now, all types added should be 100% covered by tests ND1101
- From now, all methods added should respect basic quality principles ND1102
- Avoid decreasing code coverage by tests of types ND1103
- Avoid making complex methods even more complex ND1104
- Avoid making large methods even larger ND1105
- Avoid adding methods to a type that already had many methods ND1106
- Avoid adding instance fields to a type that already had many instance fields ND1107
- Avoid transforming an immutable type into a mutable one ND1108