Notes on Code Coverage for .NET Applications
07/15/2025
3 minutes
This post summarizes my learnings about code coverage visualization in SonarQube and GitLab.
Formats for GitLab and SonarQube
I'll detail different options for displaying code coverage for a C# (.NET) application in both tools. GitLab uses Cobertura coverage files. When such a file is uploaded as a job artifact, GitLab marks each line as covered or uncovered in a pull request (Merge Request in GitLab terms). GitLab also provides other coverage features that are not covered in this post.
SonarQube accepts several coverage formats. As of writing this post, for .NET applications it works with coverage files in these formats:
Visual Studio coverage format (XML)
OpenCover (note: the OpenCover tool is archived on GitHub)
DotCover
Cobertura (support is coming soon)
Why use both tools? GitLab provides immediate visualization in pull requests, which helps streamline code reviews. SonarQube offers a more detailed summary, including branch coverage and additional features like static code analysis, justifying its use.
Coverage Collectors
Among the many coverage data collectors, the most common ones are:
The built-in Visual Studio collector
DotCover
Coverlet is an excellent choice because it is included in the default xUnit test project template and supports multiple output formats (including Cobertura and OpenCover).
The Visual Studio coverage collector supports binary and XML formats, while dotnet-coverage supports Visual Studio formats and Cobertura.
Coverlet stands out as the most versatile option since it can output both OpenCover and Cobertura formats. However, some might prefer to avoid the archived OpenCover format.
Coverage File Format Conversion
Tools like dotnet-coverage can merge coverage files, which is useful when dealing with multiple test projects in a .NET solution. This tool can also convert between its supported formats.
ReportGenerator is another powerful tool that can:
Merge coverage files
Generate reports (HTML, XML, etc.)
Convert between file formats
Note: The OpenCover format is only available for sponsors of the ReportGenerator GitHub project.
Viable Configurations
While many tools, features, and formats are available, only a few configurations provide optimal results.
The Coverlet data collector is recommended because it supports the widest variety of formats. Here are two possible approaches:
Use Coverlet to generate both OpenCover and Cobertura files
Consider that OpenCover is not future-proof
Be aware that SonarQube's merging of coverage files can be slow
Use Coverlet to generate only Cobertura files (for GitLab) and then convert them:
Using dotnet-coverage for conversion: Note that the VS-XML format loses branch coverage details in SonarQube
Using ReportGenerator: This generates coverage in SonarQube format while retaining branch coverage, though merging files is slower than with dotnet-coverage
Outlook
In the near future, SonarQube is expected to support Cobertura files for .NET projects, which will simplify the setup and provide more options. One such case that stands out would be using the dotnet-coverage tool to capture, output coverage, and merge coverage files using the Cobertura format.