xUnit.net
Create a directory structures for projects
Open a shell window. Create a directory structure with the below commands:
mkdir xUnitSample
cd xUnitSample
mkdir Calculator
mkdir Calculator.Tests
The directory and file structure thus far should be as follows:
├── xUnitSample
│ ├── Calculator
│ ├── Calculator.Tests
Create the source project
Make the Calculator
directory the current directory, and create a new project using dotnet new classlib
, and then rename Class1.cs
to Calculator.cs
├── xUnitSample
│ ├── Calculator
| | ├── Calculator.csproj
| | ├── Calculator.cs
│ ├── Calculator.Tests
To use test-driven development (TDD), you first create a maths implementation of the Calculator.cs
class:
using System;
using System.Linq;
namespace Calculator
{
public class Calculator
{
public double Add(params double[] numbers)
{
return numbers.Sum(x => x);
}
}
}
Creating the test project
Make the Calculator.Tests
directory the current directory, and create a new project using dotnet new xunit
.
dotnet new xunit
The test project requires other packages to create and run unit tests. Add the Calculator
class library as another dependency to the project. Use the
dotnet add reference ../Calculator/Calculator.csproj
Rename UnitTest1.cs
to CalculatorTests.cs
├── xUnitSample
│ ├── Calculator
| | ├── Calculator.csproj
| | ├── Calculator.cs
│ ├── Calculator.Tests
| | ├── Calculator.Tests.csproj
| | ├── CalculatorTests.cs
Creating the first test
using System;
using Xunit;
using Calculator;
namespace Calculator.Tests
{
public class CalculatorTests
{
[Fact]
public void SumTest()
{
Assert.Equal(2, Calculator.Add(1, 1));
}
}
}
The Fact
attribute indicates a test method that is run by the test runner. Run dotnet test
to build the tests and class library for running the xUnit test runner contains the program entry point to run your tests.
$ dotnet test
Build started, please wait...
Build completed.
Starting test execution, please wait...
Total tests: 1. Passed: 1. Failed: 0. Skipped: 0.
Test Run Successful.
Test execution time: 1.3167 Seconds
Creating the first theory
xUnit.net includes support for two different major types of unit tests:
Facts are tests which are always true. They test invariant conditions.
Theories are tests which are only true for a particular set of data.
Theories can be useful when we need to run multiple tests with different parameters instead of duplicate the test method, see the example code below:
[Theory]
[InlineData(2, 1, 1)]
[InlineData(15, 5, 10)]
[InlineData(120, 20, 100)]
public void SumShouldCorrect(double expected, double a, double b)
{
Assert.Equal(expected, Calculator.Add(a, b));
}
Passing array in InlineData params
[Theory]
[InlineData(6, new double[] { 1, 2, 3 })]
[InlineData(20, new double[] { 5, 5, 5, 5 })]
[InlineData(120, new double[] { 5, 5, 5, 5, 100 })]
public void SumArraysShouldCorrect(double expected, object numbers)
{
double[] _numbers = (double[])numbers;
Assert.Equal(expected, Calculator.Add(_numbers));
}
Capturing output in unit tests
Unit tests have access to a special interface which replaces previous usage of Console
and similar mechanisms: ITestOutputHelper
. In order to take advantage of this, just add a constructor argument for this interface, and stash it so you can use it in the unit test.
using Xunit;
using Xunit.Abstractions;
namespace Calculator.Tests
{
public class CalculatorTests
{
private readonly ITestOutputHelper Output;
public CalculatorTests(ITestOutputHelper output)
{
this.Output = output;
}
[Fact]
public void LoggerTest()
{
Output.WriteLine("Hello from LoggerTest");
Assert.True(true);
}
}
}
Create a test base
using Xunit.Abstractions;
namespace Calculator.Tests
{
public abstract class TestBase
{
/// <summary>
/// Gets or sets the logger to use for writing text to be captured in the test results.
/// </summary>
protected ITestOutputHelper Output { get; set; }
protected TestBase(ITestOutputHelper output)
{
this.Output = output;
}
}
}
Inherits the TestBase
public class EncryptionTests : TestBase
{
public EncryptionTests(ITestOutputHelper output)
: base(output)
{
}
}
Worth Reading
Last updated
Was this helpful?