How to Analyze Code Coverage Metrics in .NET Test Projects: The Complete Guide
The coverage-analysis skill in the dotnet/skills repository automatically detects test projects, instruments them with coverage collectors, and computes CRAP scores to surface high-risk methods that need additional testing.
The dotnet/skills repository provides a turnkey solution when you need to analyze code coverage metrics in .NET test projects without manual configuration. Located at plugins/dotnet-test/skills/coverage-analysis, this skill orchestrates the entire workflow from solution detection to actionable markdown reports, requiring only the .NET SDK and PowerShell.
What Is the Coverage-Analysis Skill?
The coverage-analysis skill is a structured automation that lives in plugins/dotnet-test/skills/coverage-analysis within the dotnet/skills repository. It operates entirely from source, discovering your solution structure and test projects automatically (see the Phase 1 script description in SKILL.md lines 80-100). The skill adheres to strict guidelines: it only adds coverage provider packages such as coverlet.collector or Microsoft.Testing.Extensions.CodeCoverage when missing, never touching source code, and isolates all generated artifacts under TestResults/coverage-analysis/ (as defined in references/guidelines.md lines 3-9).
The Five-Phase Analysis Workflow
The skill executes a predictable pipeline that transforms raw test execution into risk-based insights.
Phase 1: Project Discovery
The skill locates the solution or entry project and discovers all associated test projects. It determines the output directory for artifacts and validates the environment before proceeding.
Phase 2: Test Execution with Coverage
If no Cobertura files exist, the skill ensures a coverage provider is present. It injects coverlet.collector or Microsoft.Testing.Extensions.CodeCoverage into test projects when needed (logic defined in SKILL.md lines 124-164), then runs dotnet test with the appropriate arguments. For Coverlet, it invokes:
dotnet test <ENTRY> --collect:"XPlat Code Coverage" ...
This generates Cobertura XML files that serve as the raw data for all subsequent analysis (see SKILL.md lines 224-230).
Phase 3: CRAP Score Computation
The skill invokes scripts/Compute-CrapScores.ps1 to parse the Cobertura XML and calculate per-method CRAP scores (Change Risk Anti-Pattern). The script computes the formula:
CRAP(m) = comp(m)² * (1 - cov(m))³ + comp(m)
This highlights methods that combine high cyclomatic complexity with poor coverage, identifying the most dangerous code to modify without tests (implementation in Compute-CrapScores.ps1 lines 9-14 and 57-66).
Phase 4: Method-Level Gap Analysis
Using scripts/Extract-MethodCoverage.ps1, the skill extracts line and branch percentages for every method, filtering for uncovered or below-threshold entries. The script outputs UNCOVERED_METHODS and METHODS_FILTERED JSON structures that pinpoint exactly which files need attention (see Extract-MethodCoverage.ps1 lines 70-84 and 90-93).
Phase 5: Optional Report Generation
If requested, the skill installs dotnet-reportgenerator-globaltool and creates HTML, Text, or CSV reports using ReportGenerator (configuration in SKILL.md lines 99-106).
Understanding CRAP Scores and Risk Hotspots
Raw line and branch percentages tell you what code executed, but CRAP scores reveal why coverage may be stuck. A method with high complexity and low coverage receives an elevated CRAP score, flagging it as a risk hotspot. The skill outputs these as a ranked table in TestResults/coverage-analysis/coverage-analysis.md, showing:
- Overall Line/Branch Coverage – Aggregated percentages from all Cobertura files (output by
Compute-CrapScores.ps1lines 57-59). - Top-N Risk Hotspots – Methods with the highest CRAP scores, prioritized for new test writing.
- Coverage Gaps – Specific methods falling below configurable line and branch thresholds (default 80% line, 70% branch).
Running the Analysis Manually
You can execute the skill’s PowerShell scripts directly without the full orchestration.
Compute Overall Coverage and CRAP Scores
$skillDir = "$(git rev-parse --show-toplevel)/plugins/dotnet-test/skills/coverage-analysis"
# Find all Cobertura files and compute top 10 risk hotspots
& "$skillDir/scripts/Compute-CrapScores.ps1" `
-CoberturaPath (Get-ChildItem -Path . -Filter "*.cobertura.xml" -Recurse).FullName `
-TopN 10
Extract Methods Below Coverage Thresholds
# Filter for methods with line coverage below 80% or branch below 70%
& "$skillDir/scripts/Extract-MethodCoverage.ps1" `
-CoberturaPath (Get-ChildItem -Path . -Filter "*.cobertura.xml" -Recurse).FullName `
-Filter below-threshold |
ConvertFrom-Json |
Format-Table File, Class, Method, LineCoverage, BranchCoverage, Complexity
Add a Coverage Provider Manually
If auto-detection fails, manually add the collector:
dotnet add ./tests/MyApp.Tests.csproj package coverlet.collector --no-restore
dotnet restore ./tests/MyApp.Tests.csproj
Summary
- The coverage-analysis skill in
dotnet/skillsprovides automated detection, execution, and analysis of .NET test coverage. - It enriches raw Cobertura XML data with CRAP scores to identify complex, untested methods that pose the highest change risk.
- Key scripts include
Compute-CrapScores.ps1for risk calculation andExtract-MethodCoverage.ps1for method-level gap analysis. - All artifacts are generated under
TestResults/coverage-analysis/without modifying source code. - The workflow supports both Coverlet and Microsoft.Testing.Extensions.CodeCoverage providers.
Frequently Asked Questions
What is a CRAP score and why does it matter?
A CRAP score (Change Risk Anti-Pattern) is a composite metric calculated as complexity² × (1 - coverage)³ + complexity. It matters because it identifies methods that are both complex and poorly covered—these are the most dangerous to modify without breaking functionality, and therefore the highest priority for new unit tests.
Can I use this skill with Microsoft’s code coverage tools instead of Coverlet?
Yes. The skill automatically detects whether Microsoft.Testing.Extensions.CodeCoverage is already referenced and will prefer it or add it if no coverage provider exists. It supports both Coverlet (via coverlet.collector) and the Microsoft testing extensions, adjusting the dotnet test arguments accordingly (see SKILL.md lines 124-164).
How do I view the generated coverage report?
The skill writes a markdown summary to TestResults/coverage-analysis/coverage-analysis.md. You can read this directly in any markdown viewer, or use the optional ReportGenerator integration to create HTML reports. For CI/CD pipelines, the Cobertura XML files are compatible with standard coverage visualization tools.
Does the skill modify my source code or project files?
No. According to references/guidelines.md (lines 3-9), the skill may only add coverage provider packages (like coverlet.collector) to test projects. It never modifies source code, production project files, or adds test code. All analysis is performed on existing artifacts and output to isolated directories.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →