- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我刚开始使用 WebDriver ,我正在尝试学习最佳实践,特别是使用 PageObjects和 PageFactory .
我的理解是PageObjects应该暴露网页上的各种操作,并将WebDriver代码与测试类隔离开来。很多时候,相同的操作可能会导致导航到不同的页面,具体取决于所使用的数据。
例如,在这个假设的登录场景中,提供管理员凭据会将您带到 AdminWelcome 页面,而提供客户凭据会将您带到 CustomerWelcome 页面。
所以最简单的实现方法是公开两个返回不同页面对象的方法...
package example;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class Login {
@FindBy(id = "username")
private WebElement username;
@FindBy(id = "password")
private WebElement password;
@FindBy(id = "submitButton")
private WebElement submitButton;
private WebDriver driver;
public Login(WebDriver driver){
this.driver = driver;
}
public AdminWelcome loginAsAdmin(String user, String pw){
username.sendKeys(user);
password.sendKeys(pw);
submitButton.click();
return PageFactory.initElements(driver, AdminWelcome.class);
}
public CustomerWelcome loginAsCustomer(String user, String pw){
username.sendKeys(user);
password.sendKeys(pw);
submitButton.click();
return PageFactory.initElements(driver, CustomerWelcome.class);
}
}
并在测试类中执行以下操作:
Login loginPage = PageFactory.initElements(driver, Login.class);
AdminWelcome adminWelcome = loginPage.loginAsAdmin("admin", "admin");
或
Login loginPage = PageFactory.initElements(driver, Login.class);
CustomerWelcome customerWelcome = loginPage.loginAsCustomer("joe", "smith");
我希望有一种更简洁的方法来公开返回相关 PageObject 的单个 login()
方法,而不是重复代码。
我考虑过创建一个页面层次结构(或让它们实现一个接口(interface)),以便我可以将其用作返回类型,但感觉很笨拙。我想出的是以下内容:
public <T> T login(String user, String pw, Class<T> expectedPage){
username.sendKeys(user);
password.sendKeys(pw);
submitButton.click();
return PageFactory.initElements(driver, expectedPage);
}
这意味着您可以在测试类中执行以下操作:
Login loginPage = PageFactory.initElements(driver, Login.class);
AdminWelcome adminWelcome =
loginPage.login("admin", "admin", AdminWelcome.class);
或
Login loginPage = PageFactory.initElements(driver, Login.class);
CustomerWelcome customerWelcome =
loginPage.login("joe", "smith", CustomerWelcome.class);
这很灵活 - 您可以添加一个 ExpiredPassword 页面,而不必更改 login()
方法 - 只需添加另一个测试并传入适当的过期凭据和 ExpiredPassword 页面作为预期的页面。
当然,您可以很容易地离开 loginAsAdmin()
和 loginAsCustomer()
方法,并用对通用 login() 的调用替换它们的内容
(然后将其设为私有(private))。一个新页面(例如 ExpiredPassword 页面)将需要另一个方法(例如 loginWithExpiredPassword()
)。
这样做的好处是方法名称实际上是有意义的(您可以很容易地看到登录有 3 种可能的结果),PageObject 的 API 更容易使用(没有“预期页面”可以传入),但 WebDriver 代码仍在被重用。
进一步改进...
如果您确实公开了单个 login()
方法,则可以通过向这些页面添加标记界面来使登录可以访问哪些页面变得更加明显(这可能不是必需的,如果你为每个场景公开一个方法)。
public interface LoginResult {}
public class AdminWelcome implements LoginResult {...}
public class CustomerWelcome implements LoginResult {...}
并将登录方法更新为:
public <T extends LoginResult> T login(String user, String pw,
Class<T> expectedPage){
username.sendKeys(user);
password.sendKeys(pw);
submitButton.click();
return PageFactory.initElements(driver, expectedPage);
}
这两种方法似乎都很有效,但我不确定它如何扩展以适应更复杂的场景。我还没有看到任何类似的代码示例,所以我想知道当页面上的操作会根据数据产生不同的结果时,其他人会怎么做?
或者只是复制 WebDriver 代码并为数据/PageObjects 的每个排列公开许多不同的方法是常见的做法吗?
最佳答案
Bohemian 的回答不灵活——你不能让一个页面操作返回到同一个页面(比如输入错误的密码),你也不能有超过 1 个页面操作导致不同的页面(想想你有多乱) d 如果登录页面有另一个导致不同结果的操作)。您最终还会堆放更多的 PageObjects 来满足不同的结果。
在进一步尝试之后(包括登录失败的情况),我确定了以下几点:
private <T> T login(String user, String pw, Class<T> expectedPage){
username.sendKeys(user);
password.sendKeys(pw);
submitButton.click();
return PageFactory.initElements(driver, expectedPage);
}
public AdminWelcome loginAsAdmin(String user, String pw){
return login(user, pw, AdminWelcome.class);
}
public CustomerWelcome loginAsCustomer(String user, String pw){
return login(user, pw, CustomerWelcome.class);
}
public Login loginWithBadCredentials(String user, String pw){
return login(user, pw, Login.class);
}
这意味着你可以重用登录逻辑,但是阻止了测试类在预期页面中传递的需要,这意味着测试类的可读性非常强:
Login login = PageFactory.initElements(driver, Login.class);
login = login.loginWithBadCredentials("bad", "credentials");
// TODO assert login failure message
CustomerWelcome customerWelcome = login.loginAsCustomer("joe", "smith");
// TODO do customer things
为每个场景使用单独的方法也使 Login
PageObject 的 API 非常清晰 - 并且很容易告诉登录的所有结果。我没有看到使用接口(interface)的任何值(value)限制使用 login()
方法的页面。
我同意 Tom Anderson 的观点,即可重用的 WebDriver 代码应该重构为细粒度的方法。它们是细粒度公开(以便测试类可以选择相关操作),还是组合并作为单个粗粒度方法公开给测试类,这可能取决于个人喜好。
关于java - 如何实现可以返回不同 PageObjects 的 WebDriver PageObject 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13371699/
我刚开始使用 WebDriver ,我正在尝试学习最佳实践,特别是使用 PageObjects和 PageFactory . 我的理解是PageObjects应该暴露网页上的各种操作,并将WebDri
所以我有一个页面对象,它处理用户所在页面的所有主要功能。我想这样做,这样当调用页面对象的实例时就会发生一些事情。在当前情况下,我有: public MyPageObject MY_SCREEN = n
所以,当出现问题时,我只是在创建一个简单的 selenium/JBehave 代码。 我会先贴出简化的代码,稍后再解释我的问题。 所以这里我们有一个简单的抽象类,它将在我的 PageObjects 上
我正在尝试为 WebDriver 中的页面对象创建某种代码生成。 我读到了它,并观看了下一个讲座: http://www.youtube.com/watch?v=mSCFsUOgPpw 我还看到一些工
如何为页面中的框架实现 pageObject 模式(Selenium)..我有一个主页,有一个左框架和右框架,我想为每个框架创建页面对象.. 例如,我有如下的 LeftFrame 页面对象: Publ
有没有办法从另一个页面对象文件访问一个页面对象文件中定义的元素? 例子:如果我们需要从 LoginPage.ts 文件访问“@usernameInput”,是否需要从 HomePage.ts 复制它?
我想从下面知道哪个是创建 PageObject 类实例的更好选择(例如:LoginPage):- 1) 在所有测试和步骤中创建一个 Pageobject 类的实例(任何需要的地方)? LoginPag
我想我已经掌握了 PageObject 模式的要点,但其中有些部分我还没有掌握。 所以我一直在学习本教程,现在我有了这个 Page 类: public class SignUpPage extends
如果一个按钮可选地显示在页面(或页面的一部分)上,它是否有资格将该部分表示为两个不同的 PageObjects,其中一个 PageObject 提供与按钮交互的方法,而另一个 PageObject 不
我有一些基本的 selenium 和 java 经验,但我正在尝试了解有关页面对象模式的更多信息,并且在完全理解如何在实际项目中使用它时遇到了一些问题。我尝试在谷歌中寻找简单但实用的项目,我可以复制并
page-object gem自动 generates multiple accessors . 例如,除了 link 之外,您还可以使用 links,例如: class MyPage inc
我正在编写一些 Selenium 测试,想知道如何导航到我的 ProfilePage,只需在我的测试中调用它的类即可所以我得到了我的 BasePage 类, class BasePage(object
我正在使用 Cheezy Page Object gem(这也意味着我正在使用 Watir,这也意味着我正在使用 Selenium)。我还明确加载了 watir gem。 无论如何,我有一个网站,我正
将 PageObjects 模式应用于页面组件时的标准方法是什么? 举个例子,假设我正在为亚马逊产品页面上的功能编写测试。 该页面包含大量单独的功能、产品信息、查看此内容的客户、推荐的其他客户等。 我
本文整理了Java中com.atlassian.webdriver.pageobjects.WebDriverTester类的一些代码示例,展示了WebDriverTester类的具体用法。这些代码示
我们的应用程序具有消耗组件的组件,这些组件消耗具有不同复杂性的组件。所以我只想要页面上的输入,以验证何时设置对象文本是否正确。问题是它是这些子组件之一。 我的同事告诉我,有两种方法可以做到这一点,第一
我对 Selenium 非常陌生,我开始自动化登录过程。我为此目的使用了 PageObjects。我有一个 LoginPage ,它有一个这样的方法: public MyHomePage login(
我正在尝试使用 WebdriverIO Docs 中定义的语法定义一个 PageObject : 父页面 //page.js export default class Page { constru
我试图找到这个问题的答案,但没有一个对我有帮助。我确定我遗漏了一个细节,但我无法弄清楚到底是什么。 运行测试用例时出现NullPointerException。我认为当我尝试将驱动程序传递给我的页面对
我正在使用 PageObjects 在 Selenium Webdriver 中制作一个测试套件,但我怀疑即使驱动程序指向不同的框架,WebElement 引用的实例是否也可以工作?我正在为其编写测试
我是一名优秀的程序员,十分优秀!