Saturday, October 17, 2009

Abstract Tests and csUnit

I submitted a bug for csUnit a little while back which related to a problem in csUnit when attempting to execute abstract tests. Note that csUnit will crash (i.e. null reference exception) if the TestFixture attribute is applied to the base, and if the test method is not overridden or implemented in the subclass, it won’t execute.

Abstract tests are essential for writing contract tests, which are essential for verifying interface implementations, or rather, that classes all share a mutual understanding of how each collaborator is supposed to do its thing. And that’s essential for attaining an arbitrarily high confidence in the basic correctness of your code. I wanted to post the simplest work-around for this issue that I’ve managed to find.

Here’s the abstract test – this is where all the actual test code will be placed. That way, the same contract test will be performed on each implementation.

// NOTE: No TestFixture attribute!
public abstract class A_TestThingContract
{

   protected abstract I_Thing CreatePatient();

   [SetUp]
   public virtual void SetUp()
   {
   }

   [TearDown]
   public virtual void CleanUp()
   {
   }

    [Test]
   [DataRow(1)]
   public virtual void testMethod(int i)
   { 
      // Do your testing here…
      Trace.WriteLine(i.ToString());
   }
}

Here’s how the concrete implementation of the contract test might look:

[TestFixture]
public class TestThingContract : A_TestThingContract
{

   protected override I_Thing CreatePatient()
   {
      return new Thing ();
   }

   // Override each test method like so:
   public override void testMethod(int i)
   {
      base.testMethod(i);
   }
}

The DataRow and Test attributes are inheritable, so they will be applied to the overridden method. This is nice because it means that you don’t have to duplicate them in the subclass.

At least there isn’t much in the way of duplication to work around these issues.

That’s it!

No comments: