Project Description
MSTest is missing a number of features that other unit test frameworks have. This project fills in some of those features.


Lambda Assertions

I saw this in MbUnit and had to have it in MSTest. The common assertion framework in all the unit test frameworks looks something like this:
Assert.AreEqual(expected, actual);
This isn't the way we write our code. It is usally like this:
if (actual == expected) ...
With lambda assertions you can write your assertions like this:
AssertEx.That(() => actual == expected);
The lambda expressions make things a little harder to read, but writing the assertions the way you think of them makes up for that.

AssertEx - Allows lambda expressions in assertions.

Exception Testing

Most other unit testing frameworks have a Throws method to test for exceptions. MSTest doesn't. See AssertEx for more information.

Inconclusive Testing

MSTest as well as other testing frameworks allows you to flag a unit test as inconclusive. MSTest's version doesn't allow testing of values so I added my own which uses the same code as AssertEx.That. See AssertEx for more information.

Data Driven Tests

MSTest allows you to write a single test method and run it with many different sets of values. Unfortunately, there is no easy way to embed these values in the unit test itself. MbUnit and NUnit allow you to do this with attributes on the test method which makes it easier to use. I tried a number of things to do this in MSTest and finally came up with a set of classes that let you build lists of data and run them against a delegate (usually a lamba expression). You can also use arrays or collections if you don't want to use the ListBuilder.

ListBuilder - Allows you to easily build lists of data to use for unit tests.
ListItems - Holds the data for one run of the unit tests. This class is used under the covers.
TestRunner - The class that actually runs the built list/array/collection.
TestRunnerException - The exception wraps an individual unit test exception and specifies the data the caused the exception.
Tuple - Holds whatever typed data is needed. This will be removed when we move to .Net 4.0 where the class already exists.

As the following code shows, you build a list of whatever data you want. The C# compiler figures out the data types in the first AddItem method so you see them in the intellisense in the following AddItem methods. The unit test code you want to run should be inside the lambda expression in the Run method. This is not as simple as using attributes in MbUnit, but it can be more powerful. The Run method also runs against IEnumerable<T> so you can use arrays or lists instead of the ListBuilder.
    .AddItem(5, "a")
    .AddItem(10, "b")
    .Run((number, text) => Assert.Something());
The TestRunner can also use any IEnumerable<T>. If your data isn't too complicated you can just use arrays or lists. For example, here is the test for AssertEx.That for simple boolean expressions:
public void True_boolean_expressions_are_OK()
    bool trueValue = true;
    bool falseValue = false;
    new Expression<Func<bool>>[]
        () => trueValue,
        () => !falseValue,
        () => trueValue == true,
        () => falseValue == false,
        () => trueValue != false,
        () => falseValue != true
    .Run(assertion => AssertEx.That(assertion));

UI Testing

I do a lot of UI automation testing. For this to work, you need to run your unit tests on a UI thread. You can also use RunOnUIThread instead of the Run method used above.

UIHelper - Runs code on a UI thread.


ExceptionHelper - A couple utility methods for working with exceptions.

See Also - Uses FxCop to find issues in your compiled code. - Uses StyleCop to find issues in your source code.

Last edited Jun 14, 2009 at 7:59 PM by JeffLeBert, version 4