Есть ли способ поделиться утверждениями среди тестовых классов без наследования в NUnit?

В MSpec есть аккуратная функция, которая позволяет делиться утверждениями между несколькими тестами. Они называются "behaviors"

Поведение определяет параметры многократного использования, которые инкапсулируют определенный набор, вы догадались, поведение; Затем вы можете включить эти спецификации в любой контекст, который проявляет конкретное поведение.

Вы определяете их как класс с утверждениями (It)

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);
}

и включить их в свой тестовый класс, например

public class when_starting_a_car
{
    Behaves_like<VehicleThatHasBeenStartedBehaviors> a_started_vehicle;
}

Как я могу сделать то же самое с NUnit?

Ответ 1

Вы можете использовать методы расширения для "упаковки" ваших утверждений типа:

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);
    }
}

Используйте его по методу тестирования:

testVehicle.ShouldBeStarted();

Ответ 2

Есть ли способ поделиться утверждениями среди тестовых классов без наследование в NUnit?

Учитывая, что вы просто хотите делиться утверждениями и тестируете поведение на интерфейсах, вы можете просто создать что-то простое:

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();
    }
}

НО, если вы хотите специально использовать синтаксис MSpec, я думаю, вам, возможно, придется реализовать его или найти некоторую фреймворк, которая сделает это за вас.

ИЗМЕНИТЬ

Читая ваши комментарии по вопросу, я понял, что вы можете повторно использовать методы тестирования, а не просто утверждения. В этом случае вы можете написать настроенное дополнение для NUnit. Это может показаться немного излишним, но решать вам решать.

Моя стартовая точка будет писать настраиваемый объект SuiteBuilder:

Цель

SuiteBuilder - это добавление, используемое для сборки тестового прибора из типа. Сам NUnit использует SuiteBuilder для распознавания и сборки TestFixtures.

Используя собственный конструктор пакетов, вы можете прочитать некоторые классы поведения и составить свое устройство.

[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.
    }
}

Ответ 3

Возможно, вам стоит взглянуть на концепцию Mixin.

Вот ответ SO , описывающий, как это сделать с помощью С# 4.0

Ответ 4

Другим простым решением является создание статических методов Assertion в классе Helper, которые вы вызываете в каждом применимом тесте. Например, так:

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

Затем в каждой тестовой игре используйте его так:

[TestFixture]
public class CarTest 
{
     [Test]
     public void TestCarStartsCorrectly() 
     {
         var car = new Car();
         car.Start();
         VehicleAssert.AssertCorrectlyStarted(car);
     }
}