10

关于 selenium webdriver 中的页面对象的快速问题。我们的网站非常动态,有很多 ajax 和各种身份验证状态。很难弄清楚如何定义每个页面对象但是可以说我已经弄清楚并定义了几个代表我们网站的页面对象。

你如何处理从页面到页面的交叉。因此,我为我的主页获取了一个页面对象,为我的帐户页面获取了一个页面对象,为我的结果页面获取了一个。然后我需要编写一个遍历我所有页面的测试来模拟用户执行多个操作。

你怎么说给我一个 HomePage 对象来创建一个新的使用 -> 然后获取一个帐户页面对象来执行一些用户操作 - 然后获取一个结果页面对象来验证所有来自单个脚本的这些操作。

人们是如何做到这一点的?

谢谢

4

5 回答 5

10

当您模拟让用户在浏览器的 URL 栏中输入新 URL 时,测试类有责任创建它需要的页面对象。

另一方面,当您在页面上执行某些操作时,会导致浏览器指向另一个页面——例如,单击链接或提交表单——那么该页面对象有责任返回下一页对象。

由于我对您的主页、帐户页面和结果页面之间的关系知之甚少,无法准确告诉您它在您的网站中的表现,因此我将使用在线商店应用程序作为示例。

假设您有一个 SearchPage。当您在 SearchPage 上提交表单时,它会返回一个 ResultsPage。当你点击一个结果时,你会得到一个 ProductPage。所以这些类看起来像这样(缩写为相关方法):

public class SearchPage {

    public void open() {
        return driver.get(url);
    }

    public ResultsPage search(String term) {
        // Code to enter the term into the search box goes here
        // Code to click the submit button goes here
        return new ResultsPage();
    }

}

public class ResultsPage {

    public ProductPage openResult(int resultNumber) {
        // Code to locate the relevant result link and click on it
        return new ProductPage();
    }

}

执行这个故事的测试方法看起来像这样:

@Test
public void testSearch() {

    // Here we want to simulate the user going to the search page
    // as if opening a browser and entering the URL in the address bar. 
    // So we instantiate it here in the test code.

    SearchPage searchPage = new SearchPage();
    searchPage.open(); // calls driver.get() on the correct URL

    // Now search for "video games"

    ResultsPage videoGameResultsPage = searchPage.search("video games");

    // Now open the first result

    ProductPage firstProductPage = videoGameResultsPage.openResult(0);

    // Some assertion would probably go here

}

如您所见,页面对象存在这种“链接”,其中每个对象都返回下一个对象。

结果是您最终会得到许多不同的页面对象来实例化其他页面对象。因此,如果您有一个相当大的站点,您可以考虑使用依赖注入框架来创建这些页面对象。

于 2012-04-26T02:03:46.673 回答
4

好吧,我创建了自己的代表页面的 Java 类:

说,下面是代表主页的代码。这里用户可以登录:

public class HomePage{
  private WebDriver driver;
  private WebElement loginInput;
  private WebElement passwordInput;
  private WebElement loginSubmit;

  public WebDriver getDriver(){
    return driver;
  }

  public HomePage(){
    driver = new FirefoxDriver();
   }

  public CustomerPage login(String username, String password){
     driver.get("http://the-test-page.com");
     loginInput = driver.findElement(By.id("username"));
     loginInput.sendKeys(username);
     passwordInput = driver.findElement(By.id("password"));
     passwordInput.sendKeys(password);
     loginSubmit = driver.findElement(By.id("login"));
     loginSubmit.click();
     return new CustomerPage(this);
  }


}

客户页面可能如下所示。在这里,我正在演示如何获取登录用户:

public class CustomerPage{
    private HomePage homePage;
    private WebElement loggedInUserSpan;

 public CustomerPage(HomePage hp){
    this.homePage = hp;
  }

 public String getLoggedInUser(){
      loggedInUserSpan = homePage.getDriver().findElement(By.id("usrLongName"));
      return loggedInUserSpan.getText();
 }

}

测试可以这样进行:

@Test
public void testLogin(){
  HomePage home = new HomePage();
  CustomerPage customer = home.login("janipav", "extrasecretpassword");
  Assert.assertEquals(customer.getLoggedInUser(), "Pavel Janicek");
}
于 2012-04-25T13:42:47.570 回答
2

您通常希望对用户在使用您的网站时的实际行为进行建模。当使用页面对象时,这最终会采用领域特定语言 (DSL) 的形式。但是,它会与可重用的页面组件混淆。

现在 Java 8 推出了默认方法,可重用的页面组件可以被视为使用默认方法的 mixin。我有一篇博客文章,其中包含一些在这里找到的代码示例,更详细地解释了这一点:http: //blog.jsdevel.me/2015/04/pageobjects-done-right-in-java-8.html

于 2015-04-20T07:26:05.417 回答
1

我建议您使用为这些模式提供支持的框架。Geb是最好的之一。下面是一个取自他们手册的例子

Browser.drive {
    to LoginPage
    assert at(LoginPage)
    loginForm.with {
        username = "admin"
        password = "password"
    }
    loginButton.click()
    assert at(AdminPage)
}

class LoginPage extends Page {
    static url = "http://myapp.com/login"
    static at = { heading.text() == "Please Login" }
    static content = {
        heading { $("h1") }
        loginForm { $("form.login") }
        loginButton(to: AdminPage) { loginForm.login() }
    }
}

class AdminPage extends Page {
    static at = { heading.text() == "Admin Section" }
    static content = {
        heading { $("h1") }
    }
}
于 2012-04-26T03:40:24.223 回答
1

我喜欢使用页面对象模式编写 Selenium Webdriver 测试。但个人对必须始终显式实例化并返回下一页或页面组件的冗长和重复感到恼火。因此,借助 Python 的元类,我编写了一个名为 Keteparaha 的库,它可以自动计算出应该从 selenium 页面对象的方法调用中返回的内容

于 2015-03-11T08:34:53.860 回答