MbUnit Combinatorial Test

I presented MbUnit at the Manchester ThoughtWorks geek night last Wednesday, it was a great night with lots of great questions and feedback. It was really great meeting folks who use MbUnit day to day, it really validates the work we do on the project. I think for DDD I'll change the format of my talk as I have now started thinking about a story format for the session, voting for that is due to close soon so we shall see.  The next post in the MbUnit series will be about the combinatorial test. Let's take a look at the object under test first.

Starting with the interface

   1:  public interface IAlphaString
   2:  {
   3:      bool ValidString(string inputString);
   4:  }

and now the concrete class

   1:  using System.Text.RegularExpressions;
   2:   
   3:  public class AlphaString : IAlphaString
   4:  {
   5:      public bool ValidString(string inputString)
   6:      {      
   7:          Regex r = new Regex("[a-zA-Z]", RegexOptions.None);
   8:          return r.IsMatch(inputString);
   9:      }
  10:  }

This class tests for alpha strings and returns false if the test fails, true if the test passes. Before we get into testing this class we need one more class

   1:  using System;
   2:   
   3:  public class StringHolder
   4:  {
   5:      public string StringValue;
   6:      public bool IsValid;
   7:   
   8:      public StringHolder(string stringvalue, bool isValid)
   9:      {
  10:          StringValue = stringvalue;
  11:          IsValid = isValid;
  12:      }
  13:   
  14:      public override string ToString()
  15:      {
  16:          return String.Format("{0},{1}", StringValue, IsValid);
  17:      }
  18:  }

This class allows to set a test value and expected result. Wiring this object to the object under test we do the following.

   1:  using System.Collections;
   2:  using MbUnit.Framework;
   3:   
   4:  [TestFixture]
   5:  public class IAlphaStringTest
   6:  {
   7:      [Factory(typeof(IAlphaString))]
   8:      public IEnumerable AlphaStringInstances()
   9:      {
  10:          yield return new AlphaString();
  11:      }
  12:   
  13:      [Factory(typeof(StringHolder))]
  14:      public IEnumerable TestStrings()
  15:      {
  16:          yield return new StringHolder("aaaa", true);
  17:          yield return new StringHolder("111", false);
  18:      }
  19:   
  20:      [CombinatorialTest]
  21:      public void AlphaValuesTest([UsingFactories("TestStrings")] StringHolder testValues,
  22:                                  [UsingFactories("AlphaStringInstances")] IAlphaString itemstoTest)
  23:      {
  24:          Assert.AreEqual(itemstoTest.ValidString(testValues.StringValue), testValues.IsValid);
  25:      }
  26:  }

First we deploy the MbUnit factory attribute to have a referance to object under test and test holder object(s), we then link the factories into the actual test. The end result is that for each test value\expected result pair we run the test value against the obect under test and compare the expected result to the actual result. Let's take a look at v3 version

   1:  using System.Collections.Generic;
   2:  using MbUnit.Framework;
   3:   
   4:  [TestFixture]
   5:      public class CombinatorialTest
   6:      {
   7:   
   8:      public IEnumerable<IAlphaString> GetInstances()
   9:      {
  10:          yield return new AlphaString();
  11:      }
  12:      
  13:      [Test]
  14:      [Row("aaaa", true)]
  15:      [Row("111", false)]
  16:      public void Test(string value, bool isValid, [Factory("GetInstances")] IAlphaString alphaString)
  17:      {
  18:          Assert.AreEqual(isValid, alphaString.ValidString(value));
  19:      }
  20:  }

V3 makes things simpler in that we no longer need a test holder object and instead we can pair the test value\expected result to the object under test within the row test. As I am hopefully showing we are taking the long standing row fixture to the level in v3.

1 Comment

  • Hi, Andrew,

    The code you posted get wrapped and it's hard to follow, you may consider reformat your code a little bit so we can follow your example a little bit better.

    thanks,

Comments have been disabled for this content.