mbunit dynamic and static test factories

I’ve been a big MbUnit fan for a while now, even going so far as to leverage it as the test framework for a lot of the automated integration tests that I write. So when I started re-writing a suite of automated tests, I reached into my toolbelt and pulled out MbUnit.

What I wanted to do was consume some XML, that defined what my test suite and tests cases, and use that drive my tests through MbUnit. So I started hunting around and came accross the built support for external data sources but it didn’t really look that appealing to me. The data I was trying to consume was XML, but I didn’t want to have to deal with XPath, so I kept digging.

Then I came across a blog entry from way back in 2008 announcing a new build of MbUnit that introduced Static and Dynamic Test Factories (also known in a previous life as Test Suites). I took one look and realized that it was exactly what I needed. All I had to do was write a single method that returned an IEnumerable collection of Test objects. Those test objects can be TestCases or TestSuites, so I could build an entire set of data driven tests in one fell swoop.

All I needed to do next was decided on a dynamic or static test factory. The biggest difference is that the tests are explored at run-time for a dynamic test factory and at load-time for a static test factory.

This means that with a static test factory the tests are all generated and displayed individually in the UI (Gallio) and can be selected to run individually (if so desired). With the dynamic test factory is displayed as a single test method and all tests have to be run at once, but it also supports parameterized input where the static test factory doesn’t.

Here’s a simple example that calls into a method to get a list of the text files in a given path and for each file validates that it contains words (not a grandiose test I know but it’ll suffice).


/// <summary>
/// Example test method for creating dynamic MBUnit tests
/// </summary>
/// <returns></returns>
[DynamicTestFactory]
public IEnumerable<Test> ExampleDynamicTests()
{
 TestSuite testSuite = new TestSuite("Dynamic Tests");
 foreach (string testfile in GetFileNames())
 {
 TestSuite ts = new TestSuite(string.Format("Testdata: {0}", Path.GetFileName(testfile)));
 string testdata = File.ReadAllText(testfile);
 ts.Children.Add(TestWordCount(testdata));
 testSuite.Children.Add(ts);
 }
 return new List<Test>() { testSuite };
}

/// <summary>
/// Example test method for creating static MBUnit tests
/// </summary>
/// <returns></returns>
[StaticTestFactory]
public static IEnumerable<Test> ExampleStaticTests()
{
 TestSuite testSuite = new TestSuite("Static Tests");
 foreach (string testfile in GetFileNames())
 {
 TestSuite ts = new TestSuite(string.Format("Testdata: {0}", Path.GetFileName(testfile)));
 string testdata = File.ReadAllText(testfile);
 ts.Children.Add(TestWordCount(testdata));
 testSuite.Children.Add(ts);
 }
 return new List<Test>() { testSuite };
}

/// <summary>
/// Tests the word count.
/// </summary>
/// <param name="testdata">The testdata.</param>
/// <returns></returns>
private static TestCase TestWordCount(string testdata)
{
 return new TestCase("Test Word Count", () => Assert.IsTrue(testdata.Split(' ').Length > 0));
}

The code inside each factory is identical, but the end result in the UI is different as seen here:

Gallio Screenshot

The end result will be the same number of tests run, with essentially the same test report created. I ended up going with the static test factory for the added UI benefit of being able to run tests individually.

So there we go, yet another reason to use MbUnit for all your testing needs.

Leave a comment