Thursday, July 22, 2010

Data Driven testing using MbUnit v3

I was reading about data driven testing using mbunit from this article. I am using v3 of mbunit now and the attributes used for DataDriven testing are not applicable in v3 as per the release notes for v3.

Using this article, I was able to do data driven testing using xml data source. But I had to use [Bind("price")] with each parameter.  What I wanted was a way to deserialize the Xml test data and run the test cases as many number of times as my test data. If you read the article by Ben Hall, it was posiible in v2 using ForEachTest attribute which is not supported in v3.

So I tried to do the following as a workaround.
First of all create an Xml data source. Change the settings to make it an embedded resource.
<ArrayOfTestData>
  <TestData TestCaseNumber="1">
    <Name>Abc</Name>
  </TestData>
</ArrayOfTestData >

Create the class to deserialize the test data
[Serializable]
    public class TestData
    {
        [XmlAttribute("TestCaseNumber")]
        public int TestCaseNumber { get; set; }
        public string Name { get; set; }
    }

Now we need to deserialize the xml file. I have done it in the SetUp method so that this operation is done once for all the test cases.

I have used the feature of MbUnit to create test cases dynamically.  So for doing that you need to apply the attribute [DynamicTestFactory]  to a method which will create test cases dynamically based on the test data in your xml file.
[TestFixture]
    public class SampleTestFixture
    {
        private List<TestData> testDataList;

        [SetUp]
        public void SetUp()
        {
            XmlDocument document = new XmlDocument();
            Assembly currentAssembly = Assembly.GetExecutingAssembly();
            document.Load(currentAssembly.GetManifestResourceStream("SampleProject.TestData.xml"));

            //TODO: Implement your deserialization code
            testDataList = Deserialize<List<TestData>>(document.InnerXml);
        }

        [TearDown]
        public void TearDown()
        {
            testDataList = null;
        }

        [DynamicTestFactory]
        public IEnumerable<Test> CreateTests()
        {
            foreach (TestData testData in testDataList)
            {
                yield return new TestCase("Test case " + testData.TestCaseNumber, () =>
                    {
                        //TODO: Add your test logic and Asserts
                    });
            }
        }       
    }  

Please feel free to suggest any better solution to handle this case.

1 comment: