I have added a new fixture, ProcessTestFixture, that implements the process testing presented by Marc Clifton in http://www.codeproject.com/csharp/autp3.asp.
A process is an ordered sequence of unit tests. As long as one test passes, the next test is run. Due to the structure of MbUnit, this was straightforward to implement (I'll about this later in the blog). The syntax of the fixture is similar to Marc Clifton example but I have merge Test, Sequence(...) to TestSequence(...):
Test, Sequence(...)
TestSequence(...)
[ProcessTestFixture] public MyProcess { [TestSequence(1)] public void Hello() {...} [TestSequence(2)] public void World() {...} ... }
The implementation of the fixture was done by the following steps:
TestSequenceAttribute
TestPatternAttribute
[AttributeUsage(AttributeTargets.Method, AllowMultiple=false, Inherited=true)] public sealed class TestSequenceAttribute : TestPatternAttribute { private int order; public TestSequenceAttribute(int order) { this.order = order; } public int Order { get { return this.order; } set { this.order = value; } } }
ProcessMethodRun
IRun
Reflect
IRunInvoker
MethodRunInvoker
public class ProcessMethodRun : IRun { ... public virtual void Reflect( RunInvokerTree tree, RunInvokerVertex parent, Type t ) { // first gather all methods, with order. ArrayList methods = new ArrayList(); foreach(MethodInfo mi in TypeHelper.GetAttributedMethods(t,this.AttributeType)) { // get sequence attribute TestSequenceAttribute seq = (TestSequenceAttribute)TypeHelper.GetFirstCustomAttribute(mi,typeof(TestSequenceAttribute)); methods.Add( new OrderedMethod(mi, seq.Order) ); } // sort the methods QuickSorter sorter = new QuickSorter(); sorter.Sort(methods); // populate execution tree. RunInvokerVertex child = parent; foreach(OrderedMethod om in methods) { IRunInvoker invoker = InstanceInvoker(om.Method); child = tree.AddChild(child,invoker); } } protected IRunInvoker InstanceInvoker(MethodInfo mi) { IRunInvoker invoker = new MethodRunInvoker(this,mi); return DecoratorPatternAttribute.DecoreInvoker(mi,invoker); } #region OrderedMethod private class OrderedMethod : IComparable { private MethodInfo method; private int order; public OrderedMethod(MethodInfo method, int order) { this.method = method; this.order = order; } public MethodInfo Method { get { return this.method; } } public int Order { get { return this.order; } } public int CompareTo(OrderedMethod obj) { return this.order.CompareTo(obj.order); } int IComparable.CompareTo(Object obj) { return this.CompareTo((OrderedMethod)obj); } } #endregion }
ProcessTestFixtureAttribute
TestFixturePatternAttribute
public class ProcessTestFixtureAttribute : TestFixturePatternAttribute { public override IRun GetRun() { SequenceRun runs = new SequenceRun(); OptionalMethodRun setup = new OptionalMethodRun(typeof(SetUpAttribute),false); runs.Runs.Add( setup ); ProcessMethodRun test = new ProcessMethodRun(typeof(TestSequenceAttribute)); runs.Runs.Add(test); OptionalMethodRun tearDown = new OptionalMethodRun(typeof(TearDownAttribute),false); runs.Runs.Add(tearDown); return runs; } }
Et voilà!
Page rendered at Thursday, July 24, 2008 5:10:28 AM UTC
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.