Selenium webdriver SeleniumWebDriver页面对象

Selenium webdriver SeleniumWebDriver页面对象,selenium-webdriver,webdriver,pageobjects,Selenium Webdriver,Webdriver,Pageobjects,关于SeleniumWebDriver中页面对象的快速问题。我们的站点非常动态,有很多ajax和各种身份验证状态。很难弄清楚如何定义每个页面对象,但假设我已经弄清楚并定义了几个代表我们站点的页面对象 如何处理从一页到另一页的交叉。因此,我为我的主页获取一个页面对象,一个用于我的帐户页面,一个用于我的结果页面。然后,我需要编写一个测试,该测试遍历我的所有页面,以模拟执行多个操作的用户 你怎么说给我一个主页对象来创建一个新的使用->然后得到一个帐户页面对象去执行一些用户操作-然后得到一个结果页面对象

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

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

你怎么说给我一个主页对象来创建一个新的使用->然后得到一个帐户页面对象去执行一些用户操作-然后得到一个结果页面对象来验证这些操作都来自一个脚本

人们是如何做到这一点的


谢谢

好吧,我创建了自己的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");
}

当您模拟让用户在浏览器的URL栏中输入一个新URL时,测试类负责创建所需的页面对象

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

由于我对你的主页、帐户页和结果页之间的关系了解不够,无法准确地告诉你它在你的网站中的表现,因此我将使用在线商店应用程序作为示例

假设你有一个搜索页面。当您在SearchPage上提交表单时,它将返回一个ResultsPage。当你点击一个结果时,你会得到一个ProductPage。因此这些类看起来像这样(简称为相关方法):

公共类搜索页面{
公开作废{
返回驱动程序.get(url);
}
公共结果页面搜索(字符串术语){
//在搜索框中输入术语的代码如下
//单击提交按钮的代码显示在此处
返回新结果页();
}
}
公共类结果页{
public ProductPage openResult(int resultNumber){
//编码以定位相关的结果链接并单击它
返回新的ProductPage();
}
}
执行此故事的测试方法如下所示:

@Test
public void testLogin(){
  HomePage home = new HomePage();
  CustomerPage customer = home.login("janipav", "extrasecretpassword");
  Assert.assertEquals(customer.getLoggedInUser(), "Pavel Janicek");
}
@测试
公共void testSearch(){
//这里我们要模拟用户进入搜索页面
//就像打开浏览器并在地址栏中输入URL一样。
//所以我们在测试代码中实例化它。
SearchPage SearchPage=新建SearchPage();
searchPage.open();//在正确的URL上调用driver.get()
//现在搜索“视频游戏”
ResultsPage视频游戏ResultsPage=searchPage.search(“视频游戏”);
//现在打开第一个结果
ProductPage firstProductPage=videoGameResultsPage.openResult(0);
//这里可能会有一些断言
}
如您所见,页面对象之间存在“链接”,每个页面对象都返回下一个页面对象


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

< P>我建议你使用一个框架来支持这些模式。是最好的之一。下面是他们手册中的一个例子

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") }
    }
}

我喜欢使用页面对象模式编写SeleniumWebDriver测试。但是,我个人对必须始终显式实例化并返回下一个页面或页面组件的冗长和重复感到恼火。因此,得益于Python的元类,我编写了一个。

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


既然Java8已经不再使用默认方法,那么可以使用默认方法将可重用页面组件视为mixin。我在一篇博客文章中找到了一些代码示例,这些示例更详细地解释了这一点:

你所说的“页面对象”到底是什么意思?这就是我认为我需要做的。这看起来有点笨拙,因为我们的站点非常ajaxy,站点上的操作会根据用户当前的状态返回到不同的位置。此代码的问题是每个页面都需要调用PageFactory.initObjects(),并且驱动程序实例无法初始化两个不同页面上的所有对象(假设它们是两个不同的窗口或一个嵌入式框架)。因此,虽然我同意这是一种非常好的设计模式,但这种模式很快就会分解为仅适用于某些应用程序。WebDriver PageFactory的设计方式是,最好打开一个页面对象,使用它,将其标记为垃圾收集,然后实例化下一个页面,使用它,等等。也许您可以扩展PageFactory、 也许是一个解决办法。