DEV Community

Olabamiji Oyetubo
Olabamiji Oyetubo

Posted on

Beginner's Guide to Test Coverage with NUnit, Coverlet, and ReportGenerator

Hi guys, today I am going to show a quick and simple way to get started with Test Coverage in your code.

What is Test Coverage?

Test coverage is the percentage of code that is tested by automated tests. That is, it measures the extent to which a codebase is covered by tests we write.

Prerequisites for this tutorial;
Basic knowledge of C# and Unit testing.

Requirements;

  1. Visual Studio - Powerful IDE for .NET and C++ development on Windows.
  2. NUnit - Unit Testing framework for .NET. More here
  3. Coverlet - Cross-platform code coverage framework for .NET. More here
  4. ReportGenerator - Powerful code coverage visualization tool. More here

Let's set-up our test application.

Create a new console Application using .NET Framework

Create console app

Give your project a name TestCoverageDemo. Then select .NET framework 4.7.2 as the target framework and click Create.

Great, now In your application add a simple class called Calculator and add the following code



public class Calculator
{
    public static int Add(int number)
    {
        int sum = 20;
        return sum + number;
    }
}


Enter fullscreen mode Exit fullscreen mode

This class contains a simple implementation that takes a number, adds 20 to it, and returns the result. Seems simple enough.

Write a unit test for the implementation.

Create a new project by right-clicking on your solution file and selecting Add -> New project

Search NUnit

Configure Nunit project

You can leave the default NUnit project name of TestProject1. Click next. Select .NET Framework 4.7.2 as the target framework and click Create.

After Creating, your project should look like this.

Project Structure

Next, add a reference to the main TestCoverageDemo project from the test project

Now, Add the following code to the Class UnitTest1



    public class Tests
    {
        [SetUp]
        public void Setup()
        {
        }

        [Test]
        public void Test1()
        {
            // Arrange
            int number = 2;
            int expected = 22;

            // Act
            int actual = Calculator.Add(number);

            // Assert
            Assert.That(actual, Is.EqualTo(expected));
        }
    }


Enter fullscreen mode Exit fullscreen mode

Your class should look something like this;

Class structure

Now, right-click on the Test name and select Run Tests

After running the test, we see that we get a passing test;

Passing test

Next, Install Coverlet by navigating to the command line of your test project and running this command;



dotnet add package coverlet.collector


Enter fullscreen mode Exit fullscreen mode

Next, create a file in the directory of the test project, and call it coverlet.runsettings, and add this piece of code:



<RunSettings>
  <DataCollectionRunSettings>
    <DataCollectors>
      <DataCollector friendlyName="XPlat Code Coverage">
        <Configuration>
          <ExcludeByFile>**/Program.cs</ExcludeByFile>
        </Configuration>
      </DataCollector>
    </DataCollectors>
  </DataCollectionRunSettings>
</RunSettings>


Enter fullscreen mode Exit fullscreen mode

We're simply adding this so the program.cs does not get in the way of our demo.

Then, while still in the the Test directory, run this command;



dotnet test --collect:"XPlat Code Coverage" --settings coverlet.runsettings


Enter fullscreen mode Exit fullscreen mode

This will run your tests and generate a coverage.cobertura xml file in the TestResults folder

This file is hard to read, so we need the ReportGenerator tool to visualize it.

To Install ReportGenerator, run this command;



dotnet tool install -g dotnet-reportgenerator-globaltool


Enter fullscreen mode Exit fullscreen mode

Next, run this command;



reportgenerator -reports:"TestCoverageDemo\TestProject1\TestResults\e36a31dc-6f0e-410a-a860-cc32118ec3a8\coverage.cobertura.xml" -targetdir:"coverageresults" -reporttypes:Html


Enter fullscreen mode Exit fullscreen mode

This command will go into the location of where the coverage.cobertura file is located, parse that file and present the result as a viewable Html site in the target directory we specified: coverageresults

