XUnit vs NUnit What to Choose to Write Clean Code Part 1.

The question of which test framework to choose can appear for a new project or when the team decided to make an experiment trying to improve some internal problem. It’s well known for .net developers that there are three main frameworks: MSTest, NUnit, and XUnit. MSTest is out of scope for this article. I didn’t meet any project which uses it as a primary test framework. I certainly sure such projects exist, and it could be that developers from these projects have written a comprehensive guide щт why to choose MSTest.

xunit vs nunit

We’ll focus on two frameworks, NUnit and XUnit, and they are both quite good and provide common functionally to write tests. Firstly, we’ll look at each separately and then compare both functionalities.

NUnit

NUnit is a unit-testing framework for all .Net languages. Initially ported from JUnit

As it states on the landing page of NUnit.

We’ll cover the latest version of NUnit. At the moment when the article was written, it was 3.13.2. Execute the following commands to add NUnit for your test project:

1
2
dotnet add package NUnit --version 3.13.2
dotnet add package NUnit3TestAdapter --version 4.0.0

With these packages, you get an amazing variety of tools provided by NUnit as attributes. Let’s take a look at some of them, which definitely you need to know:

name description
TestFixture marks that class contains tests and allows to pass arguments into constructor
OneTimeSetUp allows to execute code once before all tests started
OneTimeTearDown it`s a pair to OneTimeTearDown gives us ability to clean resource when all tests finished
SetUp executes before each test
TearDown it`s a pair method to SetUp place where we can clean resources after test execution
Test allows to mark method as test which should be executed
TestCase gives ability to pass params to test and make it configurable
Ignore I hope you will not use it a lot. It skips test case during tests execution
Category define a category for test quite usefull when you need to run only specify category and not run all tests
Author this one as you can guess defines who wrote a test
MaxTime provides a way to setup max execution time for test
Description allows to add readable description to test

It contains much more tools for developers and allows to configure tests for many scenarios.

Let’s check how it looks in code with all these attributes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
[Author("Andrew", "andrewkulta@akyltech.com")]
[TestFixture]
public class TestExample
{
[OneTimeSetUp]
public void OneTimeSetup()
{
Console.WriteLine("Setup just once");
}

[OneTimeTearDown]
public void OneTimeTearDown()
{
Console.WriteLine("Teardown just once");
}

[SetUp]
public void Setup()
{
Console.WriteLine("Setup before each test case");
}

[TearDown]
public void TearDown()
{
Console.WriteLine("TearDOwn after each test");
}

[Test]
[Description("")]
[Author("AnotherAuthor")]
public void Should_DoNothing()
{
Console.WriteLine("Sync test");
}

[Test]
[Category("Async")]
[MaxTime(100)]
public async Task Should_DoNothingAsync()
{
Console.WriteLine("ASync test");
await Task.Delay(200);
}

[TestCase(1)]
[TestCase(2)]
public void Should_BeCase(int param)
{
Console.WriteLine($"param is {param}");
}

[Ignore("example")]
public void Should_BeIgnored()
{
Console.WriteLine("Never invoked");
}
}

XUnit is also known as xUnit.net

xUnit.net is a free, open-source, community-focused unit testing tool for the .NET Framework

It was created with an idea to replace nUnit 2.* and 3.*. xUnit provides a set of tools to write clean and more independent tests.

List most used attributes from xUnit:

name description
Fact marks method as test and allows to configure custom name for method as well as timeout and skip reason.
Theory marks method as special type of test theory it means that this test is valid only with certain list of params
InlineDate allows to provide params for theory tests
Trait gives ability to setup custom metadata for test such as category or author etc…

Let`s take a look at some examples for listed attributes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class xUnitExample : IDisposable
{
public xUnitExample()
{
Console.WriteLine("Executes before each test as setup");
}

[Fact(DisplayName = "Test description")]
[Trait("Category", "CustomCategory")]
public void Should_BeATest()
{
Console.WriteLine("I`m a test");
}

[Fact(Timeout = 100)]
public async Task Should_BeAsyncTest()
{
Console.WriteLine("I`m async test");
}

[Theory]
[InlineData(1)]
public void Should_BeTheory(int param)
{
Console.WriteLine($"param is {param}");
}

[Fact(Skip = "Ignore")]
public void Should_BeSkipped()
{
Console.WriteLine("Should never be invoked");
}

public void Dispose()
{
Console.WriteLine("Executes after each test as teardown");
}
}

As you can see, xUnit uses constructor and IDisposable pattern to implement setup and teardown. I faced developers who thought that xUnit requires implementing Destructor if you want to clear resources.

I think NUnit allows us to write more descriptive unit tests with various attributes for different purposes. But if you choose xUnit for your project, you get a cleaner code without all this mess with attributes. The final decision depends on your preferences, or maybe the team gets used to one of these frameworks.

Conclusion

To be honest, it doesn’t matter which framework you will choose. They both provide a set of tools to write tests, and it’s more important to concentrate on tests themselves.