Archive for March, 2009

Some cool new(-ish) NUnit features

March 18th, 2009

I haven’t looked at NUnit for a long time, and things have moved on a lot since I last used it. I particularly like the support for parameterised tests. For example, the TestCase attribute can be used to specify multiple iterations for a particular test, e.g.:

public void TestAdd(CalculatorMode mode)
   Calculator calc = new Calculator(mode);
   int res = calc.Add(10,20);
   Assert.That(res, Is.EqualTo(30));

This test will be executed twice, once with the calculator in ‘standard’ mode, and once with the calculator in ‘scientific’ mode.

We can take this a step further and use the Values and Range attributes to expand our set of tests:

public void TestAdd(
   [Values(CalculatorMode.Standard, CalculatorMode.Scientific)] CalculatorMode mode,
   [Range(0,5,1)] int x,
   [Range(0,5,1)] int y
   Calculator calc = new Calculator(mode);
   int res = calc.Add(x,y);
   Assert.That(res, Is.EqualTo(x+y));

This test will run a total of 72 times. The range of x and y are both 0 to 5, with an interval of 1 (i.e. the values 0,1,2,3,4,5), giving 6×6=36 tests, which are then combined with our two modes to give a total of 72 iterations.

The multiple iterations show up as separate tests in your test runner, with the names derived from the arguments used for each run, so it’s very easy to see what’s going on.

Also you may have noticed the constraint-based Assert syntax used in the examples above. I was a little unsure of it at first, but it’s growing on me. It uses a ‘fluent’ style to make the Assert more readable, so:

Assert.That(res, Is.EqualTo(x+y));

is very close to the English “Assert that res is equal to x+y”. There is a lot of debate about the merits of fluent APIs, but in this context I like it.

One constraint that really caught my eye is ‘After’. It’s useful when testing asynchronous code where you need to wait for a condition to become true. For example:

Assert.That(() => Status, Is.EqualTo("Done").IgnoreCase.After(5000, 50));

What this says is “Assert that status is ‘done’ (case insensitive) after a maximum of 5 seconds, checking every 50 ms”. The chaining of constraints like this is very readable, and the fact that relatively sophisticated constraints like After are built-in is very helpful. (I actually wrote my own version of this asynchronous wait/poll functionality recently, but I can throw it away now and use After instead.)

Finally if you derive from the AssertionHelper class, you can cut down the verbosity slightly, and re-write this Assert as:

Expect(() => Status, EqualTo("Done").IgnoreCase.After(5000,50));

Let me know if you’ve found any other cool NUnit features that I might have missed.