【发布时间】: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 等。它给人的印象是驱动程序必须被传递从页面对象到页面对象,不是吗?