【问题标题】:Why is a second (or third, or ...) browser window being opened?为什么要打开第二个(或第三个,或...)浏览器窗口?
【发布时间】:2021-04-04 09:56:47
【问题描述】:

我已经做了一个准系统设置来在 Java 中运行 Cucumber 和 Selenium。

当我有一个功能文件FirstScenario.feature 及其相应的步骤定义FirstScenarioSteps.java 时,一切都符合预期。所以我添加了第二个组合,那时我注意到打开了第二个浏览器窗口,即使在第一个功能文件中只运行一个场景。所以,我删除了组合,一切都很好了。我发现只有第二个步骤定义文件(没有功能文件)足以打开第二个浏览器窗口。我很好奇,所以我添加了第三步定义文件,并打开了三个浏览器窗口。

为什么(在这种情况下)每个场景会打开三个浏览器窗口?最后打开的两个窗口保持空白(即不导航到网站)。

这是一个步骤定义文件。

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 是按场景执行的,这正是我想要的。

【问题讨论】:

    标签: java selenium cucumber


    【解决方案1】:

    正如 Gaj Julije 所提到的,钩子是全局的,所以所有之前的钩子都会在每个功能之前执行。

    您可以通过使用依赖注入来解决这个问题。使用依赖注入时,Cucumber 将尝试创建步骤定义类的构造函数依赖项。这些依赖项是作为单例创建的,因此如果两个步骤定义类具有相同的依赖项,它们也会获得该依赖项的相同实例。

    这可用于在不同的步骤定义文件之间共享信息(或 Web 驱动程序)或确保只有一个 Web 驱动程序。

    这也比使用static Web 驱动程序更好。如果您不修改任何静态变量,则只能并行运行测试。

    cucumber-picocontainer 依赖添加到您的 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();
        }
    
    }
    

    然后在步骤定义中使用容器。

    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

    【讨论】:

    • 1. driver 中的 WebDriverContainer 应该是 webdriver 吗? 2.steps类的构造函数从哪里获取值?
    • 1.固定的。 2. Pico 容器可以递归地创建参数,只要它最终会找到一个零参数的构造函数。
    【解决方案2】:

    通过调用

    driver = new ChromeDriver();
    

    您正在创建一个新的驱动程序实例,这就是您拥有三个浏览器的原因,并且在您退出并打开新的之后。

    如果您不想要 3 个实例,则需要让浏览器初始化类并将全局变量驱动程序设为静态,并在该初始化类中添加 get 方法,这将返回您的静态 Web 驱动程序。确保其他类继承初始化类。

    你可以通过只创建一个浏览器实例来操作。 结论更改@Before 和@After 方法。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-09
    • 1970-01-01
    • 2012-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-06
    相关资源
    最近更新 更多