我的C#Specflow测试项目中至少有3个.feature文件,例如:
Given I am at the Home Page
当我第一次在文件Feateure1.feature
中编写步骤并创建步骤方法时,我将它放在一个步骤文件中,比如说Steps1.cs
,它继承自初始化{的基类{1}}。我的所有FirefoxDriver
类都继承自此基类。
然后,我写了StepsXXXX.cs
,它也有一个步骤Feature2.feature
。并且步骤自动绑定到Given I am at the Home Page
'直到现在,没问题。这就是我想要的 - 在整个测试项目中拥有可重复使用的步骤。但问题是,每当我运行一个包含不同Steps1.cs
文件步骤的场景时,我就会运行各种浏览器实例。
==
我很确定这是因为我的StepsXXXX
(绑定类)都是从这个具有自己的IWebDriver的基类继承的,并且当调用该步骤时,其他一切(包括调用前/后场景方法)。但我无法弄清楚如何解决这个问题。
我仍然想要可重复使用的步骤。我试图将这些步骤放在基类中,但它没有用。 我也想过改变绑定,但是specflow使用有意义的字符串来做,我不想把它们改成误导性的字符串。
有没有人偶然发现了这个? 任何帮助都非常感谢。
答案 0 :(得分:5)
问题是SpecFlow绑定不尊重继承。所有自定义属性都被认为是全局的,因此所有SpecFlow都会搜索带有[Binding]的类列表,然后为所有[Given] / [When] / [Then] s建立一个字典,以便它可以评估它们为了最好的匹配。然后它将创建该类的实例(如果它还没有这样做)并在其上调用该方法。
因此,您的简单案例都保留在Steps1类中,因为它是第一个完美匹配。你的更复杂的情况开始实例化更多的类,因此多个浏览器,你的重构尝试将无法工作,因为你的抽象基类没有[绑定]。
我可能首先将所有步骤类层次结构展平为一个大的AllSteps.cs类。 这看起来可能适得其反,但您所做的只是安排代码,了解当前绑定对SpecFlow功能的影响。这样您就可以开始重构不同GWT绑定之间的重叠
目前,您的绑定安排在场景周围。您需要做的是围绕您的功能重构它们。在开始之前阅读Whose Domain is it anyway?,这可能会给你一些好主意。然后查看SpecFlow文档中的Sharing-Data-between-Bindings,了解如何在新的步骤类之间建立链接。
答案 1 :(得分:3)
您可以使用Scoped bindings使用[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(){
{ }
}
答案 2 :(得分:2)
我面临同样的问题。
我想要一个功能文件,它将调用不同cs类中的步骤。当我想为每个场景设置和拆除时,问题就出现了。
使用步骤类构造函数和Dispose()
是不可能的,因为该场景使用了多个步骤类,我不想在场景中多次“设置”。
对两个步骤类使用[BeforeScenario]
和[AfterScenario]
也会使跑步者在两个类中运行before和after方法,使其设置运行两次。
所以我所做的就是创建另一个名为BrowserScenarioSetup
的第三类,将前后场景类放入其中,为场景设置浏览器并分配给ScenarioContext.Current
字典。测试运行时,只为场景创建了一个浏览器,我可以使用任何类中定义的场景步骤,但只使用Scenario.Context.Current
来获取浏览器实例。
我可以让两个步骤类都有一个基本步骤类,并创建一个简短的方法来获取浏览器实例(或在设置中创建的任何共享实例),只是为了隐藏Scenario.Context.Current
最后,我可以标记[BeforeScenario("Browser", "IE")]
并在功能或场景中使用@Browser和@IE,只在合适的上下文中调用此设置方法。
答案 3 :(得分:2)
我认为这比问题和答案要简单得多。这里有两个问题:
AISki在关于specflow上下文的文档链接中给出了正确的答案,但它并没有真正作为答案呈现,并且将劣质答案作为实际答案而分散注意力。
关于您所看到的行为的答案是,您应该完全按照设置的方式预期发生的事情。如果你有多个创建浏览器实例的绑定类(如果它们都有一个创建浏览器实例的公共基础),并且它们在你的功能中有匹配,你应该期望有多个浏览器实例。
您想要的答案(您的步骤中共享的单个浏览器)是您应该使用specflow的上下文功能来控制对浏览器实例的依赖性。这相当于依赖注入。你的步骤定义类应该采用构造函数依赖于创建浏览器实例的东西 - specflow为你管理依赖关系,你将为你创建的第一个类获得一个新实例,然后在之后获得相同的实例。
https://github.com/techtalk/SpecFlow/wiki/Sharing-Data-between-Bindings