Visualize Code coverage in .NET applications using NDepend and NUnit

bigboybamo

Olabamiji Oyetubo

Posted on November 6, 2024

Visualize Code coverage in .NET applications using NDepend and NUnit

In this tutorial, we're going to visualize Code Coverage metrics using NDepend.

What is NDepend?
NDepend is a feature rich static code analysis tool that helps .NET developers analyze, maintain and improve code quality. It provides detailed metrics, visualization of code dependencies, and quality rules to identify technical debt, architectural issues, and potential problems in C# and VB.NET codebases.

For this tutorial, we are going to use NDepend's inbuilt dashboard to visualize the percentage of code we have tested.

For readers new to unit testing and code coverage, I've written detailed introductions on both topics: Unit Testing Guide and Code Coverage Explained.

Before starting, download NDepend from their official website. You can opt for either the trial version or Pro version (if you have purchased a license).

Our IDE of choice will be Visual Studio on Windows, so follow this guide on how to setup the NDepend extension on your Visual Studio instance.

Create a new console Application by running this command;

dotnet new console -o CalculatorApp
Enter fullscreen mode Exit fullscreen mode

Open up your project in Visual studio and add a new class Calculator and add the below code;

    public class Calculator
    {
        public int Add(int x, int y)
        {
            return x + y;
        }

        public int Subtract(int x, in int y)
        {
            return x - y;
        }

        public int Multiply(int x, int y)
        {
            return x * y;
        }

        public int Divide(int x, int y)
        {
            return x / y;
        }
    }
Enter fullscreen mode Exit fullscreen mode

These are basic operations that can be done on a calculator.

Okay great, let's create a unit test project for our implementation.

Create a new project by right-clicking on your solution file and adding a new NUnit project and call it CalculatorTests

Don't forget to add a Project reference to CalculatorApp

Now, let's add the following code to the Class UnitTest1

public class Tests
{
    Calculator calc;
    [SetUp]
    public void Setup()
    {
        calc = new Calculator();
    }

    [Test]
    public void Add_TwoNumbers_ReturnsSum()
    {
        //Arrange
        int numOne = 5, numTwo = 10, expectedValue = 15;

        //Act
        var actualValue = calc.Add(numOne, numTwo);

        //Assert
        Assert.That(expectedValue,Is.EqualTo(actualValue));
    }

    [Test]
    public void Subtract_TwoNumbers_ReturnsDifference()
    {
       //Arrange
       int numOne = 10, numTwo = 5, expectedValue = 5;

       //Act
       var actualValue = calc.Subtract(numOne, numTwo);

       //Assert
       Assert.That(expectedValue, Is.EqualTo(actualValue));
    }
}
Enter fullscreen mode Exit fullscreen mode

When you run the tests, we get 2 passing tests.

Next, we want to use NDepend in our project. From Visual studio extensions Tab, locate the Ndepend extension and Select Attach New NDepend project to Current VS Solution like below

Add NDepend project

The Ndepend dialong pops up that shows the project that will be analyzed the one that will be filtered out

NDepend dialog

Go ahead and click on the Analyze a Single .NET Assembly button

NDepend will analyize your project for various metrics and give you a great report that tells you a lot about your code.

If its your first time using NDepend, you'll also get an nice dialog that shows what was just done.

NDepend beginner

Now, let's try to measure our code coverage. NUnit projects now come with Coverlet out of the box to enable us generate code coverage in our test project.

First, 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>
          <Format>opencover</Format>
          <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 and setting the output format to OpenCover so NDepend can parse the file.

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

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

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

Now, let's use NDepend to parse this file and see our test coverage from the NDepend dashboard

From the Extensions Tab, Select NDepend and then select NDepend Project properties

NDepend Project Properties

Next Click on the Analysis tab and then select settings for Code coverage

Analysis - Coverage

Next, Use the first Option to import your test coverage file from your testResults folder and click Ok

Import coverage files from directory

All you have to do is run NDepend Analysis again(you can also automate this process in your CI/CD pipeline)

Run analysis

After the analysis is done, simple Navigate to your NDepend Dashboard

Dashboard

From the NDepend Dashboard, we see a bunch of useful metrics that can help you improve the overall state of your project.

For this tutorial, we're mostly concerned about code coverage, and we can see that we have it at 50% but that is to be expected, since we only wrote tests for 2 out of our 4 methods.

Let's fix that.

Modify UnitTest1 class so it looks like this;

public class Tests
{
    Calculator calc;
    [SetUp]
    public void Setup()
    {
        calc = new Calculator();
    }

    [Test]
    public void Add_TwoNumbers_ReturnsSum()
    {
        //Arrange
        int numOne = 5, numTwo = 10, expectedValue = 15;

        //Act
        var actualValue = calc.Add(numOne, numTwo);

        //Assert
        Assert.That(expectedValue, Is.EqualTo(actualValue));
    }

    [Test]
    public void Subtract_TwoNumbers_ReturnsDifference()
    {
        //Arrange
        int numOne = 10, numTwo = 5, expectedValue = 5;

        //Act
        var actualValue = calc.Subtract(numOne, numTwo);

        //Assert
        Assert.That(expectedValue, Is.EqualTo(actualValue));
    }

    [Test]
    public void Multiply_TwoNumbers_ReturnsProduct()
    {
        //Arrange
        int numOne = 2, numTwo = 3, expectedValue = 6;

        //Act
        var actualValue = calc.Multiply(numOne, numTwo);

        //Assert
        Assert.That(expectedValue, Is.EqualTo(actualValue));
    }

    [Test]
    public void Divide_TwoNumbers_ReturnsRemainder()
    {
        //Arrange
        int numOne = 10, numTwo = 5, expectedValue = 2;

        //Act
        var actualValue = calc.Divide(numOne, numTwo);

        //Assert
        Assert.That(expectedValue, Is.EqualTo(actualValue));
    }
}
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.

The run NDepend analysis once more and navigate to the dashboard

Now, we see that we have 100% code coverage

Total coverage

NDepend can also help you generate reports to track improvements over time, analyxze dependencies between code components, measuring code complexityand more. Check out the docs here

Happy coding.

💖 💪 🙅 🚩
bigboybamo
Olabamiji Oyetubo

Posted on November 6, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related