Friday, April 30, 2004

The TypeFixture lets you write a fixture for specific type and apply to a number of instance of this type.This fixture is particularly usefull for writing fixtures of interfaces and apply it to all the types that implement the interface.

In this tutorial, we are going to write a fixture for the IEnumerable interface (note that this interface is best tested with EnumerationFixture).

Fixture logic

The TypeFixture has the following execution logic:

  1. (optional)Set-up the fixture, (SetUpAttribute),
  2. Get an instance of the tested type provided by the user (ProviderAttribute),
  3. Get instances of the tested type provided by a factory (ProviderFactoryAttribute),
  4. Run test method with this instance as argument (TestAttribute)
  5. (optional)Teardown fixture (TearDownAttribute)
Step 1: Creating the fixture

Create a new class EnumerableTest and tag it with TypeFixture. The TypeFixture attribute takes the tested type as parameter:

using System;
using System.Collections;
using MbUnit.Core.Framework;
using MbUnit.Framework;

[TypeFixture(typeof(IEnumerable))]
public EnumerableFixture
{
}
Step 2:  Create providers

MbUnit needs instance of the tested type to feed them into the different tests. Creating those instances is the job of tester. To do so, you can either

  • write a method in the fixture, tagged with ProviderAttribute that returns an instance of the tested type,
  • give the type of an instance factory that will be used to "produce" new instances
  • or do both appraoch

We start by writing two methods that return respectively and enumerator on a empty list and non-empty list:

using System;
using System.Collections;
using MbUnit.Core.Framework;
using MbUnit.Framework;

[TypeFixture(typeof(IEnumerable))]
public EnumerableFixture
{
    [Provider(typeof(IEnumerable))]
    public ArrayList ProviderEmptyArrayList()
    {
        return new ArrayList();
    }

    [Provider(typeof(IEnumerable))]
    public ArrayList ProviderArrayList()
    {
        ArrayList list = new ArrayList();
        list.Add(0);
        list.Add(1);
        return list;
    }
}

The disadvantage of "hardcoding" methods in the fixture is that we cannot reuse the code for other fixture, for example, for the IList fixture. To avoid this problem you can wrap you "generation" methods in a class factory and use the ProviderFactory to tell MbUnit to use this factory:

using System;
using System.Collections;
using MbUnit.Core.Framework;
using MbUnit.Framework;

public class ArrayListFactory
{
    public ArrayList Empty
    {
        get
        {
            return new ArrayList();
        }
    }

    public ArrayList TwoElems
    {
        get
        {
            ArrayList list = new ArrayList();
            list.Add(0);
            list.Add(1);
            return list;
        }
    }
}

[TypeFixture(typeof(IEnumerator))]
[ProviderFactory(typeof(ArrayListFactory), typeof(IEnumerable))]
public EnumeratorFixture
{
}

That's much better because we can reuse the factory for other fixtures. Of course, you can attach an arbitrary number of factories and provider methods.

Step 3: Add some tests

Add the unit tests as usuals on the IEnumerable instance. These methods must take the tested type the tested type as argument.

Here we check that the enumerator throws if Current is called while the cursor if before the first element or past the last element:

...
[TypeFixture(typeof(IEnumerable))]
[ProviderFactory(typeof(ArrayListFactory), typeof(IEnumerable))]
public EnumerableFixture
{
    ...

    [Test]
    [ExpectedException(
         typeof(InvalidOperationException),
         "Current called while cursor is before the first element"
    )]
    public void CurrentCalledBeforeMoveNext(IEnumerable en)
    {
          IEnumerable er = en.GetEnumerator(); 
          en.Current;
    }

    [Test]
    [ExpectedException(
         typeof(InvalidOperationException),
         "Current called while cursor is past the last element"
    )]
    public void CurrentCalledBeforeMoveNext(IEnumerable en)
    {
          IEnumerable er = en.GetEnumerator(); 
          while(en.MoveNext());
          en.Current;
    }
}
Step 4: Compile and run

Compile and load in the GUI. MbUnit will scan the providers and create a fixture for each one of them.

posted on Friday, April 30, 2004 9:40:00 PM UTC  #    Comments [4]
Tracked by:
"parkside trampoline" (online) [Trackback]
Monday, June 06, 2005 6:07:02 PM UTC
Peli's Blog
Monday, June 06, 2005 6:07:03 PM UTC
Pretty darn sweet, I'll tell you that!
Max Guernsey, III
Monday, June 06, 2005 6:07:04 PM UTC
I tried this example but got:
<br>Message: Current called while cursor is past the last element Expected exception of type System.InvalidOperationException, got System.Reflection.TargetParameterCountException (Parameter count mismatch.)
<br>
<br>Type: <a title="MbUnit, Generating Unit Testing and Model Based Testing Framework for .NET Framework" href="http://mbunit.tigris.org" target="_blank">MbUnit</a>.Core.Exceptions.ExceptionTypeMistmachException
<br>Source: <a title="MbUnit, Generating Unit Testing and Model Based Testing Framework for .NET Framework" href="http://mbunit.tigris.org" target="_blank">MbUnit</a>.Core
<br>TargetSite: System.Object Execute(System.Object, System.Collections.IList)
<br>HelpLink: null
<br>Stack: at <a title="MbUnit, Generating Unit Testing and Model Based Testing Framework for .NET Framework" href="http://mbunit.tigris.org" target="_blank">MbUnit</a>.Core.Invokers.ExpectedExceptionRunInvoker.Execute(Object o, IList args) in C:\svnhome\trunk\MbUnit\MbUnit.Core\Invokers\ExpectedExceptionRunInvoker.cs:line 92
<br> at <a title="MbUnit, Generating Unit Testing and Model Based Testing Framework for .NET Framework" href="http://mbunit.tigris.org" target="_blank">MbUnit</a>.Core.RunPipeStarter.Run(Object fixture) in C:\svnhome\trunk\MbUnit\MbUnit.Core\RunPipeStarter.cs:line 128
<br>
<br>
<br>Could anybody tell me why?
tim
Monday, June 06, 2005 6:07:04 PM UTC
The TargetParameterCountException can be fixed by properly implementing the Factory with [Factory] tags. Documentation is here:
<br><a target="_new" href="http://www.testdriven.net/wiki/default.aspx/MyWiki.TypeFixture">http://www.testdriven.net/wiki/default.aspx/MyWiki.TypeFixture</a>
<br>
<br>Example:
<br>
<br>public class ArrayListFactory
<br>{
<br> [Factory]
<br> public ArrayList Empty
<br> {
<br> get
<br> {
<br> return new ArrayList();
<br> }
<br> }
<br>
<br> [Factory]
<br> public ArrayList TwoElems
<br> {
<br> get
<br> {
<br> ArrayList list = new ArrayList();
<br> list.Add(0);
<br> list.Add(1);
<br> return list;
<br> }
<br> }
<br>}
<br>
Scott Pogue
Comments are closed.