Agile Zone is brought to you in partnership with:

Dror Helper is an experienced software developer has written and designed software in various fields including video streaming, eCommerce, performance optimization and unit testing tools. He is passionate about programming best practices and all things software development, and has been a guest presenter at several user group meetings and ALT.NET events. Dror's blog can be found at http://blog.drorhelper.com where he writes about unit testing, agile methodologies, development tools, programming languages and anything else he finds interesting. Dror is a DZone MVB and is not an employee of DZone and has posted 57 posts at DZone. You can read more from them at their website. View Full User Profile

Multiple asserts – done right

02.17.2011
| 2886 views |
  • submit to reddit

If you’ve been writing unit tests for some time or seen a good presentation on how to write unit tests you probably heard the “One assert per test” rule. There are real benefits in having only one assert in each tests – you get a focused tests, it’s easier to understand what caused the test to fail as so on.

However there are several reasons to use more than one assert in a test – not only when you want to check several properties of the same result.

The problem is that it doesn’t matter whether or not it’s ok to write several asserts in one test when a test fails you’ll be stuck with a partial view – and that’s due to the assertion implementation – it throws exception on failure, and so the first assert that fails throws an exception leaving you completely oblivious to the result of the asserts following it (please excuse the overly simplified example):

[TestMethod]
public void SimpleTest()
{
var result = 2 + 2;

Assert.IsInstanceOfType(result, typeof(double));
Assert.AreEqual(4, result);
}

And so if the first assert fails I have no clue what is the state of the 2nd assertion.

The solution

I came across this idea while reading Multiple mocks, asserts, and hidden results:

If test frameworks did NOT throw exceptions form asserts\mocks, but instead gathered all of their data before ending the test as fail\pass, this would not be needed.


Obviously this feature is not yet supported and so a solution is up to us. Roy links to a tool that uses code generation to create different tests for each assert – how cool is that! But I thought that there bound to be a simple way to run multiple asserts and only output the fail results at the end of the test run – and there is:

public class AssertAll
{
public static void Execute(params Action[] assertionsToRun)
{
var errorMessages = new List<exception>();
foreach (var action in assertionsToRun)
{
try
{
action.Invoke();
}
catch (Exception exc)
{
errorMessages.Add(exc);
}
}

if(errorMessages.Any())
{
var separator = string.Format("{0}{0}", Environment.NewLine);
string errorMessageString = string.Join(separator, errorMessages);

Assert.Fail(string.Format("The following condtions failed:{0}{1}",
Environment.NewLine, errorMessageString));
}
}
}</exception>

And now our test looks like this:

[TestMethod]
public void SimpleTest2()
{
var result = 2 + 2;

AssertAll.Execute(
() => Assert.IsInstanceOfType(result, typeof(double)),
() => Assert.AreEqual(4, result));
}

It’s not pretty but it works, and you get an error message for all the asserts that failed.

Conclusion

As always remember that “just because you can – doesn’t mean you should”, there are instances where multiple asserts in a single tests means that you’re testing too much in the same test – and it’s up to you to decide if it’s a good idea.

References
Published at DZone with permission of Dror Helper, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)