Measuring test coverage is crucial for understanding how much of your codebase is actually being tested. This blog walks you through how to generate code coverage reports, convert them into human-friendly HTML, and explains the difference between Line Coverage and Branch Coverage.
Step 1: Add Necessary Packages
In your test project .csproj file, ensure the following packages are installed:
<PackageReference Include="coverlet.collector" Version="6.0.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
You can install via CLI:
dotnet add package coverlet.collector
Step 2: Run Tests with Coverage Collection
Use the dotnet test command with coverage parameters:
dotnet test \
--collect:"XPlat Code Coverage"
This will generate a file like:
TestResults/{guid}/coverage.cobertura.xml
This .xml file is in Cobertura format, and we’ll use it to generate a readable report.
Step 3: Install ReportGenerator (if not already)
dotnet tool install -g dotnet-reportgenerator-globaltool
If it’s already installed and can’t be found, make sure you export the tool path:
export PATH="$PATH:$HOME/.dotnet/tools"
Step 4: Generate HTML Report
Use the following command in your test project:
reportgenerator \
-reports:"TestResults/**/coverage.cobertura.xml" \
-targetdir:"coverage-report" \
-reporttypes:Html
You’ll now find an
index.htmlfile inside thecoverage-reportfolder. Open it in a browser to view detailed coverage.
Line Coverage vs Branch Coverage
Here’s a quick summary:
| Metric | Description | Example |
|---|---|---|
| Line Coverage | Has each line of code been executed? |
if (x > 0) ran once → counted as covered |
| Branch Coverage | Has each logical path (true/false) of conditionals been run? | Must test both x > 0 and x <= 0
|
Branch coverage helps you detect untested logic paths, while line coverage only tells you whether the line ran or not.
My Report Screenshot
Excluding Files or Classes from Code Coverage
Sometimes, you may want to exclude specific files, classes, or folders from code coverage—for example, DbContext, auto-generated migrations, or testing helpers. You can configure these exclusions using a .runsettings file.
1. Create a coverlet.runsettings File
Place this file at the root of your project or solution (or anywhere but you need to specify the location in your command):
<RunSettings>
<DataCollectionRunSettings>
<DataCollectors>
<DataCollector friendlyName="XPlat code coverage">
<Configuration>
<Exclude>
<!-- Exclude specific class names or folders -->
<ModulePath>.*Tests.*</ModulePath>
<ClassName>.*DbContext.*</ClassName>
<ClassName>.*Migrations.*</ClassName>
<ClassName>.*FakeService.*</ClassName>
</Exclude>
</Configuration>
</DataCollector>
</DataCollectors>
</DataCollectionRunSettings>
</RunSettings>
2. Use the File in Your Coverage Command
Tell the test runner to use this settings file:
dotnet test --settings coverlet.runsettings
This will exclude the specified classes or paths from the final coverage result.


Top comments (1)
Thank you for creating a very simple example of how to get code coverage up and running on a .NET project.