【问题标题】:How does copying/passing instances of a WebDriver work, and is it dangerous?复制/传递 WebDriver 的实例如何工作,是否危险?
【发布时间】:2012-10-21 09:53:51
【问题描述】:

几个月来,我一直在一个开发 Selenium WebDriver 基础架构的团队中工作,而我们从测试用例和页面对象访问驱动程序对象的方式让我很烦。

我们的测试用例创建一个新的 WebDriver 实例并打开浏览器。这个新实例存储在测试用例类中。

然后,测试用例实例化一个页面对象。与Selenium's Page Object Pattern 一起,这些页面对象将WebDriver 作为其构造函数中的参数(尽管我注意到在我们的版本中它不是最终版本)。各种页面对象方法使用在页面对象的构造函数中设置的驱动程序来完成它们的工作。如果页面对象方法导航到新页面对象,则将 WebDriver 传递给它。就像在 Selenium 的例子中一样:

public class LoginPage {
    private final WebDriver driver;

    public LoginPage(WebDriver driver) {
        this.driver = driver;

        // Check that we're on the right page.
        if (!"Login".equals(driver.getTitle())) {
            // Alternatively, we could navigate to the login page, perhaps logging out first
            throw new IllegalStateException("This is not the login page");
        }
    }

    // Conceptually, the login page offers the user the service of being able to "log into"
    // the application using a user name and password. 
    public HomePage loginAs(String username, String password) {
        // This is the only place in the test code that "knows" how to enter these details
        driver.findElement(By.id("username")).sendKeys(username);
        driver.findElement(By.id("passwd")).sendKeys(password);
        driver.findElement(By.id("login")).submit();

        // Return a new page object representing the destination. Should the login page ever
        // go somewhere else (for example, a legal disclaimer) then changing the method signature
        // for this method will mean that all tests that rely on this behaviour won't compile.
        return new HomePage(driver);
    }
}

这使得 WebDriver 实例看起来是唯一且重要的,就像必须从页面对象传递到页面对象的火炬一样。代码的风格让我觉得我总是必须确保我使用的驱动程序实例与上次操作中使用的驱动程序实例相同。

但是,如果页面上有多个页面对象,并且页面对象方法不会返回您计划接下来使用的页面对象,那么这种“传递火炬”会变得复杂或不可能。当屏幕上有两个页面对象并且需要在它们之间交替时,如何在同一个 WebDriver 实例上进行操作,而无需切换到新页面或创建新页面对象?

所有这些困惑让我相信实际上没有必要传递火炬,甚至可能发生(所有这些页面对象都存储对同一个 WebDriver 实例的引用吗?),但是我不知道为什么这种模式在 Selenium 给出的描述中提出了建议。

那么,我需要担心“传递火炬”吗?或者任何页面对象在使用其 WebDriver 实例化后是否会正常运行,即使其他页面对象在此期间使用它们自己版本的同一 WebDriver 执行操作?

将 WebDriver 设为单例会更容易/更好吗,所有人都可以访问,因为我们不会在任何给定时间为每个 JVM 使用多个 WebDriver?然后我们根本不需要在构造函数中传递 WebDriver。提前感谢您的任何意见。

【问题讨论】:

  • 好吧,在我的项目中,我有以下结构:BaseSeleniumTest.java,它由其他类扩展(包含一组带有@Test 注释的 tets)。所以在 BaseSeleniumTest.java 我声明了 WebDriver 驱动程序;作为静态变量,这样我就避免了创建多个 webDriver 实例。
  • 只是把它放在那里,如果你真的需要为给定的用例使用两个单独的浏览器,那么在某些情况下你会想要多个 webdriver 实例。
  • "...那么我不知道为什么 Selenium 给出的描述中会建议这种模式。"你能提供一个链接吗?我记得他们将 WebDriver 实例传递给静态方法。
  • 这不是一个明确的建议,但建议在我发布的代码中。 loginAs 方法是 LoginPage 的一部分,它在创建时从某个地方获取驱动程序。 loginAs 方法返回一个 HomePage,它是从 LoginPage 传递给驱动程序的。因此,在您的测试中,您创建了一个驱动程序,将其传递给您的第一个页面对象(如 LoginPage),然后 LoginPage 将其传递给 HomePage 等。它给人的印象是驱动程序必须被传递从页面对象到页面对象,不是吗?

标签: java selenium webdriver


【解决方案1】:

最好将webdriver标记为整个框架的单例。我目前一直在使用这种模式,它工作正常。
注意:处理并行执行时应小心。

@代码热情 例如获取一个类GeneralLibrary,在其中创建一个WebDriver

使用GeneralLibrary 作为超类扩展页面对象模型中的类

【讨论】:

  • 我肯定想使用单例,特别是如果 WebDriver 确实维护某种状态信息,这使得所有页面对象和操作都必须使用 same WebDriver .我不认为我们计划在同一台机器上使用相同的 JVM 进行并行执行。到目前为止,我使用 Selenium 的经验让我担心它太脆弱而无法做到这一点 - 我担心一个浏览器上的操作会扰乱另一个浏览器的执行。
  • @rironin,每个 webdriver 实例都与一个会话 id 相关联,可以假定为随机生成的 32 位密钥。因此,一个浏览器操作根本不会影响其他浏览器
  • 一个浏览器根本不会直接影响另一个浏览器是有道理的,但是当 IE 窗口不在焦点时,IE 运行自动化不是特别有问题吗?如果浏览器窗口被不同的浏览器窗口覆盖,如果浏览器被最小化等,所有自动化调用是否同样有效?我觉得如果您在同一台机器上同时运行多个测试,则无法保证正在操作的浏览器具有焦点或可见。
  • @rironin,Selenium 完全基于创建的浏览器实例。但不在浏览器区域覆盖/最小化/最大化
  • @Automation_User 您能否提供 sn-p 或链接以使 WebDriver 在您的答案中成为单例?
猜你喜欢
  • 2022-06-13
  • 2021-02-04
  • 2020-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-14
  • 1970-01-01
  • 2016-02-11
相关资源
最近更新 更多