Specflow特性文件使用相同的步骤导致多个浏览器实例启动

本文关键字:启动 实例 浏览器 文件 Specflow | 更新日期: 2023-09-27 18:04:56

在我的c# Specflow测试项目中,我至少有3个.feature文件,其中我有步骤,例如:

Given I am at the Home Page

当我第一次在文件Feateure1.feature中编写步骤并创建步骤方法时,我将它放在一个步骤文件中,例如,Steps1.cs,它继承了初始化FirefoxDriver的基类。我所有的StepsXXXX.cs类都继承自这个基类。

然后,我写了Feature2.feature,它也有一个步骤Given I am at the Home Page。并且该步骤自动绑定到Steps1.cs

中的步骤

到现在为止,没有问题。这正是我想要的——在整个测试项目中具有可重用的步骤。但问题是,每当我运行一个场景,在不同的StepsXXXX文件的步骤,我得到不同的浏览器实例运行。

= = = = = =

我很确定这是由于我的StepsXXXX(绑定类)都继承自这个基类,它有自己的IWebDriver,当步骤被调用时,其他一切(包括前/后场景方法)被调用。但是我不知道如何解决这个问题。

我仍然需要可重用的步骤。我试图将这些步骤放在基类中,但它不起作用。我也想过改变绑定,但是specflow使用有意义的字符串来这样做,我不想把它们变成误导的字符串。

有人偶然发现这个吗?任何帮助都非常感谢。

Specflow特性文件使用相同的步骤导致多个浏览器实例启动

您可以使用[Scope(Tag = "mytag", Feature = "feature title", Scenario = "scenario title")]使用作用域绑定来引用特定的场景或特性,如:

Feature: Feateure1
Scenario: demo
Given I am at the Home Page
When ....
[Binding, Scope(Feature = "Feateure1")]
public class Steps1{
 [Given(@"Given I am at the Home Page")]
 public void GivenIAmAtTheHomePage(){
  {  }
}
Feature: Feateure2
Scenario: demo
Given I am at the Home Page
When ....
...
[Binding,Scope(Feature = "Feateure2")]
public class Steps2{
 [Given(@"Given I am at the Home Page")]
 public void GivenIAmAtTheHomePage(){
 {  }
}

问题是SpecFlow绑定不尊重继承。所有自定义属性都被认为是全局的,因此SpecFlow所做的就是用[Binding]搜索类列表,然后为所有的[Given]/[When]/[then]建立一个字典,以便它可以评估它们以获得最佳匹配。然后,它将创建类的一个实例(如果它还没有这样做的话)并调用它的方法。

结果,您的简单案例都留在Steps1类中,因为它是第一个完美匹配。你的更复杂的情况开始实例化更多的类,因此多个浏览器,你的重构尝试将不起作用,因为你的抽象基类上没有一个[Binding]。

我可能会开始扁平化所有的步骤类层次结构,成一个大的AllSteps.cs类。这可能看起来适得其反,但是你真正做的是安排代码,就像当前绑定出现在你的SpecFlow特性。这样您就可以开始重构出不同GWT绑定之间的重叠。

目前您的绑定是围绕场景安排的。您需要做的是围绕您的功能重构它们。读一下这到底是谁的领地?在你开始之前,这可能会给你一些好主意。然后查看SpecFlow文档中的绑定之间的数据共享,了解如何在新的步骤类之间进行链接。

我认为这比这里的问答要简单得多。这里有两个问题:

AISki在specflow上下文文档的链接中给了你正确的答案,但它并没有真正作为答案呈现出来,而且把一个次等的答案作为实际答案呈现出来会分散注意力。

关于你看到的行为的答案是,你应该准确地期望你设置事物的方式会发生什么。如果你有多个绑定类来创建浏览器实例(如果它们都有一个创建浏览器实例的公共基础,你就会这样做),并且它们在你的特性中有匹配,你应该期待多个浏览器实例。

你想要的答案(在你的步骤中共享一个浏览器)是你应该使用specflow的上下文特性来控制对浏览器实例的依赖。这相当于依赖注入。你的步骤定义类应该有一个构造函数依赖于创建你的浏览器实例的东西——specflow为你管理依赖,你会得到一个新的实例为你创建的第一个类,然后相同的一个。

https://github.com/techtalk/SpecFlow/wiki/Sharing-Data-between-Bindings

我也面临同样的问题

我想有一个功能文件,将调用步骤在不同的cs类。当我想为每个场景设置和拆除时,这个问题就出现了。

使用步骤类构造器和Dispose()是不可能的,因为该场景使用多个步骤类,我不想在一个场景中多次"设置"。

对于两个步骤类使用[BeforeScenario][AfterScenario]也会使运行程序在两个类中运行before和after方法,从而使其设置运行两次。

所以我所做的是创建另一个叫做BrowserScenarioSetup的第三个类,把之前和之后的场景类放在里面,为场景设置一个浏览器,并分配给ScenarioContext.Current字典。当测试运行时,只为一个场景创建一个浏览器,我可以使用在任何类中定义的场景步骤,但只使用Scenario.Context.Current来获取浏览器实例。

我可以使两个步骤类都有一个基本步骤类,并创建一个简短的方法来获取浏览器实例(或在设置中创建的任何共享实例),只是为了隐藏Scenario.Context.Current

最后,我可以标记[BeforeScenario("Browser", "IE")],并在功能或场景中使用@Browser和@IE,仅在合适的上下文中调用此设置方法。