New features in NUnit 2.5. Part 1 – parameterized tests

June 10, 2009 Waldemar Mękal

At the beginning of May 2009, NUnit 2.5 was released. It was a big release and brought a lot of new functionalities. The main changes were the following (full changelist):

  • added support for parameterized tests,
  • added support for theories,
  • changed way of testing expected exceptions – Assert.Throws instead of ExpectedExceptionAttribute,
  • added ability to specify the thread and apartment state requirements of a test,
  • added support for generics – TestFixture classes and test methods may now be generic,
  • added support for lambda expressions,
  • added support for executing test in a separate process for better isolation,
  • added ability to display source code in the gui runner.

I am going to describe some of these new features in a couple of posts. In this, I will focus on parameterized tests.

Parameterized Tests

Before NUnit 2.5 test methods always looked like this:

[Test]
public void TestMethod()
{
  ....
}

If you needed to run the same test with different parameters you would write something like this:

[Test]
public void TestMethod()
{
  ParameterizedTestMethod(1, 1, 2);
  ...
  ParameterizedTestMethod(1, 3, 8);
}

private void ParameterizedTestMethod(int arg1, int arg2,
  int result)
{
  //some asserts
}

Now, you can forget about it. NUnit 2.5 introduced a number of new attributes to help you to write parameterized tests. Some of those attributes are:

  • TestCaseAttribute, TestCaseSourceAttribute – for test method,
  • RandomAttribute, RangeAttribute, ValuesAttribute, ValueSourceAttribute – for arguments in parameterized test method.

TestCaseAttribute

This attribute allows you to specify values of arguments for given the test method. You may also set TestName, Description or ExpectedException, if you expect exception for given values.

[TestCase("test1")]
[TestCase("test2", TestName = "This is a second test.")]
[TestCase("")]
[TestCase(null,
  ExpectedException = typeof(ArgumentNullException))]
public void TestCaseAttributeTest(string arg)
{
  ...
}

TestCaseSourceAttribute

TestCaseSourceAttribute is used to specify the property, method or field that will provide required values of arguments for parameterized method. You must provide its name to identify the source. The source specified by the attribute must return IEnumerable or type that implements IEnumerable.

[Test, TestCaseSource("TestCases")]
public void TestCaseSourceTest(int arg1, int arg2)
{
  ...
}

static object[] TestCases =
{
  new object[] { 1, 2 },
  new object[] { 1, 3 },
  new object[] { 2, 4 }
};

You can also choose property or method from other class than one that contains your test cases. To do so, you must specify the source type.

[TestFixture]
public class TestCaseSourceTests
{
  [Test,TestCaseSource(typeof(SourceClass),"TestCases")]
  public void TestCaseSourceTest(int arg1, int arg2)
  {
    ...
  }
  ...
}
public class SourceClass
{
  public static object[] TestCases =
  {
    new object[] { 1, 2 },
    new object[] { 1, 3 },
    new object[] { 2, 4 }
  }
}

ValuesAttribute

It is used for method parameter to specify set of values that will be given for it. It must be applied on all parameters. NUnit then creates test cases from all possible combinations of the given value sets.

[Test]
public void ValuesAttributeTest([Values(1,2,3)] int arg1,
  [Values(-1,-2,-3)] int arg2)
{
  ...
}

It will be executed nine times:

ValuesAttributeTest(1, -1)
ValuesAttributeTest(1, -2)
ValuesAttributeTest(1, -3)
ValuesAttributeTest(2, -1)
ValuesAttributeTest(2, -2)
ValuesAttributeTest(2, -3)
ValuesAttributeTest(3, -1)
ValuesAttributeTest(3, -2)
ValuesAttributeTest(3, -3)

ValueSourceAttribute

It works in the same way as TestCaseSourceAttribute, but is used on method parameter.

RangeAttribute

It is used for specifying the range of values to be provided for the given parameter. You can specify minimum, maximum and step. Then, NUnit creates test cases of all possible combinations of given ranges.

[Test]
public void RangeAttributeTest([Values(1,2,3)] int arg1,
  [Range(0.5,1.5,0.5)] double arg2)
{
  ...
}

It will be executed nine times:

RangeAttributeTest(1, 0.5)
RangeAttributeTest(1, 1.0)
RangeAttributeTest(1, 1.5)
RangeAttributeTest(2, 0.5)
RangeAttributeTest(2, 1.0)
RangeAttributeTest(2, 1.5)
RangeAttributeTest(3, 0.5)
RangeAttributeTest(3, 1.0)
RangeAttributeTest(3, 1.5)

RandomAttribute

This attribute is used for specifying a set of random values to be provided for the given parameter. You can specify the range and count how many values will be produced for a parameter.

[Test]
public void RandomAttributeTest([Values(1,2,3)] int arg1,
  [Random(-1.0,1.0,5)] double arg2)
{
  ...
}

It will be executed 15 times. 3 times for each value of arg1, each combined with 5 random values of arg2.

Summary

Testing may be a repetitive task. There are many situations in which you have to test the same behavior with different input values. Previously, you had to handle it by yourself. Now, using NUnit 2.5, you can use parameterized test methods and appropriate attributes in a simple declarative way.

Examples of attribute usage were brought from NUnit documentation.

Sources:

http://www.nunit.org/
http://blog.benhall.me.uk/2008/08/taking-look-at-nunit-25-alpha-3.html

ParameterizedTestMethod

Last posts