Coverage reports in C# with Cobertura
In the last contract I completed, we were building WebAPI microservices in C#, and part of our build process was to run all of our XUnit (and, depending on who originally wrote the microservice, maybe NUnit) tests and use SonarCloud to produce a pretty amazingly specific coverage report that highlighted every source file's test status, line-by-line.
I've got a personal project in C#, have been spending time recently writing tests for it, and wondered if I could pull off the same level of coverage testing.
Turns out I can! Exactly the same!
Install by adding a ref to the coverlet collector to your testing proj:
dotnet add package coverlet.collector
Then run the test with this:
dotnet test --collect:"XPlat Code Coverage"
After the above command is run, a
coverage.cobertura.xml
file containing the results will be published to theTestResults
directory as an attachment.
And sure enough, there's a new folder with every run in my C:\path\to\app\MyTestingProjectFolder\TestResults
folder. The cobertura file is in painfully named folders like 946f0f00-2eec-4cef-b734-e683d4e258aa
, but open the latest and you can see the XML.
Now the XML isn't very interesting.
<coverage line-rate="0.4882" branch-rate="0.465" version="1.9" timestamp="1745620667" lines-covered="1101" lines-valid="2255" branches-covered="299" branches-valid="643">
<sources>
<source>C:\path\to\app\MyApp\</source>
</sources>
<packages>
<package name="MyAppPackage" line-rate="0.4882" branch-rate="0.465" complexity="734">
<classes>
<class name="Program" filename="Program.cs" line-rate="0" branch-rate="1" complexity="2">
<methods>
<method name="<Main>$" signature="(System.String[])" line-rate="0" branch-rate="1" complexity="1">
<lines>
<line number="16" hits="0" branch="False"/>
<line number="20" hits="0" branch="False"/>
</lines>
</method>
<!-- ... -->
You have to turn that into a more interesting report.
This Stackoverflow answer explains how:
This tool quickly generate Html reports from coverage file. Works quite well and does not require complex activities, can be easily included in the build process.
From the README:
Install:
dotnet tool install -g dotnet-reportgenerator-globaltool
Run:
reportgenerator [options]
which, in my case, if I'm already in the same folder as the coverage.cobertura.xml
file, looks like this:
reportgenerator -reports:".\coverage.cobertura.xml" -targetdir:"coveragereport" -reporttypes:Html
... which, because we said so in the options, creates a folder named coveragereport
in the same dir, and within that are two html files that are identical except for their file extensions, index.htm
and index.html
. Far be it for a Microsoft-adjacent tool to stop producing three-letter file extensions.
And then that report looks incredible:
I have no idea why I redacted so much of that. Also note this is running against a very early stage piece of code. This coverage is obviously horrendous. But the coverage report isn't!