Analyze code coverage and CRAP (Change Risk Anti-Patterns) scores to identify high-risk code. Use OpenCover format with ReportGenerator for Risk Hotspots showing cyclomatic complexity and untested code paths.
SKILL.md
CRAP Score Analysis
When to Use This Skill
Use this skill when:
Evaluating code quality and test coverage before changes
Identifying high-risk code that needs refactoring or testing
Setting up coverage collection for a .NET project
Prioritizing which code to test based on risk
Establishing coverage thresholds for CI/CD pipelines
What is CRAP?
CRAP Score = Complexity x (1 - Coverage)^2
The CRAP (Change Risk Anti-Patterns) score combines cyclomatic complexity with test coverage to identify risky code.
CRAP Score
Risk Level
Action Required
< 5
Low
Well-tested, maintainable code
5-30
Medium
Acceptable but watch complexity
> 30
High
Needs tests or refactoring
Why CRAP Matters
High complexity + low coverage = danger: Code that's hard to understand AND untested is risky to modify
Complexity alone isn't enough: A complex method with 100% coverage is safer than a simple method with 0%
Focuses effort: Prioritize testing on complex code, not simple getters/setters
CRAP Score Examples
Method
Complexity
Coverage
Calculation
CRAP
GetUserId()
1
0%
1 x (1 - 0)^2
1
ParseToken()
54
52%
54 x (1 - 0.52)^2
12.4
ValidateForm()
20
0%
20 x (1 - 0)^2
20
ProcessOrder()
45
20%
45 x (1 - 0.20)^2
28.8
ImportData()
80
10%
80 x (1 - 0.10)^2
64.8
Coverage Collection Setup
coverage.runsettings
Create a coverage.runsettings file in your repository root. The OpenCover format is required for CRAP score calculation because it includes cyclomatic complexity metrics.
<?xml version="1.0" encoding="utf-8" ?>
<RunSettings>
<DataCollectionRunSettings>
<DataCollectors>
<DataCollector friendlyName="XPlat code coverage">
<Configuration>
<!-- OpenCover format includes cyclomatic complexity for CRAP scores -->
<Format>cobertura,opencover</Format>
<!-- Exclude test and benchmark assemblies -->
<Exclude>[*.Tests]*,[*.Benchmark]*,[*.Migrations]*</Exclude>
<!-- Exclude generated code, obsolete members, and explicit exclusions -->
<ExcludeByAttribute>Obsolete,GeneratedCodeAttribute,CompilerGeneratedAttribute,ExcludeFromCodeCoverageAttribute</ExcludeByAttribute>
<!-- Exclude source-generated files, Blazor generated code, and migrations -->
<ExcludeByFile>**/obj/**/*,**/*.g.cs,**/*.designer.cs,**/*.razor.g.cs,**/*.razor.css.g.cs,**/Migrations/**/*</ExcludeByFile>
<!-- Exclude test projects -->
<IncludeTestAssembly>false</IncludeTestAssembly>
<!-- Optimization flags -->
<SingleHit>false</SingleHit>
<UseSourceLink>true</UseSourceLink>
<SkipAutoProps>true</SkipAutoProps>
</Configuration>
</DataCollector>
</DataCollectors>
</DataCollectionRunSettings>
</RunSettings>
Key Configuration Options
Option
Purpose
Format
Must include opencover for complexity metrics
Exclude
Exclude test/benchmark assemblies by pattern
ExcludeByAttribute
Skip generated, obsolete, and explicitly excluded code (includes ExcludeFromCodeCoverageAttribute)
ExcludeByFile
Skip source-generated files, Blazor components, and migrations
SkipAutoProps
Don't count auto-properties as branches
ReportGenerator Installation
Install ReportGenerator as a local tool for generating HTML reports with Risk Hotspots.