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; }
}
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;
}
}
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:
- NUnit
- NUnit3TestAdapter
- NunitXml.TestLogger
- Microsoft.NET.Test.Sdk
- Microsoft.CodeCoverage
- coverlet.msbuild
- ReportGenerator
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\
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);
}
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).
The test report for the UserService
class looks something like this:
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)