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;
- Visual Studio - Powerful IDE for .NET and C++ development on Windows.
- NUnit - Unit Testing framework for .NET. More here
- Coverlet - Cross-platform code coverage framework for .NET. More here
- ReportGenerator - Powerful code coverage visualization tool. More here
Let's set-up our test application.
Create a new console Application using .NET Framework
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;
}
}
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
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.
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));
}
}
Your class should look something like this;
Now, right-click on the Test name and select Run Tests
After running the test, we see that we get a passing test;
Next, Install Coverlet by navigating to the command line of your test project and running this command;
dotnet add package coverlet.collector
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>
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
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
Next, run this command;
reportgenerator -reports:"TestCoverageDemo\TestProject1\TestResults\e36a31dc-6f0e-410a-a860-cc32118ec3a8\coverage.cobertura.xml" -targetdir:"coverageresults" -reporttypes:Html
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
Navigate into the coverageresults
folder and click on index, the coverage results have been presented in a nice way and we have 100% coverage;
Scrolling down, we will see a better breakdown of what is covered
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.
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;
}
Now, in your test explorer run the test Test1
again
We see that the test still passes as expected.
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
reportgenerator -reports:"TestCoverageDemo\TestProject1\TestResults\e36a31dc-6f0e-410a-a860-cc32118ec3a8\coverage.cobertura.xml" -targetdir:"coverageresults" -reporttypes:Html
Now, navigate to the coverageresults folder once more and click the index.
We see that the coverage has dropped from 100% to 70%
If we investigate further by checking TestCoverageDemo.Calculator class, we can see why;
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));
}
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.
We see that the test coverage is back to 100%.
Checking TestCoverageDemo.Calculator will reveal a further breakdown;
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)
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
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
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