The endless battle between the two testing frameworks NUnit and xUnit is a hot potato and in this blog post I intend to give my two cents on this topic.
As a consultant I work with both these frameworks everyday so I have a lot of experience working with both of them so hopefully I’ll be able to declare a winner in this lifelong battle once and for all.
I’ve split the comparison into eight rounds all covering the steps needed from installing to running tests with these two frameworks. Let’s get started!
After this article have been published, I've received some amazing feedback from a NUnit Core Team member. Round 2, You can skip TestFixture, it's not needed. I did not know that by the time I wrote this. And round 6: You can change to instance by test.
Round 1: Installation
Both NUnit and xUnit are super easy to install using nuget (Install-Package nunit vs. Install-Package xunit). After you’ve installed your test framework you can get started writing your tests. Not much to compare here, both easy and straightforward. One point each!
NUnit (+1p): 1p
xUnit (+1p): 1p
Round 2: Creating a test class
In NUnit you need to add an attribute called [TestFixture] in order for your test class to be a part of your test run, but this is not necessary in xUnit which will find your tests without any attribute. Point goes to xUnit.
xUnit (+1p): 2p
Round 3: Setup tests
In NUnit in order to run some setup methods before and after each of your tests you need to use the [SetUp] and [TearDown] attributes and just as with the test class this is not necessary in xUnit. In xUnit you create a standard class Constructor and if you need code to run after each test you make sure your code implements the IDisposable interface. Again point goes to xUnit for not introducing more concepts but instead letting us use concepts we are already familiar with as .NET developers.
xUnit (+1p): 3p
Round 4: Writing tests
When it comes to writing a test in NUnit, a [Test] is always a test, regardless if it has parameters or not. This is not the case with xUnit. There is nothing called a [Test] in xUnit, instead they are either called [Fact] or [Theory] depending if you are going to use parameters or not. Point goes to NUnit. A test is a test
NUnit (+1p): 2p
Round 5: Adding parameters to your test
As mentioned in the previous round, xUnit splits tests into either a [Fact] or a [Theory]. If you add a parameter [InlineData()] to a [Fact] you will get an error in your test run and if you don’t add parameters to a [Theory] this will also fail. I cannot begin to explain how annoying this is. I write a lot of tests and sometimes when I start writing a test I might not be sure yet if I will be needing parameters or not. Sometimes when doing integration tests I might start to write an experimental test just to get something working before I refactor it and move my hardcoded values into parameters. So in NUnit I just need to move these values in to a [TestCase()] but in xUnit I need to move them in to a [InlineData()] and remember to change the [Fact] to a [Theory]. Super annoying. Point goes to NUnit!
NUnit (+1p): 3p
Round 6: Running tests
When it comes to running your tests there is a slight difference that you might not notice up front. I’ve mentioned in a previous blog post (PARALLELISM: NUNIT VS. XUNIT) that both these frameworks handle parallelism differently and I like the fact that xUnit has it enabled by default instead of NUnit having it disabled. I’ve also found that xUnit creates a new instance per test, whereas NUnit creates a new instance per class (or [TestFixture]). If you reset all your dependencies properly in your [SetUp] and [TearDown] this won’t be a problem in NUnit, but you could potentially forget to reset one dependency and find yourself having tests that might pass in one given order and fail in another due to the fact that your tests share the same instance of the class. Point goes to xUnit!
xUnit (+1p): 4p
Round 7: Ignore or skip a test
I mentioned in another blog post (GETTING STARTED WITH UNIT TESTING #2: DON'T GET STUCK!) that sometimes you get stuck and the only thing you can do is ignore the test and come back later. In NUnit this is called Ignore and in xUnit this is called Skip but they essentially do the same thing. Point to both frameworks.
NUnit (+1p): 4p
xUnit (+1p): 5p
Round 8: Finding help
If you find yourself so stuck that you need to go find help, I’ve found that NUnit seems to be a lot more widely used than xUnit. A quick search on Google and StackOverflow shows almost double the amount of results on NUnit than xUnit and also for me who is a big fan of Umbraco, this seems to be the case on our.umbraco.com. Also the source tests for Umbraco are written in NUnit, the documentation and most people blogging about testing in Umbraco seems to be using NUnit so that’s another point to NUnit.
NUnit (+1p): 5p
We have a tie, judge ruling!
So it seems we have a tie but for the sake of declaring a winner I will give the final point to NUnit. I guess it all comes down to personal preferences. Personally I must say I prefer NUnit mostly because I don't have to care if I should use a [Fact] or a [Theory], a [Test] is always a test. This might seem like a trivial thing but it’s actually really annoying if you write a lot of tests.
But the truth is it doesn’t matter that much. They’re both great testing frameworks and the differences are so small that you are not going to regret choosing one or the other. I work with both xUnit and NUnit on a daily basis and most of the time I hardly notice the differences. But for the sake of declaring a winner: My personal favourite is NUnit!
Cheers friends! ❤️