Navigating to the Test project folder, we see that the folder coverageresults has been generated

Coverage folder generated

Navigate into the coverageresults folder and click on index, the coverage results have been presented in a nice way and we have 100% coverage;

Coverage results

Scrolling down, we will see a better breakdown of what is covered

Coverage Breakdown

Clicking on TestCoverageDemo.Calculator we see that we have 100% of coverage and that all the lines of code we've written are covered by the unit test.

Line Coverage

Great.

Let's make some modifications to the Add method in the calculator class, by adding this code:



 public static int Add(int number)
 {
     int sum;

     if(number % 2 == 0)
     {
         sum = 20;
     }
     else
     {
         sum = 30;
     }
     return sum + number;
 }


Enter fullscreen mode Exit fullscreen mode

Now, in your test explorer run the test Test1 again

We see that the test still passes as expected.

Test passes after changes

Now, Let's try to recalculate the test coverage once more. Run these 2 commands in the directory of the test project again,



dotnet test --collect:"XPlat Code Coverage" --settings coverlet.runsettings


Enter fullscreen mode Exit fullscreen mode


reportgenerator -reports:"TestCoverageDemo\TestProject1\TestResults\e36a31dc-6f0e-410a-a860-cc32118ec3a8\coverage.cobertura.xml" -targetdir:"coverageresults" -reporttypes:Html


Enter fullscreen mode Exit fullscreen mode

Now, navigate to the coverageresults folder once more and click the index.

Coverage has reduced

We see that the coverage has dropped from 100% to 70%

If we investigate further by checking TestCoverageDemo.Calculator class, we can see why;

Breakdown of coverage after changes

The else block is not covered by the test because we have not created any scenario where that part of the code is tested.

Let's fix that.

Add this piece of code to the UnitTest1 class;



 public void Test2()
 {
     // Arrange
     int number = 3;
     int expected = 33;

     // Act
     int actual = Calculator.Add(number);

     // Assert
     Assert.That(actual, Is.EqualTo(expected));
 }


Enter fullscreen mode Exit fullscreen mode

Run the test and see that it passes.

Now run the commands to generate the test coverage once more.

Navigate to coverageresult and click Index once more.

Coverage after changing tests

We see that the test coverage is back to 100%.

Checking TestCoverageDemo.Calculator will reveal a further breakdown;

Breakdown of test coverage by line

And we see that the new code we introduced to the system is now covered by the tests as well.

This was a very brief introduction to test coverage in C# applications we have gone through. You can check out some of the tools we used in this tutorial and use them in your projects as well.

Happy coding

Top comments (3)

Collapse
 
kotto profile image
kotto

Hi, it does not work for .NET Framework 4.7.2 despite being mentioned in the blog, maybe I am doing smth wrong, do you know how to resolve that issue? Im getting following error when trying to install coverlet nuget : The expression "[System.Version]::Parse('')" cannot be evaluated. Version string portion was too short or too long.

Did search stack overflow and have even found one entry on that but with no results when trying to apply the changes, maybe you know how to resolve that since you said it works with .NET Framework 4.7.2 idk hmm any other way to generate coverage report for .NET Framework 4.7.2 project would also be great as I just need to be able to create the coverage report , ReportGenerator seems to work just fine hah I need to stay with .NET Framework 4.7.2 and can not build separate .NET Core Project just for tests

Thanks in advance and have a great day

Collapse
 
bigboybamo profile image
Olabamiji Oyetubo

The expression "[System.Version]::Parse('')" cannot be evaluated.

This has something to do with the command you put into the command line. Instead of copying and pasting, try to manually write the entire command to install coverlet yourself. if you still have any issues, you can drop a screenshot here

Collapse
 
kotto profile image
kotto

Hi, thanks, unfortunately installation from command line is blocked in this project but I will try to find a way around for that, I assume you dont have any suggestions without indepth knowledne on that issue? thanks again and have a great day