10

In MSpec there is a neat feature that allows you share assertions between multiple tests. They're called "behaviors"

Behaviours define reusable specs that encapsulate a particular set of, you guessed it, behaviours; you’re then able to include these specs in any context that exhibits a particular behaviour.

You define them as a class with assertions (It fields)

public class VehicleThatHasBeenStartedBehaviors
{
    protected static IVehicle vehicle;
    It should_have_a_running_engine = () => vehicle.IsEngineRunning.ShouldBeTrue();
    It should_be_idling = () => vehicle.RevCount.ShouldBeBetween(0, 1000);
}

and include them in your test class like

public class when_starting_a_car
{
    Behaves_like<VehicleThatHasBeenStartedBehaviors> a_started_vehicle;
}

How can I accomplish the same with NUnit?

Anthony Mastrean
  • 21,850
  • 21
  • 110
  • 188
ptomasroos
  • 1,129
  • 1
  • 9
  • 18
  • Do you mean two tests running simultaneously? Or some kind of verification that is run for two tests? Do you have a code sample or link to one that uses this feature? – Ryan Gates Jan 07 '13 at 18:16
  • I want to have 1 class with assertions that is included in another class. Can't use inheritance. Example. http://lostechies.com/jamesgregory/2010/01/18/behaviours-in-mspec/ – ptomasroos Jan 08 '13 at 05:58

4 Answers4

4

You can use extension methods to "package" your type-specific assertions:

public static class VehicleAssertions {
    public static void ShouldBeStarted(this IVehicle vehicle) {
        // TODO: change these to NUnit assertions
        vehicle.IsEngineRunning.ShouldBeTrue();
        vehicle.RevCount.ShouldBeBetween(0, 1000);
    }
}

Use it on a test method:

testVehicle.ShouldBeStarted();
Jordão
  • 55,340
  • 13
  • 112
  • 144
3

Is there a way to share assertions among test classes without inheritance in NUnit?

Considering you just want to share assertions and you're testing for behaviors on interfaces, you could just create something simple:

public interface IBehavior
{
    void Check();
}

public class VehicleThatHasBeenStartedBehaviors : IBehavior
{
    protected IVehicle vehicle;

    public VehicleThatHasBeenStartedBehaviors(IVehicle vehicle)
    {
        this.vehicle = vehicle;
    }

    public void Check()
    {
        Assert.That(vehicle.IsEngineRunning, Is.True);
        Assert.That(vehicle.RevCount, Is.LessThanOrEqualTo(1000));
        Assert.That(vehicle.RevCount, Is.GreaterThanOrEqualTo(0));
    }
}

[TestFixture]
public class when_starting_a_car
{
    protected Car car;

    [SetUp]
    public void SetUp()
    {
        car = new Car();
    }

    [Test]
    public void behaves_like_a_started_vehicle()
    {
        new VehicleThatHasBeenStartedBehaviors(car).Check();
    }
}

BUT, if you want to specifically use MSpec syntax, I think you may have to implement it or find some framework that does it for you.

EDIT

Reading your comments on the question I realized you may be wanting to reuse test methods, and not simply assertions. If that's the case, you could write a customized addin for NUnit. That may sound a little overkill, but it's up to you to decide.

My starting point would be writing a customized SuiteBuilder object:

Purpose

A SuiteBuilder is an addin used to build a test fixture from a type. NUnit itself uses a SuiteBuilder to recognize and build TestFixtures.

Using your own suite builder you could read some behavior classes and compose your fixture.

[NUnitAddin]
public class TestCompositionAddinProvider : IAddin
{
    #region IAddin Members

    public bool Install(IExtensionHost host)
    {
        IExtensionPoint builders = host.GetExtensionPoint("SuiteBuilders");
        if (builders == null)
            return false;
        builders.Install(new TestCompositionSuiteBuilder());
        return true;
    }

    #endregion
}
public class TestCompositionSuiteBuilder : ISuiteBuilder
{
    #region ISuiteBuilder Members

    public bool CanBuildFrom(Type type)
    {
                    //TODO: Create validation logic
        return true;
    }

    public NUnit.Core.Test BuildFrom(Type type)
    {
        if (CanBuildFrom(type))
            return new ComposedSuiteExtension(type);
        return null;
    }

    #endregion
}

public class ComposedSuiteExtension : TestSuite
{
    public ComposedSuiteExtension(Type fixtureType)
        : base(fixtureType)
    {
        //TODO: Create logic to add test methods from various behaviors.
    }
}
Marcos Brigante
  • 974
  • 9
  • 25
1

You might want to have a look at the Mixin concept.

Here is an SO answer describing how to accomplish this with C# 4.0

Community
  • 1
  • 1
Mikael Östberg
  • 16,982
  • 6
  • 61
  • 79
  • But, I don't think that this approach will work for the NUnit test runner out of the box. It uses basic reflection to find classes/methods decorated with their specific attributes. This is a dynamic-ish lookup? – Anthony Mastrean Jan 10 '13 at 14:52
1

Another simple solution is to create static Assertion methods in a Helper class that you call in each applicable test. For instance like so:

public static class VehicleAssert 
{
    public void AssertCorrectlyStarted(IVehicle car) 
    {
         vehicle.IsEngineRunning.ShouldBeTrue();
         vehicle.RevCount.ShouldBeBetween(0, 1000); 
    }
 }   

Then in each testfixture use it like this:

[TestFixture]
public class CarTest 
{
     [Test]
     public void TestCarStartsCorrectly() 
     {
         var car = new Car();
         car.Start();
         VehicleAssert.AssertCorrectlyStarted(car);
     }
}
Bas Bossink
  • 9,388
  • 4
  • 41
  • 53