可以在步骤之间共享SpecFlow功能吗?

Rik*_*ley 4 c# testing bdd specflow

我们有从三个不同角度测试的代码:

  • 内部(直接呼叫)
  • 网络服务
  • Web应用程序

由于我们不想编写三次功能文件,似乎我们应该在Steps之间共享功能,但我无法弄清楚如何完成这项功能,除了可能在VS项目之间共享文件,这似乎一直是有点,好吧,片状.

在项目之间共享功能文件是实现这一目标的最佳方式,还是有更明智的方法?

Sam*_*der 5

我知道这是很久以前的问题,但我认为你想要的是可能的,并且有很多方法可以实现它,正如我所理解的那样.实际上,您真正想要的是定义一次功能,但根据您是在调用内部服务,公共Web服务还是WebApp,切换为该功能调用的步骤.讨论了在邮件列表中针对specflow解决此问题的各种方法,但其主要内容如下(示例显示了API与UI方法,但同样适用于您的内部vs Web服务与Web应用相比):

选项1 #

(感谢邮件列表中的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)

选项2 ##

(感谢邮件列表中的GáspárNagy)

尝试在构建期间生成测试.我不确定这是如何工作的,但这是我们可以调查的一个领域.

选项3 ##

(感谢来自邮件列表的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)

这仍然让你知道如何知道要注册哪个实现的问题.这将取决于您的解决方案,您的构建环境,您的测试执行环境等的具体细节.一些选项...

  • 标签参数 BeforeScenarioAttribute
  • 为您的项目创建两个不同的构建配置,每个配置定义不同的常量,并使用预编译器指令在代码中构建正确的注册
  • 添加条件逻辑以检查环境变量
  • 添加条件逻辑以检查配置设置
  • 我没有检查过,但可能ScopeAttribute是可扩展的,你可以创建一个子类,并为是否BeforeScenarioAttribute执行方法提供自己的逻辑.

希望这会给你一些选择来做你想要的.

恕我直言,第一个选项可能是最好的,虽然选项3也很好.