Basic unit testing with xUnit
Unit testing has many benefits and will help you identify bugs and problem areas in your code. If we look at the benefits of unit testing they are as follows:
In this article, I will be adding a new xUnit test project to my solution and giving some information on the basics of unit testing with xUnit to get you started. There will be a follow-up article on how this can be applied directly to a project to test the code within the project. This article is not a follow-on from my previous article however references are made below to the project structure I created in my previous article.
First, we need to add a new project to the solution. The new project will be a "xUnit Test Project", so right-click your solution, hover "Add" and click "New Project...". Search for a template using the following text: "XUnit". Select "xUnit Test Project" making sure it is for C# and not VB and click "Next".
Name the Project in accordance with what it will be testing. In this case, I will be naming it "V3.Practice.Tests" and the reason why I like to name it specifically is so that I can easily identify the test project for each function/project and know which function/project the test applies to. Click "Next". Select Target Framework as ".NET Core 3.1 (Long-term support)" to match the function we are going to be testing. Click "Create" and wait for the project to be added and compiled.
Now that the test project has been added, you will see the following code in the file "UnitTest1.cs":
using System
using Xunit;
namespace V3.Practice.Tests
{
? ? public class UnitTest1
? ? {
? ? ? ? [Fact]
? ? ? ? public void Test1()
? ? ? ? {
? ? ? ? }
? ? }
};
Before we start writing code, we will need an understanding of the "[Fact]" attribute and explore other attributes.
We are going to rename "Test1" to be "Fact_BasicMath_Equal" and then add a new Fact test and call it "Fact_BasicMath_NotEqual". Your code will look as follows:
using System
using Xunit;
namespace V3.Practice.Tests
{
? ? public class UnitTest1
? ? {
? ? ? ? [Fact]
? ? ? ? public void Fact_BasicMath_Equal()
? ? ? ? {
? ? ? ? }
? ? ? ? [Fact]
? ? ? ? public void Fact_BasicMath_NotEqual()
? ? ? ? {
? ? ? ? }
? ? }
};
There are three steps I like to follow with my unit tests and they are as follows:
Using what is mentioned above, we will make our class look as follows:
using System;
using Xunit;
namespace V3.Practice.Tests
{
? ? public class UnitTest1
? ? {
? ? ? ? [Fact]
? ? ? ? public void Fact_BasicMath_Equal()
? ? ? ? {
? ? ? ? ? ? // Arrange
? ? ? ? ? ? int a = 2;
? ? ? ? ? ? int b = 2;
? ? ? ? ? ? int expected = 4;
? ? ? ? ? ? // Act
? ? ? ? ? ? var response = Add(a, b);
? ? ? ? ? ? // Assert
? ? ? ? ? ? Assert.Equal(expected, response);
? ? ? ? }
? ? ? ? [Fact]
? ? ? ? public void Fact_BasicMath_NotEqual()
? ? ? ? {
? ? ? ? ? ? // Arrange
? ? ? ? ? ? int a = 2;
? ? ? ? ? ? int b = 3;
? ? ? ? ? ? int expected = 4;
? ? ? ? ? ? // Act
? ? ? ? ? ? var response = Add(a, b);
? ? ? ? ? ? // Assert
? ? ? ? ? ? Assert.NotEqual(expected, response);
? ? ? ? }
? ? ? ? private int Add(int a, int b)
? ? ? ? {
? ? ? ? ? ? return a + b;
? ? ? ? }
? ? }
}
Now, we need to add a new view so we can see our tests. Click on "View" in the top left and select "Test Explorer".
Once the test explorer is visible, click the button indicated and select "Dock" from the menu and you will see the following:
Now, we can see that the two tests we created are showing and we can now run them. Click the following button to run all tests in view:
领英推荐
This will run our tests and show us the result of each test indicated with a green icon or a red icon. Your tests should look as follows:
If we are to change a test to fail, it will look as follows:
As you can see, a test failed and we are given an Error Message which can help us diagnose the issue and resolve it.
We will now perform some tests using [Theory] and [InlineData], this allows us to have multiple tests against a single method which can greatly increase the protection of code quality.
Add the following to your class:
[Theory]
? ? ? ? [InlineData(2)]
? ? ? ? [InlineData(4)]
? ? ? ? [InlineData(5)]
? ? ? ? public void Theory_BasicMath_IsEvenNumber(int number)
? ? ? ? {
? ? ? ? ? ? // Arrange
? ? ? ? ? ? int numberToCheck = number;
? ? ? ? ? ? // Act
? ? ? ? ? ? bool IsEqualNumber = CheckEven(numberToCheck);
? ? ? ? ? ? // Assert
? ? ? ? ? ? Assert.True(IsEqualNumber);
? ? ? ? }
? ? ? ? [Theory]
? ? ? ? [InlineData(1)]
? ? ? ? [InlineData(3)]
? ? ? ? [InlineData(4)]
? ? ? ? public void Theory_BasicMath_IsOddNumber(int number)
? ? ? ? {
? ? ? ? ? ? // Arrange
? ? ? ? ? ? int numberToCheck = number;
? ? ? ? ? ? // Act
? ? ? ? ? ? bool IsEqualNumber = CheckEven(numberToCheck);
? ? ? ? ? ? // Assert
? ? ? ? ? ? Assert.False(IsEqualNumber);
? ? ? ? }
? ? ? ? private bool CheckEven(int a)
? ? ? ? {
? ? ? ? ? ? return a % 2 == 0;
? ? ? ? }
A breakdown of what you see happening above:
In the "Test Explorer" we can now see that we have new tests that we have not run yet:
And if you expand those tests, you will see each [InlineData] attribute is treated as a separate test against the single test method. We can also see each parameter that will be passed in for each test as we defined above using our [InlineData] attribute.
If we "Run All Tests In View" again, we will see the following:
Here we can see that two tests failed, the number 5 is not an even number and the number 4 is not an odd number. If we replace the 5 with a 6 and the 4 with a 5 and run it again, we will see the following:
All our tests have now passed!
This brings us to the end of the article, I hope that you have learned something new and/or enjoyed this article! All feedback is extremely welcome! The next article will look to covering xUnit in depth while using Moq to assist with the unit tests. Until next time!