Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / DevOps / unit-testing

RelationAssert as extension to the unit test Assert class

5.00/5 (2 votes)
11 Mar 2012CPOL2 min read 21.7K   137  
How to define RelationAssert as an extension to the VisualStudio Assert class.

Introduction

This article details how one can extend the existing unit test assertions provided by Microsoft's Visual Studio unit test framework (see Assert and StringAssert).

I first give some guideline for writing concise and expressive assertions, followed by exploring the limits of the current Assert classes, resulting in a suggestion on how to overcome these limits.

Writing Expressive Assertions

The assertion classes available contain some specific methods to assert certain conditions. The challenging part in applying assertions is, to

  1. call the proper assert methods which report the expected and actual values
  2. provide a meningful assertion message
  3. overcome the temptation to format the message by repeating the values from 1. above

Item 1. ensures concise and meaningful assertions, item 2. makes potential additional code comments redundant, item 3. does not re-invent the wheel.

E.g., the following assertion should be rewritten:

C#
// ensure that the list of xxx contains 6 elements
if (list.Count != 6)
{
    Assert.Fail("Error: list.Count = {0}", list.Count);
}
Resulting message: Assert.Fail failed. Error: list.Count = 0

The first attempt replaces the if-block:

C#
// ensure that the list of xxx contains 6 elements
Assert.IsTrue(list.Count == 6, "Error: list.Count = {0}", list.Count);
Resulting message: Assert.IsTrue failed. Error: list.Count = 0

The next attempt uses an appropriate Assert method:

C#
// ensure that the list of xxx contains 6 elements
Assert.AreEqual(6, list.Count, "Error: list.Count = {0}", list.Count);
Resulting message: Assert.AreEqual failed. Expected:<6>. Actual:<0>. Error: list.Count = 0

The final attempt makes the comment and the message formatting redundant:

C#
Assert.AreEqual(6, list.Count, "wrong number of xxx");
Resulting message: Assert.AreEqual failed. Expected:<6>. Actual:<0>. wrong number of xxx

This last assertion is the desired one: appropriate method used that reports the values, a concise non-formatted message, no useless comment. Keep it Simple!

Missing Assert Methods

So, how asserting the following:

  • list.Count > 4

There are no such function like Assert.Greater(...). The closest we get to the guideline above is Assert.IsTrue(...). E.g.:

C#
Assert.IsTrue(list.Count > 4, "too little xxx elements");
Resulting message: Assert.IsTrue failed. too little xxx elements

No word about expected and actual value, no word about the kind of check applied...

So, fall back to commenting and formatting messages? E.g. (not my recommendation):

C#
// check that the list contains at least one element
Assert.IsTrue(list.Count > 4, "xxx list has only {0} elements instead of more than 4 elements", list.Count);
Resulting message: Assert.IsTrue failed. xxx list has only 1 elements instead of more than 4 elements

Suggested Solution

The attached code provides an ExtAssert class that provides the four missing functions:

C#
public static void Greater<T>(T a, T b, string message, params object[] args) where T : IComparable<T>
public static void GreaterOrEqual<T>(T a, T b, string message, params object[] args) where T : IComparable<T>
public static void LessOrEqual<T>(T a, T b, string message, params object[] args) where T : IComparable<T>
public static void Less<T>(T a, T b, string message, params object[] args) where T : IComparable<T>

With these, you can re-write the relation assertion, following the guidelines:

C#
ExtAssert.Greater(list.Count, 4, "too little xxx elements");
Resulting message: Assert.AreEqual failed. Expected:<(a > b)>. Actual:<(1 < 4)>. too little xxx elements

Behind the Scenes

The concept is quite simple:

  1. define an "ok" string, e.g. "(a > b)"
  2. provide a check function that returns the "ok" string if the check passes or the actual value relation if it fails, e.g. "(a > b)" versus "(1 < 4)"
  3. compare the outcome of the check with the "ok" string: Assert.AreEqual(ok, check, ...)

This concept is implemented in the attached code for the case of relation assertions. One can extend assertion as indicated in the ExtAssert for the NullOrEmpty check, etc.

If you like the article, please rate it.

Any comments are welcome, e.g. if it is useful or suggestions for improvements, etc. Thanks!

History

  • Version 1.0: 2012-01-29: Initial verision.
  • Version 1.1: 2012-03-11: Added request for rating and for comments.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)