DEV Community

Eduard Stefanescu
Eduard Stefanescu

Posted on

.NET Core Code Coverage

Originally published at https://eduardstefanescu.dev/2020/02/22/dotnet-core-code-coverage/.


Code coverage tools are a great way to improve the code quality, but there are a lot of tools that require a paid license to use it like dotCover, the Enterprise version of Visual Studio or Visual Studio extensions. After some research, I found out that two free tools combined can generate code coverage reports. The first tool is called Coverlet which generates the code coverage as I wanted and it's also working with .NET Framework. Essentially is creating an XML report file that covers the lines, branches, and methods. And the second tool is ReportGenerator which is used for parsing the generated XML and expose the data in a friendly format.

For this article, I created a small project to demonstrate how is working.
Let's begin with the Business layer; which contains two classes, a dummy User that only has two properties Roles and ManagedCountries.

public class User
{
    public IEnumerable<string> Roles { get; set; }
    public IEnumerable<string> ManagedCountries { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

And a UserService that checks if the User has sufficient rights to delete a country.

I know that the return of the CanDeleteCountry method can be simplified, but I will keep it as it is, just for the sake of this example.

public class UserService
{
  private readonly User user;

  public UserService(User user)
  {
    this.user = user;
  }

  public bool CanDeleteCountry(string country)
  {
    bool isCountryManager = user.Roles.Any(u => u == "CountryManager");
    bool canManageCountry = user.ManagedCountries.Any(c => c == country);

    if (isCountryManager && canManageCountry)
    {
      return true;
    }

    return false;
  }
}
Enter fullscreen mode Exit fullscreen mode

The Tests project uses NUnit, but I saw that Coverlet and ReportGenerator also work with MSBuild and xUnit, for those you only need another TestAdapter and TestLogger. The packages installed for this project are:

In order to get the code coverage, a script is needed that will run the tests, create the XML file report and generate an HTML file with the reports.

dotnet test --logger "trx;LogFileName=TestResults.trx" ^
            --logger "nunit;LogFileName=TestResults.xml" ^
            --results-directory ./Coverage ^
            /p:CollectCoverage=true ^
            /p:CoverletOutput=Coverage\ ^
            /p:CoverletOutputFormat=cobertura ^
            /p:Exclude="[nunit.*]*

dotnet %userprofile%\.nuget\packages\reportgenerator\4.4.7\tools\netcoreapp3.0\ReportGenerator.dll ^
    "-reports:Coverage\coverage.cobertura.xml" ^
    "-targetdir:Coverage" ^
    -reporttypes:HTML

start .\Coverage\index.htm\
Enter fullscreen mode Exit fullscreen mode

I've created a batch file to be easier to run all the commands in a single unit. Also please note that if you are using Mac or Linux, the nuget packages path, would be: ~/.nuget/packages.
The first command will run the tests and will generate the XML file used by the second command to generate the report. And the third command will open index.html.
Please consider adding the Coverage folder into .gitignore if you are working on a team, this is just for local purposes and it would be nice if the project you are working on has on the CI build process a step where the code coverage is generated.

So now, with all that in place, let's see the results. I wanted to test only if the User is not a CountryManager and skip the other conditions that will also check for the managed countries because I wanted to generate a report with all the available covered areas.

[Test]
public void CanDeleteCountry_UserIsNotCountryManager_ReturnsFalse()
{
  var user = new User
  {
    Roles = new[] { "User" },
    ManagedCountries = new[] { "Sweden" }
  };
  var userService = new UserService(user);

  bool canDeleteCountry = userService.CanDeleteCountry("Romania");

  Assert.IsFalse(canDeleteCountry);
}
Enter fullscreen mode Exit fullscreen mode

Let's take a look at the code coverage report. When the index.html file is open, the first page contains an overview of the ran tests, it offers a brief summary of the report and a grouping feature, that can be used to view the files on different layers (i.e. No grouping, By assembly, By namespace, Level: 1 and By namespace, Level: 2).
image
The test report for the UserService class looks something like this:
image
The color code is the same as in the other tools, but what I like is that it also has branch coverage, which in the above picture is the yellow area.
In conclusion, these two tools are great and don't cost anything, also can be configured to run through all test projects and generate more comprehensive code coverage.
Here is the repository link with all the code from this article: https://github.com/StefanescuEduard/NetCoreCodeCoverage. I kept the Coverage folder on the repository just for testing purposes.
Thanks for reading this article, if you find it interesting please share it with your colleagues and friends. Or if you find something that can be improved please let me know.

Top comments (0)