Есть ли способ поделиться утверждениями среди тестовых классов без наследования в 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);
}
}