Types tagged with FullCoveredAttribute should be 100% covered

Rule ND1607 Code Coverage

Lists partially covered methods of types tagged FullCoveredAttribute. Runs only when coverage data is imported.

FullCoveredAttribute expresses in source code the intention that a class is and should remain 100% covered — an intention continuously checked by this rule. To avoid linking NDepend.API.dll, use your own attribute and adapt the rule.

The last ~10% of a class is as hard to cover as the first 90%, but untestable code usually means poorly written, error prone code: most tricky bugs might come from this small portion of hard-to-test code.

Severity is High: a type that lost 100% coverage is a bug-prone situation to handle carefully.

How to fix

Write more unit-tests for uncovered code of matched classes. Hard-to-test code signals a design needing refactoring.

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>Types tagged with FullCoveredAttribute should be 100% covered</Name>
// <Id>ND1607:TypesTaggedWithFullCoveredAttributeShouldBe100PercentCovered</Id>
warnif count > 0
let covAttrs = Types.WithName("FullCoveredAttribute").Where(t => t.IsAttributeClass).ToArray()
where covAttrs.Any()

from t in JustMyCode.Types where
  t.AttributeClassesThatTagMe.Intersect(covAttrs).Any() &&
  t.PercentageCoverage < 100 

from m in t.MethodsAndConstructors where 
  m.NbLinesOfCode> 0 && 
  m.PercentageCoverage < 100 &&
 !m.IsExcludedFromCoverage

select new { 
   m, 
   m.PercentageCoverage, 
   m.NbLinesOfCodeNotCovered, 
   m.NbLinesOfCode, 

   // 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 *{0}* is tagged with *FullCoveredAttribute*, yet its current coverage ratio stands at {1}%.
// This attribute indicates a commitment to keep this type fully tested.
// It is important to craft additional tests that align with this commitment.
//</Expl>

//<Desc>
// Lists partially covered methods of types tagged **FullCoveredAttribute**.
// Runs only when coverage data is imported.
//
// **FullCoveredAttribute** expresses in source code the intention that a
// class is and should remain 100% covered — an intention continuously
// checked by this rule. To avoid linking *NDepend.API.dll*, use your own
// attribute and adapt the rule.
//
// The last ~10% of a class is as hard to cover as the first 90%, but
// *untestable code* usually means *poorly written*, *error prone* code:
// **most tricky bugs might come from this small portion of hard-to-test
// code**.
//
// Severity is **High**: a type that lost 100% coverage is a bug-prone
// situation to handle carefully.
//</Desc>

//<HowToFix>
// Write more unit-tests for uncovered code of matched classes.
// *Hard-to-test code* signals a design needing refactoring.
//</HowToFix>

Code Coverage: all 15 items