How to create code coverage script for your .NET projects

Stefan Acimovic
7 min readOct 19, 2022

--

Whether your client requires you to keep code coverage above a certain percentage or you just want your code to be future-proof, good code coverage is one of the nice things to have in your project.

Not every IDE supports code coverage checking by default (looking at you VS) or if it supports then you have to pay for it (looking at you Rider). The good thing is that for VS there is a couple of free plugins that are available for checking your code coverage (my recommendation is Fine Code Coverage). Still, if you are using Rider, well, you can pay for JetBrains plugin dotCover or you can follow this post and create your code coverage script for free!

If you follow this post in the end you will have your custom code coverage script that you can even use in your CI/CD as one of the steps in the pipeline that will check if your code is covered above some percentage and you can set pipeline to fail if that’s not the case!

So let’s get started!

First, we need to install an open-source tool called coverlet. Coverlet is a cross-platform code coverage framework for .NET, with support for the line, branch, and method coverage. It works with .NET Framework on Windows and .NET Core on all supported platforms.

Run dotnet tool command in CMD or PowerShell:

dotnet tool install --g coverlet.console

This will install coverlet as a global tool and now we can use its commands. Then navigate to your test project folder and run:

coverlet /path/to/test-assembly.dll -t "dotnet" -a "test --no-build"

Let's explain this command. Of course, we start with the coverlet keyword (if you type coverlet you can find all options that can be used), followed up with the relative path to your test project .dll file (note that this is the path to your Test project .dll). Next, we specify the path to the test runner application using —-target or -t , and in our case, it’s dotnet. This is followed by the arguments that will be passed to the test runner using the parameter --targetargs or -a and we pass test --no-build (no build is provided so that dotnet build is not executed but then you will need to be sure that your test-assembly.dll exists, in other words, run dotnet build before this :).

Now run it and you should get something like this:

Result of coverlet command

And like that, you get code coverage for your project. As I mentioned before, you get Line, Branch, and Method code coverage for each module and also as calculated total and average code coverage.

But something I need to add. My example is just a simple project with one service and it’s not near a real project. In real projects, we have a lot more projects for different uses that in this case will for sure show wrong code coverage! For example, why should Program.cs be counted in our code coverage, I mean it can, but should it? So an additional option that we should use is--exclude that can be used to filter expressions to exclude specific modules and types. It uses some specific patterns for excluding that you can find here.

Let’s add one additional service that affects our code coverage but it should be excluded.

Code coverage affected by service that should be excluded

As you can see our total and average code coverage dropped because of the new service. And now let’s upgrade our script to exclude this service:

coverlet /path/to/test-assembly.dll -t "dotnet" -a "test --no-build" --exclude "something to exclude"

And now code coverage for my example is:

Code coverage after service has been excluded

As you can see now, excluded service says it has 100% code coverage and now we get the correct total code coverage that doesn’t consider that excluded service, but as you can see the average does.

Okay, we now have code coverage in numbers but would it be nice to also see what is covered and what's not? Of course, it would! We just need to use something to generate a code coverage report and something to read that report and visually show it.

To generate a code coverage report we have to install the Coverlet Nuget package coverlet.collector to our test project. After that, we can just use the dotnet test command to create a code coverage report (note this will generate the report in your test project folder and if you want to save it somewhere else you can just use --results-directory option and just provide the path where you want to save it):

dotnet test --collect:"XPlat Code Coverage" 

This will generate a TestResult folder with a .xml file that is our code coverage report:

Generated code coverage report

In the background Coverlet uses cobertura. And it generates a report that you can try to read but it’s not really for us, but for a tool that uses that file to show this report visually.

Now we have a code coverage report and we need something to visualize it. For this, we are going to use a dotnet tool called dotnet-reportgenerator. We are going to install it like in the first step we did with the coverlet.

dotnet tool install -g dotnet-reportgenerator-globaltool

Now we can use this tool with keyword reportgenerator. And now we run its command:

reportgenerator -reports:”.\coverage.cobertura.xml”
-targetdir:”coverageresults” -reporttypes:Html

Let’s quickly explain this command. As you can see first we need to provide a relative path to the cobertura report .xml file and provide a target dir where we want to save files that are going to be generated by reportgenerator. In the end, we provide which report type will be used and we will specify HTML (more options can be found on their GitHub). This command also accepts excluding some files that we don’t want to include in our code coverage. This can be done with-filefilters option and then we specify what pattern we want to exclude (again you can find more on their GitHub).

And after you run this command you will get a new folder with all required HTML files:

New generated folder with all required files for visualization of the report

And if you start index.html, you will get something like this:

Visualized code coverage report using reportgenerator tool

And if you click on any service you can have a detailed view of what is covered and what’s not:

Detailed view of service coverage

And here you go! Your own fully visual code coverage! 🎉

We all know that we don't want to type all these commands every time we want to check what’s our project code coverage. So I got you covered (pun not intended :)!

Here is the PowerShell script that I'm currently using for my projects. This could also be the TL;DR part of this post for everyone who doesn’t want to read the rest of the post, but I think this is the better way to generate code coverage for your project by yourself.

As you can see you just need to call this script with one required parameter and that’s an absolute path to your test project .dll file and one more optional parameter and that’s excluded files pattern that will, as you noticed before, exclude files with that pattern from code coverage. I’ve set that code coverage reports are saved on the desktop but you can change it however you want (you can add a parameter for that). And when the script is finished it will automatically open the index.html file and show the code coverage report for your project!

So that’s it, guys! This is the end of the post! If you’ve read the whole post awesome and give yourself a clap! Hopefully, you learned something today, and this can maybe help you in the future if you don’t have some code coverage tool (I hope you don't get into that situation :). You need to know that this is not rocket science and as you can see, you just need a couple of tools to do this yourself.

Guys, if you liked this post feel free to follow me for more stuff like this in the .NET world! And don’t hesitate to post any questions or suggestions, I will be more than happy to answer them :)

--

--

Stefan Acimovic

.NET, Flutter and Leet code enthusiast. I will mostly post stories about them, but there will also be some stories about programming in general. 😄