BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Testing
.NET 2.0+

Creating Custom NUnit Assertion Methods

NUnit provides a large number of assertion methods that can test values for correctness during a test run. For complex and repetitive test scenarios, it can be useful to create custom assertions that can be reused in a number of tests.

Asserts

The NUnit framework allows you to test that your code is behaving correctly, primarily through the use of assertions. These are static methods that check one or more values for correctness and throw exceptions when there is a problem. The exceptions are caught by a test runner and displayed as a failing test. There are assertions to cover all possible test scenarios defined within a number of standard classes, including the Assert, CollectionAssert and StringAssert types.

Sometimes the assertion that you need to express in a test becomes complicated. If a similar assertion must be made several times, this can cause unnecessary repetition in your code. If an assertion includes a complex expression, you may find that your test becomes harder to read than is ideal. In such situations you may elect to create your own, custom assertion class and methods to simplify your unit tests.

In this article we'll create two such assertions that work with colours. As we'll be using classes from the NUnit framework and the System.Drawing namespaces, we'll need the following using directives in the code:

using NUnit.Framework;
using System.Drawing;

Primary Colour Assertions

For our demonstration we'll create some rather contrived tests and assertions that deal with colours. We'll test that several colours either are, or are not, additive primary colours; these being pure red, green or blue. We'll assume that a colour is a primary colour if two of the red, green and blue elements are zero and the third is any value other than zero. This will identify primary colours of any brightness.

We can write three simplistic tests for three colours as follows. Here we test that red is primary, black is not and purple is. As purple is not a primary colour, the third test will fail.

[Test]
public void RedIsAPrimaryColor()
{
    Color c = Color.Red;

    Assert.IsTrue(
        (c.R > 0 && c.G == 0 && c.B == 0)
        || (c.G > 0 && c.R == 0 && c.B == 0)
        || (c.B > 0 && c.R == 0 && c.G == 0));
}

[Test]
public void BlackIsNotAPrimaryColor()
{
    Color c = Color.Black;

    Assert.IsFalse(
        (c.R > 0 && c.G == 0 && c.B == 0)
        || (c.G > 0 && c.R == 0 && c.B == 0)
        || (c.B > 0 && c.R == 0 && c.G == 0));
}

[Test]
public void PurpleIsAPrimaryColor()
{
    Color c = Color.Purple;

    Assert.IsTrue(
        (c.R > 0 && c.G == 0 && c.B == 0)
        || (c.G > 0 && c.R == 0 && c.B == 0)
        || (c.B > 0 && c.R == 0 && c.G == 0));
    }
}

As you can see, the assertions used are repetitive and not particularly easy to understand. We can infer the meaning of the assertions from the test names but in more complex tests you can see that it would be easy to be confused by the assertions, or to introduce errors into the expressions used. A second problem with these assertions is the output that you see when a test fails. As shown below, when purple is identified as not being a primary colour, we see a rather undescriptive message.

Test 'Example.Tests.PurpleIsAPrimaryColor' failed: 
  Expected: True
  But was:  False

In this example we can gain benefits by creating custom assert methods.

Adding the Custom Assertion Class

For our custom assertions we'll create a static class that contains two methods. One will check if a colour is primary and one will assert that the supplied colour is not a primary colour. In NUnit, assertion classes are either named "Assert" or have the "Assert" suffix. We'll follow this convention by calling our class, "ColorAssert".

The expressions from the original tests above are used in our assertions as the predicates of if statements. In the IsPrimaryColor method we test whether the expression incorrectly returns true. For IsNotPrimaryColor we check if it the expression evaluates as true. When one of the if statements detects an incorrect value we need to generate an appropriate failure message and throw an exception for a test runner to intercept. We could throw an AssertionException manually. However, it makes more sense to use NUnit's utility assertion, Assert.Fail, as follows:

public static class ColorAssert
{
    public static void IsPrimaryColor(Color c)
    {
        if (!((c.R > 0 && c.G == 0 && c.B == 0)
            || (c.G > 0 && c.R == 0 && c.B == 0)
            || (c.B > 0 && c.R == 0 && c.G == 0)))
        {
            string message = string.Format("{0} is not a primary color", c.ToString());
            Assert.Fail(message);
        }
    }

    public static void IsNotPrimaryColor(Color c)
    {
        if ((c.R > 0 && c.G == 0 && c.B == 0)
            || (c.G > 0 && c.R == 0 && c.B == 0)
            || (c.B > 0 && c.R == 0 && c.G == 0))
        {
            string message = string.Format("{0} is a primary color", c.ToString());
            Assert.Fail(message);
        }
    }
}

Updating the Tests

With our ColorAssert class in place we can refactor the original tests. As you can see, this simplifies the tests greatly:

[Test]
public void RedIsAPrimaryColor()
{
    Color c = Color.Red;
    ColorAssert.IsPrimaryColor(c);
}

[Test]
public void BlackIsNotAPrimaryColor()
{
    Color c = Color.Black;
    ColorAssert.IsNotPrimaryColor(c);
}

[Test]
public void PurpleIsAPrimaryColor()
{
    Color c = Color.Purple;
    ColorAssert.IsPrimaryColor(c);
}

Try executing the tests to see the failure message. You should see the "purple" test fail with improved output.

Test 'Example.Tests.PurpleIsAPrimaryColor' failed: Color [Purple] is not a primary color
7 July 2012