为什么要打开第二个(或第三个,或...)浏览器窗口?
我已经做了一个准系统设置来在 Java 中运行 Cucumber 和 Selenium.
I've made a barebones setup to run Cucumber and Selenium in Java.
当我有一个功能文件 FirstScenario.feature
及其相应的步骤定义 FirstScenarioSteps.java
时,一切都符合预期.所以我添加了第二个组合,那时我注意到打开了第二个浏览器窗口,即使在第一个功能文件中只运行一个场景.所以,我删除了组合,一切都很好了.我发现只有第二个步骤定义文件(没有功能文件)足以打开第二个浏览器窗口.我很好奇,所以我添加了第三步定义文件,并打开了三个浏览器窗口.
When I have one feature file FirstScenario.feature
with its corresponding step definition FirstScenarioSteps.java
, everything as expected. So I added a second combo, and that's when I noticed that a second browser window was opened, even when running only one scenario in the first feature file. So, I deleted the combo and everything was fine again. I found out that only the second step definition file (without the feature file) was enough to open that second browser window. I was curious so I added a third step definition file, and three browser windows got opened.
为什么(在这种情况下)每个场景会打开三个浏览器窗口?最后打开的两个窗口保持空白(即不导航到网站).
Why are there (in this case) three browser windows being opened per scenario? The last two windows opened remain blank (ie. do not navigate to a website).
这是一个步骤定义文件.
Here's a step definition file.
public class ThirdFeatureSteps {
WebDriver driver;
// Tests or no tests, browser windows are still opened.
@Before
public void setup() {
System.setProperty(
"webdriver.chrome.driver",
System.getProperty("user.dir") + "\webdriver\chromedriver.exe"
);
driver = new ChromeDriver();
}
@After
public void teardown() {
driver.quit();
}
}
我知道@Before 和@After 是按场景执行的,这正是我想要的.
I understand that @Before and @After are executed per scenario, and that is exactly what I want.
推荐答案
正如 Gaj Julije 提到的,钩子是全局的,所以所有之前的钩子都在每个功能之前执行.
As Gaj Julije mentioned, hooks are global so all before hooks are executed before each feature.
您可以通过使用依赖注入来解决这个问题.使用依赖注入时,Cucumber 将尝试创建步骤定义类的构造函数依赖项.这些依赖项是作为单例创建的,因此如果两个步骤定义类具有相同的依赖项,它们也会获得该依赖项的相同实例.
You can solve this by using dependency injection. When using dependency injection Cucumber will try to create the constructor dependencies of your step definition classes. These dependencies are created as singletons so if two step definition classes have the same dependency they'll also get the same instance of that dependency.
这可用于在不同的步骤定义文件之间共享信息(或 Web 驱动程序)或确保只有一个 Web 驱动程序.
This can be used to share information (or web drivers) between different step definition files or ensure that there is only a single web driver.
这也比使用 static
Web 驱动程序更好.如果您不修改任何静态变量,则只能并行运行测试.
This is also better then using a static
web driver. You can only run your tests in parallel if you don't modify any static variables.
将 cucumber-picocontainer 依赖项添加到您的 pom.xml:
Add the cucumber-picocontainer dependency to your pom.xml:
<dependencies>
[...]
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-picocontainer</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
[...]
</dependencies>
然后为WebDriver
创建一个容器:
public class WebDriverContainer {
public WebDriver webdriver;
@Before
public void setup() {
System.setProperty(
"webdriver.chrome.driver",
System.getProperty("user.dir") + "\webdriver\chromedriver.exe"
);
webdriver = new ChromeDriver();
}
@After
public void teardown() {
webdriver.quit();
}
}
然后在步骤定义中使用容器.
Then use the container in your step definitions.
public class FirstFeatureSteps {
WebDriverContainer container;
public FirstFeatureSteps(WebDriverContainer container){
this.container = container;
}
// use container.webdriver in your steps
}
public class SecondFeatureSteps {
WebDriverContainer container;
public SecondFeatureSteps(WebDriverContainer container){
this.container = container;
}
// use container.webdriver in your steps
}
public class ThirdFeatureSteps {
WebDriverContainer container;
public ThirdFeatureSteps(WebDriverContainer container){
this.container = container;
}
// use container.webdriver in your steps
}
但请记住,您可以在构造函数中使用 container.webdriver
,Web 驱动程序将 null
直到 before-hook 运行.
But keep in mind that you can use container.webdriver
in the constructor, the web driver will be null
until the before-hook has ran.
相关文章