我刚刚开始使用
WebDriver,我正在尝试学习最佳做法,特别是使用
PageObjects和
PageFactory.
我的理解是,PageObjects应该在网页上公开各种操作,并将WebDriver代码与测试类隔离开来.通常,相同的操作可以导致根据所使用的数据导航到不同的页面.
例如,在这个假设的登录方案中,提供管理员凭据会将您带到AdminWelcome页面,并提供“客户”凭据将您带到“CustomerWelcome”页面.
所以实现这个最简单的方法是公开两种返回不同的PageObjects的方法
登录PageObject
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()方法.
我想到创建一个层次结构的页面(或者让它们实现一个接口),以便我可以使用它作为返回类型,但是感觉很笨拙.我想到了如下:
public T login(String user, String pw, Class 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()方法,并将其内容替换为通用登录名()的调用(将被隐藏).然后,新页面(例如ExpiredPassword页面)将需要另一种方法(例如loginWithExpiredPassword()).
这有利于方法名称实际上意味着什么(你可以很容易地看到有3个可能的登录结果),PageObject的API更容易使用(没有“期望的页面”传入),但是WebDriver代码仍在重复使用.
进一步改进…
如果您公开了单一登录()方法,则可以通过向这些页面添加标记界面来更明显地登录哪些页面(如果您为每个场景公开一个方法,这可能不是必需的).
public interface LoginResult {}
public class AdminWelcome implements LoginResult {...}
public class CustomerWelcome implements LoginResult {...}
并将登录方法更新为:
public T login(String user, String pw,
Class expectedPage){
username.sendKeys(user);
password.sendKeys(pw);
submitButton.click();
return PageFactory.initElements(driver, expectedPage);
}
任何一种方法似乎都能很好地工作,但我不知道如何扩展更复杂的场景.我没有看到任何代码示例,所以我想知道别人做什么,当一个页面上的操作可以导致不同的结果取决于数据?
或者通常的做法是复制WebDriver代码,并为数据/ PageObjects的每个排列公开大量不同的方法?