页面工厂模型(Selenium Page Factory Pattern)就像一个扩展的页面对象模型 (PageObject Model),但页面工厂模型(Page Factory Pattern)是一个更强大的模型。开始前先,我们需要导入包“org.openqa.selenium.support.PageFactory”
工厂类(Factory class)使 页面对象模型 (PageObject Model)使用起来更简单,更容易
我们使用 页面工厂模式(Page Factory pattern ) 初始化页面对象模型 (PageObject Model)中使用的web页面元素。
如下所示,我们应该使用PageFactory类的initElements()方法初始化对象,一旦我们调用了initElements()方法,所有元素将被初始化。PageFactory.initElements()静态方法的入参为driver实例和class名称。 返回页面对象定义的所有定义元素。
Home homePage = new HomePage(driver);
PageFactory.initElements(driver, homePage);
或者,
// To initialize elements.
HomePage homePage =PageFactory.initElements(driver, HomePage.class);
或者, 作为页面类的构造函数如下:
publicHompePage(WebDriver driver){
this.driver = driver;
PageFactory.initElements(driver, this);
}
Page Factory将初始化每个WebElement变量引用相应的实际web页面上的元素定义基于“定位器”。这是通过使用 @FindBy注解 。
Page Factory,注解是用来给WebElements描述性的名字来提高代码的可读性。和注释 @FindBy 用于识别Web页面中的元素。
默认情况下,PageFactory将搜索与页面元素属性ID匹配的元素,如果失败,那么它将搜索的名称属性。但是我们需要更多的控制识别HTML页面中的元素并将它们映射为我们的页面对象字段。一种方法是使用@FindBy注释,如以下代码所示:
@FindBy 注解支出如下所有的元素定位策略:
id, name, className, css, xpath, tagName, linkText andpartialLinkText
我们可以使用这个注释通过指定“how”和“using”或通过指定的任何一个位置策略(如:“id”)
@FindBy(how = How.ID, using = "username")
private WebElement userName;
我们可以重写上面一个如下:
@FindBy(id="username")
private WebElement userName;
使用类名称,我们将定义如下:
@FindBy(className=".input.username")
private WebElement userName;
当我们有多个元素(WebElements列表),我们可以使用PageFactory初始化它们如下:
@FindBy(tagName = "mylist")
private List<WebElement> links;
当页面元素被方法调用时,driver首先在当前页面查找到当前元素并模拟元素操作。在某些情况下,大多数的用例执行都依赖基础页面元素。我么可能需要多次调用同页面的相同元素。
有这种情况下, 我们可以使用page factory的另外一个注解 “@CacheLookup”
@FindBy(name="username")
@CacheLookup
private WebElement userName;
@CacheLookup注解是什么?
注解@CacheLookup 表明元素永远不会改变(即,同一个实例在 POM中将一直被使用)
AjaxElementLocatorFactory注解:
AjaxElementLocatorFactory 是一个延迟加载的概念
例子:
/***
* Constructor
* @param driver an instance ofWebDriver
*/
public int TimeoutValue = 30;
publicSearchResultsPage(Webdriver driver) {
PageFactory.initElements(newAjaxElementLocatorFactory(driver, TimeoutValue), this);
}
上面的代码将等待最多30秒,直到加载到指定的注释元素。如果元素在给定的时间间隔内没有发现,它将抛出NoSuchElementException”异常。
结论:
事实上,我们可以只使用POM不使用Page Factory。POM从物理结构简单抽象业务逻辑。Page Factory给我们能够使用注释自动找到页面上的元素没有指定findElement。
下面是示例代码页在Selenium对象模型:
public class BasePage {
private By username = By.id("username");
private By password = By.id("password");
private By loginBtn = By.name("loginbtn");
public void userLogin(String userName, String password) {
driver.findElement(username).sendKeys("testuser");
driver.findElement(password).sendKeys("testpassword");
driver.findElement(loginBtn).click();
}
}
下面是简单的代码编写使用页面在selenium工厂:
public classBasePage {
@FindBy(id="username") private WebElement userName;
@FindBy(id="password") private WebElement password;
@FindBy(id="login") private WebElement loginBtn;
public void userLogin(String userName, String password) {
userName.sendKeys(userName);
password.sendKeys(password);
loginBtn.click();
}
}