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 (0)