Thursday, May 21, 2009

NUnit ValuesAttribute is tasty delicious!

There are quite a few nice features in the new 2.5 release of NUnit so if you’ve not yet checked it out please do so. I’ve migrated to it in all our solutions at work and we’ve had no problems, we did have to upgrade to the latest versions for TestDriven.Net and TeamCity, but hey, upgrading is a good thing.

One thing I really like is the ValuesAttribute, if you’ve done parameterized tests (that were previously available in the NUnit.Framework.Extensions library) this is something similar. Just tag your test as a normal Test-method but add a parameter and tag that parameter with the ValuesAttribute like this:

[TestFixture]
public class ValidatorTests
{
    [Test]
    public void IsInRange_returns_true_for_values_that_are_in_range([Values(1,2,3)] int value)
    {
        var validator = new Validator();
        validator.IsInRange(value, 1, 3);
    }
}

public class Validator
{
    public bool IsInRange(int value, int lowerBound, int upperBound)
    {
        return value >= lowerBound && value <= upperBound;
    }
}

This will result in three tests being run, one for each value, quite nice.

The really cool thing is that you can add more than one parameter each tagged with this attribute and the number of tests will be the cross-product of the values.

Sunday, May 17, 2009

Cast null values in tests

My first tests of classes are often tests that asserts that the constructor throws ArgumentNullException for null arguments, something like this:

[Test]
public void constructor_throws_when_fileSystem_is_null()
{
    Assert.Throws<ArgumentNullException>(() =>
        {
            new TransactionalFileSystem((IFileSystem)null, this.transactionManager);
        });
}

As you see I explicitly cast the null value to the type of the parameter in the constructor signature, this is benefitial for two reasons:

  1. It reads better, the reader know what it is that is NOT passed in.
  2. Several times in the past I have refactored and reordered the parameters in the constructor with the result that the tests test the wrong parameters this is avoided this way.