Page Object实例(二) 配合PageFactory使用

之前介绍了Page Object的概念及基本使用(这里), 虽然实现了页与页的分离, 测试与页的分离, 但有些时候可能只是改个别元素的id什么的, 不需要改动更多, PageFactory(Selenium wiki)就是Selenium用来帮助更简单高效实现Page Object的一个工具类. 

本文结合上篇给出使用了PageFactory和没使用的区别:

PageFactory: LoginPage.java:

 1 import org.openqa.selenium.WebDriver;
 2 import org.openqa.selenium.WebElement;
 3 import org.openqa.selenium.support.CacheLookup;
 4 import org.openqa.selenium.support.FindBy;
 5 //需要导入PageFactory包
 6 import org.openqa.selenium.support.PageFactory;
 7 import java.util.List;
 8 import java.util.concurrent.TimeUnit;
 9 
10 public class LoginPage {
11     WebDriver driver;
12 
13     //关于元素的查找全部放page最前面, 后期如有UI修改很方便
14     //@FindBy 是有一个特性是使用的时候才会调用实际上的findElement
15     //如果确定此元素在当前页面不再改变, 可以加上@CacheLookup, 第一次找过此元素后不会再次查找
16     @FindBy(id = "lbNormal")
17     @CacheLookup
18     private WebElement accoutLogin;
19     @FindBy(tagName = "iframe")
20     private List<WebElement> iframes;
21     @FindBy(name = "email")
22     private WebElement loginEmail;
23     @FindBy(name = "password")
24     private WebElement loginPassword;
25     @FindBy(id = "dologin")
26     private WebElement loginButton;
27 
28     public LoginPage(WebDriver driver) {
29         this.driver = driver;
30     }
31 
32     public HomePage login(String user, String pwd) {
33         driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
34         accoutLogin.click();
35         String id = iframes.get(0).getAttribute("id");
36         if (id != null) {
37             driver.switchTo().frame(id);
38         }
39         loginEmail.sendKeys(user);
40         loginPassword.sendKeys(pwd);
41         loginButton.click();
42         driver.switchTo().defaultContent();
43         driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
44 
45         //使用PageFactory传递driver实例初始化@FindBy的元素并实例化下一个被跳转的页面
46         HomePage homePage = new HomePage();
47         PageFactory.initElements(driver, homePage);
48         return homePage;
49     }
50 }

PageFactory: LoginTest.java

 1 import org.openqa.selenium.WebDriver;
 2 import org.openqa.selenium.support.PageFactory;
 3 import org.testng.Assert;
 4 import simple.com.faye.selenium.pages.HomePage;
 5 import simple.com.faye.selenium.pages.LoginPage;
 6 import simple.com.faye.selenium.utils.SeleniumInit;
 7 
 8 public class LoginTest {
 9     public static void main(String[] args) {
10         SeleniumInit seleniumInit = new SeleniumInit();
11         WebDriver driver = seleniumInit.getFFDriver();
12         String URL = "https://mail.163.com/";
13         String user = "邮箱";
14         String pwd = "密码";
15         try {
16             driver.get(URL);
17             LoginPage loginPage = new LoginPage(driver);
18             //注意要初始化LoginPage页面(HomePage不需要是因为login方法已经初始化了)
19             PageFactory.initElements(driver, loginPage);
20             HomePage homePage = loginPage.login(user, pwd);
21             Assert.assertTrue(homePage.idExists(), "login failed");
22         } catch (Exception e) {
23             e.printStackTrace();
24         } finally {
25             driver.quit();
26         }
27     }
28 }

 LoginPage.java对比:

 1 class LoginPagePageObejectOnly {
 2     WebDriver driver;
 3 
 4     public HomePage loginOperation(String user, String pwd) {
 5         // 进入frame略, 没PageFactory若有改动需得进入所有使用此元素的方法修改
 6         WebElement loginEmail = driver.findElement(By.name("email"));
 7         loginEmail.sendKeys(user);
 8 
 9         //直接返回到新页面,不需要调用PageFactory.initElements, 但要传driver实例
10         return new HomePage(driver);
11     }
12 }
13 
14 class LoginPageWithPageFactory {
15     WebDriver driver;
16     //若有改动仅需改动此一处则其他所有使用此元素的方法都无需修改
17     //若加上@CacheLookup, 第一次找过此元素后不会再次查找
18     @FindBy(name = "email")
19     private WebElement loginEmail;
20 
21     public HomePage loginOperation(String user, String pwd) {
22         // 进入frame略, 使用时去调用findElement
23         loginEmail.sendKeys(user);
24 
25         //使用PageFactory传递driver实例初始化@FindBy的元素并实例化下一个被跳转的页面
26         HomePage homePage = new HomePage();
27         PageFactory.initElements(driver, homePage);
28         return homePage;
29     }
30 }

 以上代码可以看到使用区别以及使用方法, PageFactory还有@FindBys用以查找List<WebElement>, 以及类似以下方式的使用, 不过个人不推荐, 原因是此种方法仅适用于find by id 和 name, 且元素变量名需和页面元素的查找值一样, 还是一改全得改, 不划算:

 1 public class HomePage {
 2     //先把元素id 或 name定义上
 3     private WebElement spnUid;
 4 
 5     public boolean idExists() {
 6         //使用时先执行 driver.findElement(By.id("spnUid"))找元素,
 7         //若没有则执行 driver.findElement(By.name("spnUid"))找元素
 8         //再没有则会抛 NoSuchElementException, 相较@FindBy可以使用findByElement的所有常用方式来说不够用
 9         System.out.println(spnUid.getText());
10         return spnUid.isDisplayed();
11     }
12 }
原文地址:https://www.cnblogs.com/fayez/p/11725051.html