Methods refactored should be tested
Runs only in diff mode (baseline defined) and when coverage data is imported, on methods refactored since baseline.
Covered code is maintainable and non-error-prone. Since stopping development to test a poorly covered code base is impracticable, each time a method or type gets refactored, write associated unit-tests. Maintainability increases, refactoring becomes driven by testability, and the overall design improves.
Severity is High: these issues reflect an actual trend of not writing tests for refactored code.
Covered code is maintainable and non-error-prone. Since stopping development to test a poorly covered code base is impracticable, each time a method or type gets refactored, write associated unit-tests. Maintainability increases, refactoring becomes driven by testability, and the overall design improves.
Severity is High: these issues reflect an actual trend of not writing tests for refactored code.
How to fix
Write unit-tests covering most refactored methods and classes.
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>Methods refactored should be tested</Name>
// <Id>ND1602:MethodsRefactoredShouldBeTested</Id>
warnif count > 0
from m in JustMyCode.Methods where
m.PercentageCoverage < 30 &&
m.CodeWasChanged() &&
!m.IsClassConstructor &&
// Make sure the source file really changed, and it is not just a IL change
m.SourceFileDeclAvailable &&
context.CompareContext.WasChanged(m.SourceDecls.First().SourceFile.FilePath)
// A change that keeps the method's shape — same lines of code, same IL size, same
// cyclomatic complexity — is the ripple of a rename, a namespace move or a retyped
// dependency (a type reference or a call/callvirt swap in the IL), not a refactoring
// of this method: nothing new to test here.
let older = m.OlderVersion()
where older == null ||
m.NbLinesOfCode != older.NbLinesOfCode ||
m.NbILInstructions != older.NbILInstructions ||
m.CyclomaticComplexity != older.CyclomaticComplexity
orderby m.NbLinesOfCode descending,
m.NbLinesOfCodeNotCovered ,
m.PercentageCoverage
select new {
m,
m.PercentageCoverage,
m.NbLinesOfCode,
m.NbLinesOfCodeNotCovered,
// Simplistic Debt estimation, because the effort to write tests for a method not 100% tested
// is already estimated properly with the rule "Code should be tested".
Debt = m.NbLinesOfCodeNotCovered.Linear(1,2, 10,10).ToMinutes().ToDebt(),
Severity = Severity.High
}
//<Expl>The refactored *{0}* is {1}% covered by tests.
// When engaging in code refactoring, it is important to write tests to safeguard against the introduction of regression bugs.</Expl>
//<Desc>
// Runs only in *diff mode* (baseline defined) and when coverage data is
// imported, on methods refactored since baseline.
//
// Covered code is *maintainable* and *non-error-prone*. Since stopping
// development to test a poorly covered code base is impracticable, each time
// a method or type gets refactored, write associated unit-tests.
// Maintainability increases, refactoring becomes driven by testability, and
// the overall design improves.
//
// Severity is **High**: these issues reflect an actual trend of not writing
// tests for refactored code.
//</Desc>
//<HowToFix>
// Write unit-tests covering most refactored methods and classes.
//</HowToFix>
Open in the interactive Rules Explorer · All default rules
Code Coverage: all 15 items
- Code should be tested ND1600
- New Types and Methods should be tested ND1601
- Methods refactored should be tested ND1602
- Assemblies and Namespaces should be tested ND1603
- Types almost 100% tested should be 100% tested ND1604
- Namespaces almost 100% tested should be 100% tested ND1605
- Types that used to be 100% covered by tests should still be 100% covered ND1606
- Types tagged with FullCoveredAttribute should be 100% covered ND1607
- Types 100% covered should be tagged with FullCoveredAttribute ND1608
- Methods should have a low C.R.A.P score ND1609
- Complex Methods should be 100% tested ND1610
- Test methods should assert something ND1611
- Test Methods
- Methods directly called by test Methods
- Methods directly and indirectly called by test Methods