我知道这是很久以前的问题,但我认为你想要的是可能的,并且有很多方法可以实现它,正如我所理解的那样.实际上,您真正想要的是定义一次功能,但根据您是在调用内部服务,公共Web服务还是WebApp,切换为该功能调用的步骤.讨论了在邮件列表中针对specflow解决此问题的各种方法,但其主要内容如下(示例显示了API与UI方法,但同样适用于您的内部vs Web服务与Web应用相比):
(感谢邮件列表中的Oliver Friedrich)
您需要为每个要为步骤改变的选项创建一个程序集,因此一个用于内部,一个用于Web服务,一个用于webapp.您告诉配置中有关所有不同程序集的specflow,如下所示:
<specFlow>
<stepAssemblies>
<stepAssembly assembly="Tests.API" />
<stepAssembly assembly="Tests.UI" />
</stepAssemblies>
</specFlow>
Run Code Online (Sandbox Code Playgroud)
然后在您的常见测试步骤中,您可以[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");
}
}
}
Run Code Online (Sandbox Code Playgroud)
(感谢邮件列表中的GáspárNagy)
尝试在构建期间生成测试.我不确定这是如何工作的,但这是我们可以调查的一个领域.
(感谢来自邮件列表的Dan Mork)
如果您使用SpecFlow的依赖注入功能,那么您可以创建一个接口来执行您想要执行的调用,并在一组通用步骤中使用它.然后,您可以拥有该接口的3个实现,一个调用您的内部服务,一个调用Web服务,另一个调用Web应用程序.剩下的就是将该接口的正确实现注入到specflow步骤文件中,可以这样做:
// 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
}
}
Run Code Online (Sandbox Code Playgroud)
这仍然让你知道如何知道要注册哪个实现的问题.这将取决于您的解决方案,您的构建环境,您的测试执行环境等的具体细节.一些选项...
BeforeScenarioAttributeScopeAttribute是可扩展的,你可以创建一个子类,并为是否BeforeScenarioAttribute执行方法提供自己的逻辑.希望这会给你一些选择来做你想要的.
恕我直言,第一个选项可能是最好的,虽然选项3也很好.