Publish Code Coverage of .NET app in SonarQube from Azure DevOps

SonarQubeThis article enhances the one where I explained the steps of generation and publication code coverage in Azure DevOps pipeline. This time we go further and implement “shift-left” strategy by introducing SonarQube in Azure DevOps CI/CD process. Our task here will be not only configure code analysis in SonarQube but also get code coverage metrics so we can use it in quality gates and follow “clean as you code” principle.

These two steps of the pipeline will perform tests, generate code coverage results and publish code coverage results in Azure DevOps pipeline in “Code coverage” tab:

However, code coverage results will be generated in Cobertura format which is not supported by SonarQube, thus cannot be imported and if you try to import it into SonarQube you will see the following error:

WARN: Could not import coverage report ‘/agent/_work/_temp/sonarcoverage/SonarQube.xml’ because ‘Missing root element <CoverageSession> in /agent/_work/_temp/sonarcoverage/SonarQube.xml at line 2’. 
The things are simpler in case we leverage Azure DevOps Windows image for your build. In these cases, the .NET Framework scanner will automatically find the coverage output generated by the --collect "Code Coverage" parameter without the need for an explicit report path setting. It will also automatically convert the generated report to XML. No further configuration is required.

However, in case of tests in Linux images the option above is unavailable and we need to get code coverage  in one of dotCover, OpenCover or Coverlet formats.  For that we can use reportgenerator extension and convert Cobertura report or pass special parameter

to dotnet test command to get desired format.

I prefer the second option and here is the dotnet test commmand that will generate code coverage reports in both OpenCover (for SonarQube) and Cobertura (for Azure DevOps) formats:

And now we have two files of different formats and we can pass the Opencover report to SonarQube with

sonar.cs.opencover.reportsPaths parameter.

After that you will get coverage metrics in SonarQube:


Full yml pipeline is now available and can be applied immediately! You can get it here  

Good luck!


Want me to do this for you? Drop me a line: itgalaxyzzz {at} gmail [dot] com