In this post, I’m creating a code coverage report for a .NET Core project. I’m also using SonarCloud to analyze the project’s quality.

First things first. Code coverage should be something provided for free and out of the box. It should be easy to setup and something that just works. Unfortunately, that’s not the case for .NET Core. For the time being, you can only get code coverage either by using Visual Studio Enterprise (which is not free) or by using the open source tool OpenCover (which is Windows only). .NET Core is supposed to be a cross-platform solution and code coverage should also be available cross-platform. I hope this gets addressed in the near future. There is a GitHub issue which is still open.

My setup

  • Windows 10 Home
  • Visual Studio 2017 Community
  • NuGet on the path

Generating code coverage report

To generate the code coverage report, I used OpenCover and ReportGenerator. The first tool does the heavy lifting of instrumenting the code. The latter generates a friendly HTML report. I have a PowerShell script for generating the report:

nuget install OpenCover -Version 4.6.519 -OutputDirectory packages
nuget install ReportGenerator -Version 3.1.2 -OutputDirectory packages

.\packages\OpenCover.4.6.519\tools\OpenCover.Console.exe `
  -oldstyle `
  -output:opencover.xml `
  -register:user `
  -filter:"+[MyApp*]* -[*.UnitTests]*" `
  -target:"C:\Program Files\dotnet\dotnet.exe" `
  -targetargs:"test --no-build MyApp.UnitTests"

.\packages\ReportGenerator.3.1.2\tools\ReportGenerator.exe `
  -reports:opencover.xml `
  -targetdir:coverage

Some points about this script:

  • the -target and targetargs parameters specify the command that will run the unit tests. Combined, that's dotnet test --no-build MyApp.UnitTests. The --no-build avoids rebuilding the project, assuming we've already built it.
  • the -filter argument is used to exclude the unit tests themselves from the coverage report. The unit test code shouldn't be part of the coverage report because then the numbers get inflated.
  • the -register:user allows this to work without administrator privileges.
  • the -oldstyle parameter is needed for .NET Core.
  • the .csproj files need to have full debug information. That's done with the DebugType property.
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
    <IsPackable>false</IsPackable>
    <DebugType>Full</DebugType>
  </PropertyGroup>

</Project>

OpenCover will generate an XML file at opencover.xml and then ReportGenerator will produce the HTML report at the coverage folder.

Coverage summary
Coverage of a class

Analyzing code quality with SonarCloud

I discovered the other day that it’s possible to use SonarQube online for free for open source projects via a service called SonarCloud.

It’s possible to sign in with your GitHub account, as it’s expected for this type of tools, like Travis, Coveralls, etc. I’ve set it up just for the same .NET Core project, as an experiment.

To use SonarCloud, you need to download the SonarQube scanner for MSBuild.

The usage involves three steps:

  • starting the scanner
  • using MSBuild to build the project
  • stopping the scanner and submitting the analysis to SonarCloud

I have a PowerShell script for that:

if (-Not ($Env:SONAR_LOGIN)) {
  Write-Error -Category InvalidArgument -Message "Please set the SONAR_LOGIN environment variable"
Exit 1
}

SonarQube.Scanner.MSBuild.exe begin /k:"MyApp" `
  /d:sonar.organization="ngeor-github" `
  /d:sonar.host.url="https://sonarcloud.io" `
  /d:sonar.login="$Env:SONAR_LOGIN" `
  /d:sonar.cs.opencover.reportsPaths="opencover.xml" `
  /d:sonar.coverage.exclusions="**/*Test.cs"

MSBuild.exe /t:Rebuild .\MyApp.sln
.\coverage.ps1

SonarQube.Scanner.MSBuild.exe end /d:sonar.login="$Env:SONAR_LOGIN"

Some comments on the script:

  • the SONAR_LOGIN environment variable is my way of committing the script without committing the authorization token. You can get this token from SonarCloud.
  • you need to use an MSBuild that is compatible with .NET Core. In my case, that's the one that comes with Visual Studio 2017 (found at C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin).
  • the SonarQube scanner supports OpenCover, so I'm also running my coverage script here.

The first analysis will take more time, subsequent runs are faster. In the end you get a nice dashboard:

SonarCloud Dashboard

And I see SonarCloud even supports various badges for your README:

Code coverage badge
Quality gate badge
Technical debt badge