Я знаю, что это было задано довольно давно, но то, что я думаю, вы хотите, возможно, и, как я понимаю, есть несколько способов добиться этого. По сути, вы действительно хотите определить функцию один раз, но отключить шаги, которые вызываются для этой функции, в зависимости от того, вызываете ли вы внутреннюю службу, общедоступную веб-службу или веб-приложение. Различные подходы к решению этой проблемы обсуждаются в списке рассылки для specflow, но суть его заключается в следующем (пример показывает подход API и пользовательского интерфейса, но то же самое относится к вашему внутреннему, веб-сервису и веб-приложению, я считаю):
Опция 1 #
(спасибо Оливеру Фридриху из списка рассылки)
вам нужно создать одну сборку для каждого из параметров, которые вы хотите изменить для шагов, поэтому одну для внутреннего, одну для веб-службы и одну для веб-приложения. Вы сообщаете specflow обо всех различных сборках в конфигурации, например:
<specFlow>
<stepAssemblies>
<stepAssembly assembly="Tests.API" />
<stepAssembly assembly="Tests.UI" />
</stepAssemblies>
</specFlow>
то в ваших общих тестовых шагах у вас есть шаг [BeforeTestRun]
, который выбирает, из какой сборки загружать шаги:
[Binding]
public class TestRunSetup {
// this method needs to be static
[BeforeTestRun]
public static void BeforeTestRun()
{
if (RunApiTests()) // <-- implement this method to choose whether to run the tests via your chosen method
{
Assembly.Load("Tests.API");
}
else
{
Assembly.Load("Tests.UI");
}
}
}
Вариант 2 ##
(спасибо Gáspár Nagy из списка рассылки)
Попробуйте генерировать тесты во время сборки. Я точно не знаю, как это будет работать, но мы можем исследовать эту область.
Вариант 3 ##
(спасибо Дэну Морку из списка рассылки)
Если вы используете возможности внедрения зависимостей SpecFlow, вы можете создать интерфейс для выполнения вызовов, которые вы хотите сделать, и использовать его в общем наборе шагов. Тогда у вас может быть 3 реализации этого интерфейса, одна из которых вызывает вашу внутреннюю службу, другая — веб-службу, а третья — управление веб-приложением. После этого остается только внедрить правильную реализацию этого интерфейса в файлы шага спецификации, что можно сделать следующим образом:
// the abstract concept of the system that could be implemented with
Selenium, HttpClient, etc.
public interface IDocument
{
string Title { get;}
void Load();
}
// the steps that are executed when the scenarios from your feature
file are executed
[Binding]
public class Steps
{
private readonly IDocument _document;
public Steps(IDocument document)
{
_document = document;
}
[Given("something")]
public void GivenSomething()
{
// set up given state
}
[When("I view the document")]
public void WhenIViewTheDocument()
{
_document.Load();
}
[Then(@"the title should be ""(.*)""")]
public void Then(string title)
{
Assert.ArEqual(_document.Title, title);
}
}
// this is where the magic happens - get the dependency injection
// container and register an IDocument implementation
[Binding]
public class Dependencies
{
private readonly IObjectContainer _objectContainer;
public Dependencies(IObjectContainer objectContainer)
{
_objectContainer = objectContainer;
}
[BeforeScenario]
public void RegisterDocumentInterfaces()
{
// register the correct IDocument implementation - UI or API
}
}
Это по-прежнему оставляет вас с проблемой, как узнать, какую реализацию зарегистрировать. Это будет зависеть от специфики вашего решения, среды сборки, среды выполнения тестов и т. д. Некоторые варианты для этого...
- параметр тега для
BeforeScenarioAttribute
- создайте две разные конфигурации сборки для вашего проекта, каждая из которых определяет разные константы и использует директивы прекомпилятора для встраивания правильных регистраций в код
- добавить условную логику для проверки переменной среды
- добавить условную логику для проверки параметра конфигурации
- Я не проверял, но, возможно,
ScopeAttribute
можно расширить, чтобы вы могли создать подкласс и предоставить собственную логику того, выполняется ли метод BeforeScenarioAttribute
.
Надеюсь, это даст вам несколько вариантов сделать то, что вы хотите.
ИМХО, первый вариант, вероятно, лучший, хотя вариант 3 тоже довольно приятный.
01.07.2014