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
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;
}
}
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));
}
}
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
The Ndepend dialong pops up that shows the project that will be analyzed the one that will be filtered out
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.
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>
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
Next Click on the Analysis tab and then select settings for Code coverage
Next, Use the first Option to import your test coverage file from your testResults folder and click Ok
All you have to do is run NDepend Analysis again(you can also automate this process in your CI/CD pipeline)
After the analysis is done, simple Navigate to your NDepend 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));
}
}
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
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.
Top comments (0)