NUnit uses open source tools to test .NET code

Unit tests are an important part of modern application development. NUnit is perhaps the best-known way of using them with .NET code.

NUnit uses open source tools to test .NET code
Thinkstock

Modern application development depends on tests. The software development life cycle has evolved to take a test-first approach, with tests designed from the same requirements as your code. At the heart of this model is the unit test, ensuring that each module of your code responds to inputs correctly and delivers the expected outputs.

That requires developing tests before you even write your first line of code, providing a framework that ensures that all code in a CI/CD (continuous integration and continuous delivery) system has passed functional tests before being assembled into an application or service. This test-first approach is central to agile development methodologies, giving sprints a target that can measure progress.

Introducing NUnit

You need to choose a test framework early in your development process, finding an appropriate tool for your development platform. Java developers are likely to choose the familiar JUnit, and .NET developers likely to select the similar NUnit. NUnit and JUnit are part of a loose family of tools derived from the original Smalltalk SUnit testing framework, all building on a similar architecture that uses test runners to run tests, cases to describe the tests, fixtures to manage state and context for a test, all wrapped up into a suite of tests to be passed.

NUnit is part of a related family of tools, so you can bring existing test development skills from other platforms to .NET (and vice versa). Tests are written in .NET languages, but the underlying concepts and structure remain similar, ensuring a minimal learning curve. There’s plenty of documentation, so you should be able to get up and running very quickly. You’re not limited to Windows applications; there’s support for testing mobile apps written using Xamarin.

Like much of the rest of the .NET platform, NUnit is an open source project supported by the .NET Foundation. Its core development team is well known in the community, having worked on the project for more than a decade. The current release, Version 3, is a major rewrite, with the latest build rolled out at the end of March 2022, adding improved support for .NET 6. If you began to use NUnit tests with the .NET Framework, you can bring the same test tools to the new .NET Core-based releases, ensuring your tests can migrate to current .NET releases along with your code.

Getting started with NUnit

NUnit is straightforward. Like many .NET tools, the packages you need in order to run the test framework are installed from NuGet or can be downloaded as a Windows installer. First, install the NUnit and NUnit.Console packages in your solution. The first needs to be referenced from your test code but not from your application. If you want a central repository of NUnit for use across multiple solutions, download and install the zip file, adding it to your path. You can then reference the same NUnit DLL from all your tests, no matter which application they’re testing.

Building your first test is relatively simple. Once you’ve added references to NUnit to your Visual Studio solution, you can start to construct tests in a test project. So, if your code is in a project called AppCode, you’ll create a parallel project for your tests in the same solution, say AppCode.NUnit. This should be used to mirror the methods and classes of your code with appropriate tests.

In your project, install the latest version of NUnit from NuGet. Create a file for your test and add a reference to NUnit.Framework, ready to write your tests. There’s support for most .NET languages, so you can work with C#, F#, Visual Basic.NET, or managed C++. It’s a good idea to use the same language for tests and code to be sure you’re calling methods correctly.

There’s some debate about the best practices for naming test classes and methods. You could use a Test pre- or post-fix to the class or method name in your test, or perhaps give them the same names as in your application. I tend to prefer the latter approach, as it helps you ensure you have the right level of code coverage in your tests and can quickly see which parts of an application aren’t being called from a test.

Designing and running tests

Much of working with NUnit is about setting up the appropriate attributes and parameters to manage and run tests. These mark classes and methods in your tests, for example, marking classes as TestFixture and methods as Test.

A Test calls a method in your application with a predefined value or set of values. This is used to validate the response, which uses an assertion to compare the response from the method with the expected value. In some cases, this value will need to be computed. For instance, if you’re using a method to deliver a response based on external data, your test will need the same data to compute an expected value. There’s a lot you can do to build appropriate tests for your code. NUnit uses a constraint-based model to process assertions, which turns out to be very flexible and adapts well to different methods and their inputs and outputs.

Once written, tests need to be run. This can be done from the NUnit console or from Visual Studio’s NUnit adapter. This last option is probably your best choice for running lots of tests as part of writing code. By running tests inside your IDE, you can ensure that changes to code don’t break applications. If you’re planning on using NUnit as part of a CI/CD process to automate testing prior to approving pull requests or as part of a build, use the .NET CLI to run your tests.

NUnit has been one of the most popular .NET unit testing tools for a long time now. Its constraint- and parameter-driven approach to test design and development gives you a flexible way of building tests and managing them alongside the classes and methods of your code. As tests need to be built before code, you can use your requirements capture and design processes to construct a first pass at a set of unit tests, using them to define your methods and APIs.

Test-first development does add discipline to your software development life cycle—discipline that’s essential for a successful agile development process. Your tests are a contract with your code that allows you to ensure that it meets requirements as you build it and add functionality. New test features can be added, and because tests are code, they’re stored in your repositories along with the application. Well-designed tests are perhaps best thought of as part of your code documentation, allowing future developers to quickly understand the intent of your code and make necessary updates, fixes, and ports.

Copyright © 2022 IDG Communications, Inc.