views:

156

answers:

2

I have a number of C# integration tests written using the Given/When/Then style popularized by cucumber. I'm using a framework which basically works the same as NBehave.

A recurring issue I'm facing is the issue of setup and wiring up all the application state necessary for the integration test. Most of my tests look something like this:

Given an empty system
  And a new NetworkServer
  And a new ServerDatabase
  And a new Eventlogger
  And a new Networkconnection
  And a new LoggingClient
When the client logs a new event
Then it should appear in the server database

As you can see the action and assertion are single lines, but I have 6 lines of 'wiring'. Almost every test I have repeats these 6 lines.

This seems like a code smell to me, but I'm unsure as to how to handle this. I could refactor the 6 lines into a single one (Given "a valid system..." or somesuch) but that seems like it goes too far and I'd be hiding too much information.

I'd appreciate any thoughts from others with more experience in this area. Thanks a lot.

+1  A: 

To me this smells like you'd like to have a base class doing the setup kind of things and then have your test classes inherit from this base and only add the new testing functionality.

Base():
  constructor():
    do your wiring
    test if everything's ok


TestClass : Base
  constructor():
    Base.constructor()
    additional setup?

  test_functions()
    ..
BjoernD
Hrm... Thanks for the input. I must admit I don't like the base-class model as it means that half the setup code is hidden in the base constructor in a completely different file... always good to see different points of view though. +1
Orion Edwards
+1  A: 

We have something like this

public abstract class ContextSpecification
{
    [FixtureSetUp]
    public void SetUp()
    {
        EstablishContext();
        Act();
    }

    protected abstract void Act();

    protected abstract void EstablishContext();

    [FixtureTearDown]
    public void TidyUpCore()
    {
        TidyUp();
    }

    protected virtual void TidyUp()
    {

    }
}

Then for each group of similar tests we create a BaseContext like this:

internal class TestClassTests 
{
    internal abstract class BaseContext : ContextSpecification
    {
        protected TestClass _sut;

        protected override void Act()
        {

        }

        protected override void EstablishContext()
        {
            _sut = new TestClass ();
           // common wiring
        }
    }

   internal class Given_this_situation : BaseContext
   {
       protected override void EstablishContext()
       {
           base.EstablishContext();
           // test specific wiring
       }

       protected override void Act()
       {
           // carry out the test actions
       }

       [UnitTest]
       public void ThisShouldBeTrue()
       {
          Assert.IsTrue();
       }
   }
}
Samuel Jack
Interesting to see a single "Act" method and then all the assertions handled seperately afterwards. How do you find this working in practice? I thought one of the goals of unit testing was to have each Test Method be autonomous (not depend on "Act" having run before it)...
Orion Edwards
It works very well - we tend to put each assertion in its own test method, and that conveys more information when a test breaks: we don't have to hunt for the assertion that failed. With this technique we have simply moved the principle up one level in the hierarchy - each test class is autonomous.
Samuel Jack