I saw a Reddit post asking which test framework to use: xUnit, NUnit, or MSTest. I’ve used xUnit almost exclusively for years and don’t have firm enough experience with the others to recommend for or against them. Any bias I have against MSTest is probably years out of date. I hear it’s pretty good now!
Instead, I thought I would list my top test framework considerations.
You’ll spend more time staring at error messages than any other activity. A framework that provides clear and actionable feedback on failed test cases will save thousands of hours over the lifetime of your project.
I don’t particularly like any of the built-in assertion libraries. They get the job done but always leave me wanting more.
I also strongly dislike
Assert.AreEqual: which value comes first, the expected
or the actual? I think it’s different between test frameworks! I can never
remember, and if I get it wrong, I get very misleading error messages when the
I prefer to install FluentAssertions. The API for checking values doesn’t have ambiguity; it has a wide variety of assertions and generates obvious error messages.
It’s very convenient if your test framework can generate or templatize test cases. This will save you a lot of repetitive setup and let you cover many edge cases quickly. Choose a framework with robust and typesafe support.
This capability was a more substantial differentiator in the past, but nowadays, they all have valuable utilities. You should be able to define test data through attributes or other methods on the test class.
Nothing is more challenging to diagnose than test cases that fail due to data leaking between individual tests.
Prefer a test framework that instantiates a new instance of your test class for each test. This forces you to go out of your way to bleed data.
I like xUnit here because the setup is just a constructor, and tear down is
IDisposable. Standard c# conventions!
As your suite grows, it’ll be a benefit to run tests in parallel to complete the test run faster and get feedback earlier.
XUnit is so good at this that I once had to introduce throttling in my integration tests to avoid smoking my local SQLServer.