Unit Testing Frameworks for C#
What is Unit Test?
Unit testing involves the testing of each unit or an individual component of the software application. It is the first level of functional testing. The aim behind unit testing is to validate unit components with its performance.
A unit is a single testable part of a software system and tested during the development phase of the application software The purpose of unit testing is to test the correctness of isolated code. A unit component is an individual function or code of the application. white box testing approach used for testing and usually done by the developer.
Why Unit Testing?
In a testing level hierarchy , unit testing is the first level of testing done before integration and other remaining levels of the testing. It uses modules of the testing process which reduces the dependency of waiting for Unit testing framework, stubs, drivers and mock objects are used for assistance in unit testing. For example, let’s say that we had the Calculator class and that contained an Add(int, int) method.
Let’s say that you want to write some code to test that method.
public class CalculatorTester { public void TestAdd() { var calculator = new Calculator(); if (calculator.Add(2, 2) == 4) Console.WriteLine("Success"); else Console.WriteLine("Failure"); } }
No magic there. I just create a test called “CalculatorTester” and then write a method that instantiates and exercises Calculator.Add(). You could write this knowing nothing about unit testing practice at all. And, if someone had told you to automate the testing of Calculator.Add(), you may have done this exact thing.
What Are Unit Test Frameworks?
Well, as you can imagine, having this sort of unit testing across your entire codebase could prove cumbersome. You’d write lots of classes just like this one and then… what? You’d look at all of the console output for failures, only to discover that failure proved pretty inscrutable.
Most likely you would then have the clever idea to include the name of the test in the output so that you could see what had failed. From there, you might start to add some sort of GUI-like feedback to the results, to present them in a more readable fashion. From there, who knows? Maybe you write a Visual Studio plugin or maybe you find a way to incorporate this test suite into your build?
Well, it turns out that if you did all that stuff, you would have built yourself a unit testing framework. Let’s take a look now at what some code written for an actual unit test framework (MS Test) looks like.
[TestClass] public class CalculatorTests { [TestMethod] public void TestMethod1() { var calculator = new Calculator(); Assert.AreEqual(4, calculator.Add(2, 2)); } }
Unlike the last snippet, we have a bit of magic here. Notice the attributes, TestClass and TestMethod. Those exist simply to tell the unit test framework to pay attention to them when executing the unit test suite. When you want to get results, you invoke the unit test runner, and it executes all methods decorated like this, compiling the results into a visually pleasing report that you can view.
So, with that background established, let’s take a look at your top 3 unit test framework options for C#.
1. MSTest/Visual Studio
First, since I’ve already mentioned it, I’ll lead with MSTest. MSTest was actually the name of a command line tool for executing tests, so we’re really talking about something called the “Visual Studio Unit Testing Framework.” But veterans will colloquially call it MSTest, so let’s use that here.
MSTest ships with Visual Studio, so you have it right out of the box, in your IDE, without doing anything. This lack of friction to getting started is arguably its killer feature. The preferred .NET pattern for unit tests is to have a test project for each production (regular) project in your codebase. With MSTest, getting that setup is as easy as File->New Project. Then, when you write a test, you can right click on it and execute, having your result displayed in the IDE. Pretty neat, huh? And you can also see code coverage without installing any other tools.
On the con side, one of the most frequent knocks on MSTest is that of performance. People find the experience can be sluggish. On top of that, many people struggle with interoperability. After all, Microsoft makes it so you can integrate with other Microsoft/Visual Studio stuff, so making it work with third party things would probably not rate as a priority.
2. NUnit
Unit test frameworks have a history dating back almost 30 years, so they long predated .NET. NUnit started out as a port from Java’s JUnit, but the authors eventually redid it to be more C# idiomatic. So the tool has the rich history of unit testing behind it, but with an appropriately C# flavor.
Because of its independent history, NUnit also has the distinction of interoperating nicely with other tools, such as non-Microsoft build platforms and custom test runners. On top of that, NUnit also has a reputation for fast testing running, and it has some nice additional features as well, including test annotations allowing easy specification of multiple inputs to a given test.
The main downside here is that it doesn’t integrate into Visual Studio the way that MSTest does. Using it means doing extra work, and installing extra tools, regardless of how easy those tools’ authors may make the process.
3. xUnit.NET
The last option that I’ll cover is xUnit.NET (I’ll just call it xUnit for brevity, not to be confused with the xUnit category of test tools). One of the creators of the idiomatic version of NUnit went on to create xUnit. xUnit has a relatively innovative for users to reason about their tests, dividing tests into “facts” and “theories” to distinguish between “always true” and “true for the right data,” respectively.
xUnit earns points for creating extremely intuitive terminology and ways to reason about the language of tests. On top of that, the tool has a reputation for excellent extensibility. Another awesome feature of xUnit is actually not a feature of the software, but a feature of the authors. They have a reputation for commitment, responsiveness, and evangelism.
Comments
Post a Comment