Tip – When writing custom assertion methods – Keep your assertion stack trace clean

I have bumped in to a couple of custom assertion methods which lets the assertion stack trace contain the assertion method itself. Hence, if I use, e.g. Testdriven.Net, I might double-click on the wrong line and end up in the assertion method, instead of the test. It’s really easy to prevent this, just add the DebuggerHiddenAttribute (read more) to the assertion method.

Example

First, lets be clear. The taken example is not realistic and there’s already support for array assertions but lets pretend I want an assertion method that asserts string arrays and ensures that:

  • the number of elements are the same
  • the order of the elements are the same

I’m using Galio, MbUnit and Testdriven.net

The test

[TestFixture]
public class DummyTests
{
    [Test]
    public void GetAsSortedStringArray_WhenManyParams_ReturnsSortedStringArray()
    {
        var values = new int[] {0, 4, 5, 1, 3, 2};
        var expectedResult = new[] {"0", "-1", "2", "3", "4", "5"};

        var dummy = new Dummy();
        var sortedStringArray = dummy.GetAsSortedStringArray(values);

        ArrayAssert.AreMatches(expectedResult, sortedStringArray);
    }
}

The test will fail (which is expected in this blogpost) since The expected element number "2" should have value "1" and not "-1"

What is wrong with the test

The implementation of Dummy

public class Dummy
{
    public string[] GetAsSortedStringArray(params int[] values)
    {
        return values.Select(v => v.ToString()).OrderBy(v => v).ToArray();
    }
}

The Assertion method

public static class ArrayAssert
{
    public static void AreMatches(string[] expectedValues, string[] actualValues)
    {
        var numOfExpected = expectedValues.Count();
        var numOfActual = actualValues.Count();

        if (numOfExpected != numOfActual)
            throw new AssertionException(string.Format(
                @"The expected values and the actual values have 
                different number of elements.
                Expected: '{0}'; Actual: '{1}'.", numOfExpected, numOfActual));

        for(var c = 0; c < numOfExpected; c++)
        {
            var expected = expectedValues[c];
            var actual = actualValues[c];

            if(!expected.Equals(actual))
                throw new AssertionException(string.Format(
                    @"The values in element-position '{0}' are not the same.
                    Expected: '{1}'; Actual: '{2}'.", c, expected ?? "", actual ?? ""));
        }
    }
}

What’s wrong?

The result of the assertion will be:

Testdriven.Net – Result
Testdriven.Net - Result - Not friendly

Gallio – Result
Gallio - Result - Not friendly

I have tried to mark the lines that I think pollutes the result. It’s the lines stating something like:

Class1.cs(44,0): at ClassLibrary1.ArrayAssert.AreMatches(String[] expectedValues, String[] actualValues)

This is not of interest. And by adding the attribute DebuggerHidden I will get another assertion result, which in my opinion is slightly more friendly.

The corrected assertion method

public static class ArrayAssert
{
    [DebuggerHidden]
    public static void AreMatches(string[] expectedValues, string[] actualValues)
    {
        ...
    }
}
More friendly assertion result

Testdriven.Net – Result
Testdriven.Net - Results - Friendly

Gallio – Result
Gallio - Results - Friendly

Nothing more to say.

//Daniel

About these ads

3 thoughts on “Tip – When writing custom assertion methods – Keep your assertion stack trace clean

  1. Pingback: DotNetShoutout

  2. Pingback: The Morning Brew - Chris Alcock » The Morning Brew #612

  3. Pingback: Tweets that mention Tip – When writing custom assertion methods – Keep your assertion stack trace clean « Daniel Wertheim -- Topsy.com

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s