Unit Testing with NUnit

I’m preparing a presentation on unit testing in .NET (using NUnit). Unit Testing is generally non-implementation language specific. The original SmallTalk framework and the popular jUnit Framework for Java have nearly identical designs. The same is true for CppUnit (for C++) and every other unit testing framework I’ve looked at. Since .NET languages support all of the language features necessary to implement this design, I assumed that it would be the same—and for NUnit 1.0, that was the case.

NUnit 2.0 takes it further. The developers correctly realized that .NET offers some features that can automate some of the tasks in unit testing, and took advantage of them. This “breaks” consistency with other unit testing frameworks, but for a good reason, and it’s close enough to the others to not be a big problem.

The basic architecture of the xUnit Frameworks provides a base class called TestCase which you extend to contain the test methods. The framework requires you to write another class that builds a list of these classes into a TestSuite. In jUnit, this class typically looks like this:

import junit.framework.*;

public class AllTests
{
  public static Test suite() {
    TestSuite suite =
      new TestSuite(“All tests”);

    suite.addTest(
      new TestSuite(ReaderTest.class)
    );

    suite.addTest(
      new TestSuite(CommandTest.class)
    );

    return suite;
  }
}

Note that the method AllTests.suite() must be edited each time a test class is added. If you forget, you will get a false test success. If you’re writing tests first, you will notice this immediately—but it would still be nice not to have to write or maintain this class. NUnit 2.0 uses custom attributes so that the framework can discover all Test classes and call them automatically, and takes care of this manual task. In NUnit, instead of extending a TestCase, you use a custom attribute to mark the class as a TestFixture and add test methods to it (either marked with the attribute Test or named with the prefix “test”).  It looks like this:

namespace NUnit.Tests
{
  using System;
  using NUnit.Framework;

  [TestFixture]
  public class SuccessTests
  {
    [Test] public void Add()
    { /* … */ }

    public void TestSubtract()
    { /* … */ }
  }
}

There is no need to write an AllTests class, as .NET has features that allows the framework to discover this class automatically and run it. Kent Beck calls this an “idiomatic design”, one that takes advantage of language features, instead of porting the design from a language with less features, and is a good lesson for any type of language port.