到这节课为止我们已经基本上把WebDriver和TestNG的基础都讲完了,下去开始讲讲实战过程中我们会用到的一些思想和工具。

例如这节我们要讲的PageObject思想。相信如果现在你们的脚本已经经过几个迭代的修改了,你们一定会遇到一个头痛的问题,那就是页面变化,以前脚本的定位方式不能用了,得修改定位方式,那如果以往的脚本没有用PageObject思想,意味着你得一个一个Case中把需要修改的定位方式找出来,然后再进行修改。这不但照成脚本维护的成本加大,也可能照成大量代码冗余。

那这时候PageObject就显得尤为重要。 那什么是PageObject呢?

什么是PageObject思想

PageObject 见名思意,就是页面对象。说白就是把页面元素定位和页面元素操作分开。
PageObject在实战过程中我们回对脚本实现进行分层。通常做法是分三层:

  1. 对象库层
  2. 逻辑层
  3. 业务层

对象层用于存放我们的页面元素和一些特殊控件操作。逻辑层则是一些封装好的功能用例模块。业务层则是我们真正的测试用例的操作。

当然如果我们的测试数据量大时,我们还可以在三层基础上再加一层 数据层,用于存放我们的测试数据,这也是比较常规的做法。

  1. 对象库层
  2. 逻辑层
  3. 业务层
  4. 数据层

实战例子

废话不多说我们直接来看个例子,我们还是以163邮箱登录为例子。

对象库层

首先我们新建个叫LoginPage的类,编写登录页面所有可能需要操作的元素定位方式和操作,代码示例如下:

  1. package com.selenium.pageobjcet;
  2. import org.openqa.selenium.By;
  3. import org.openqa.selenium.WebDriver;
  4. /**
  5. * Created by 米阳 on 14/10/2017.
  6. */
  7. public class LoginPage {
  8. // 定位 ifrmae
  9. public static By loginFrame = By.id("x-URS-iframe");
  10. // 定位 邮箱地址输入框
  11. public static By emailField = By.name("email");
  12. // 定位 密码输入框
  13. public static By pwdFiled = By.name("password");
  14. // 定位 登录按钮
  15. public static By loginBtn = By.id("dologin");
  16. WebDriver driver;
  17. public LoginPage(WebDriver driver) {
  18. this.driver = driver;
  19. }
  20. /**
  21. * 往邮箱文本框输入邮箱
  22. * @param email 邮箱地址
  23. */
  24. public void sendKeysEmail(String email) {
  25. driver.findElement(emailField).clear();
  26. driver.findElement(emailField).sendKeys(email);
  27. }
  28. /**
  29. * 往密码文本框输入密码
  30. * @param pwd 密码
  31. */
  32. public void sendKeysPWD(String pwd) {
  33. driver.findElement(pwdFiled).clear();
  34. driver.findElement(pwdFiled).sendKeys(pwd);
  35. }
  36. }

这里我们只把邮件输入框和密码输入框的操作进行封装,当然如果为了便于阅读也可以把所有的元素操作进行封装取名。


操作层

我们再新建个叫LoginMail的类,用于登录逻辑封装,供业务层Case调用,实现如下:

  1. package com.selenium.pageobjcet;
  2. import org.openqa.selenium.WebDriver;
  3. import org.openqa.selenium.WebElement;
  4. /**
  5. * Created by 米阳 on 14/10/2017.
  6. */
  7. public class LoginMail {
  8. WebDriver driver;
  9. public LoginMail(WebDriver driver) {
  10. this.driver = driver;
  11. }
  12. /**
  13. * 登陆
  14. *
  15. * @param emial 邮箱地址
  16. * @param pwd 密码
  17. */
  18. public void login(String emial, String pwd) {
  19. LoginPage loginPage = new LoginPage(driver);
  20. WebElement element = driver.findElement(LoginPage.loginFrame);
  21. driver.switchTo().frame(element);
  22. loginPage.sendKeysEmail(emial);
  23. loginPage.sendKeysPWD(pwd);
  24. driver.findElement(LoginPage.loginBtn).click();
  25. }
  26. }

业务层

最后我们来看下业务层的封装,也就是我们真正Case的编写:

  1. package com.selenium.pageobjcet;
  2. import org.openqa.selenium.WebDriver;
  3. import org.openqa.selenium.WebElement;
  4. import org.openqa.selenium.chrome.ChromeDriver;
  5. import org.testng.annotations.AfterClass;
  6. import org.testng.annotations.BeforeClass;
  7. import org.testng.annotations.Test;
  8. import java.util.concurrent.TimeUnit;
  9. /**
  10. * Created by 米阳 on 14/10/2017.
  11. */
  12. public class LoginTest {
  13. WebDriver driver;
  14. @BeforeClass
  15. public void openChrome() {
  16. System.setProperty("webdriver.chrome.driver", "./drivers/chromedriver.exe");
  17. driver = new ChromeDriver();
  18. driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
  19. }
  20. @Test
  21. public void testLogin2() {
  22. driver.get("http://mail.163.com/");
  23. LoginMail loginMail = new LoginMail(driver);
  24. loginMail.login("meyoungtester", "meyoung123");
  25. }
  26. @AfterClass
  27. public void closedChrome() {
  28. driver.quit();
  29. }
  30. }

小结

经过我们对登陆功能的改装,采用了PageObject思想后,假设以后要是登录页面的A元素变更,我们就不需要在工程里面到处找用到这个A元素的Case去修改他们的定位方式,我们只需要打开我们的LoginPage,找到A元素的定位方式,进行修改,则整个工程用到A元素定位的就自然而然的修改了。同样如果哪天登录流程变更了,例如登录过程必须输入验证码,那么我们也不需要把所有Case涉及到登录的都找出来,插入输入验证码过程,只需要在先在LoginPage里面登陆验证码的定位方式,接着加入打开LoginMail,在登录逻辑里面加入我们的验证码输入步骤,则用到登录逻辑的所有Case则不需要其他维护。


PageObject 的优点

一张图差不多对PO思想引入的前后对比。PO思想对界面交互细节进行了封装,这样可以使我们的自动化测试脚本案例更关注业务,而非界面细节,提高了测试案例的可读性。

14-Web-自动化测试----PageObject-思想 - 图1

PageFactory

PageFactory 整体思想同于PageObject思想,只是表象显示上不太一样,它通过注解的方式来定位元素对象,例如:

对象库层:

  1. @FindBy(id = "kw")
  2. public static WebElement emailName;

Case使用:

  1. @Test
  2. public void test(){
  3. driver.get("https://www.baidu.com");
  4. // 初始化 LoginPage
  5. PageFactory.initElements(driver ,LoginPage.class);
  6. LoginPage.emailName.sendKeys("Test");
  7. }

PageObject VS PageFactor

WebDriver 提供了这两种元素对象管理的思想,总的来说没有谁好谁坏,看个人习惯,实际工程也可以两者结合使用。就个人而言更习惯PageObject思想,但PageFactor也不错,通过注解方式代码看起来更加简洁。