前言

上一小节我们已经学习了Page Object设计模式,优势很明显,能更好的体现java的面向对象思想和封装特性。但同时也存在一些不足之处,那就是随着这种模式使用,随着元素定位获取,元素定位与页面操作方法都在一个类里维护,会造成代码冗余度过高。

相信使用过spring的同学肯定都知道,基于注解方式的开发,会大大提高开发效率,使代码块变得相对整洁,清晰。

本小节要介绍的就是PageFactory 设计模式,同Page Object思想大体差不多,只是表现形式不太一样,只是通过注解方式来定位元素对象。

一、@FindBy和@CacheLookup用法

元素声明的写法:

    //定位 密码输入框
@FindBy(name = "loginpassword")
@CacheLookup
private WebElement passWord;

注解说明:

@FindBy:这个注解的意思是说我们所查找的元素是以什么方式定位,

@CacheLookup:这个注解的意思是说找到元素之后将缓存元素,重复的使用这些元素,将会大大加快测试的速度。

WebElement passWord:就是变量名

二、PageFactory类使用

PageFactory提供的是静态方法,可以直接调用,一般在用完@FindBy后,需要进行元素初始化,则需要调用initElements(driver, this);方法。

三、使用 PageFactory 模式来分离页面元素

此处演示还沿用page object模式的风格,这里我又加了一层自己暂时定义叫基础层,现在就变成了四层:

  • 基础层:用来存放driver及初始化使用。
  • 对象层:用于存放页面元素定位和控件操作。
  • 操作层:则是一些封装好的功能用例模块。
  • 业务层:则是我们真正的测试用例的操作部分。

下面将举例说明Page Object设计模式,我们还有360影视页面为例,来做进一步讲解。

1、基础层

先创建一个包,名为com.pagefactory.demo,接着在这个包下创建一个类名为HomePage,具体示例代码如下:

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.PageFactory; /**
* @author rongrong
* 基础页面
*/
public class HomePage { private static WebDriver driver; /***
* 用来传递WebDriver
* @return
*/
public static WebDriver driver() {
return driver;
} public HomePage() {
//设置系统变量,并设置chromedriver的路径为系统属性值
System.setProperty("webdriver.chrome.driver", "tool/chromedriver.exe");
//实例ChromeDriver
driver = new ChromeDriver();
PageFactory.initElements(driver, this);
} /**
* 打开浏览器
*/
public void open() {
driver.get("https://i.360kan.com/login");
} /**
* 关闭浏览器
*/
public void close() {
driver.quit();
} public LoginPage loginPage() {
LoginPage loginPage = new LoginPage();
return loginPage;
} }

这是我的基础页面,为了让driver抽离出去

2、对象层

接着我们再来创建一个类,名为LoginPage,具体示例代码如下:

import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.CacheLookup;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;
import org.openqa.selenium.support.PageFactory; /**
* @author rongrong
* 对象库层代码案例
*/
public class LoginPage { public LoginPage(){
PageFactory.initElements(HomePage.driver(),this);
} //定位 用户名输入框
@FindBy(how = How.NAME, using = "loginname")//第一种写法
@CacheLookup
private WebElement userName; //定位 密码输入框
@FindBy(name = "loginpassword")//第二种写法
@CacheLookup
private WebElement passWord; //定位 登录按钮
@FindBy(linkText = "立即登录")
@CacheLookup
private WebElement loginBtn; //定位 提示错误信息
@FindBy(css = "[class='b-signin-error js-b-signin-error error-2']")
@CacheLookup
private WebElement errorMsg; public WebElement getUserName() {
return userName;
} public WebElement getPassWord() {
return passWord;
} public WebElement getLoginBtn() {
return loginBtn;
} public WebElement getErrorMsg() {
return errorMsg;
} /**
* 用户名输入操作
*
* @param userName
*/
public void sendKeysUserName(String userName) {
getUserName().clear();
getUserName().sendKeys(userName);
} /**
* 密码输入操作
*
* @param passWord
*/
public void sendKeysPassWord(String passWord) {
getPassWord().clear();
getPassWord().sendKeys(passWord);
}
}

3、操作层

接着我们再来创建一个类,名为LoginMovies,用来记录登录的一系列操作,具体示例代码如下:

package com.demo;

import org.testng.Assert;

/**
* @author rongrong
* 操作层代码案例
*/
public class LoginMovies { /***
* 登录过程
* @param userName
* @param pwd
* @param expected
*/
public void loginByPageFactory(String userName, String pwd, String expected) {
HomePage homePage = new HomePage();
//打开登录页
homePage.open();
//输入用户名
homePage.loginPage().sendKeysUserName(userName);
//输入密码
homePage.loginPage().sendKeysPassWord(pwd);
//点击登录
homePage.loginPage().getLoginBtn().click();
//获取提示语操作
String msg = homePage.loginPage().getErrorMsg().getText();
//验证输入手机号错误是否提示
Assert.assertEquals(msg, expected);
//关闭浏览器
homePage.close();
}
}

4、业务层

最后我们再来创建一个类,名为TestPageFactory,用来验证登录功能,具体示例代码如下:

import org.testng.annotations.Test;

/**
* @author rongrong
* 业务层代码案例
*/
public class TestPageFactory { /**
* 测试登录
*/
@Test
public void textLogin() {
//实例化操作对象
LoginMovies loginMovies = new LoginMovies();
//登录操作
loginMovies.loginByPageFactory("your userName", "your passWord", "输入手机号不合法");
} }

从以上代码看,如果页面元素发生变化,我们在对应类里修改对应元素即可,而操作和业务层流程类及用例都不用改,如果仅是业务流程更改,只需要维护业务层流程类业务脚本,其他几个类都不用改,从而做到了很好的将页面、元素、脚本进行了分离。

关于PageObject & PageFactory的使用,这里仅为读者提供了思路,有兴趣的同学可以继续拓展,笔者能力有限,如果觉得文章好,还请添加关注我哦

最新文章

  1. (转) Deep Learning Research Review Week 2: Reinforcement Learning
  2. 百度地图api 常用demo
  3. 【BZOJ】1856: [Scoi2010]字符串
  4. QT中QWS的含义 (转至 宋金时的专栏
  5. android:scaleType属性
  6. POJ 1032问题描述
  7. MVC4下拉少数名族
  8. CodeBlocks+opencv2.4.4+cmake+MinGW
  9. ISO14443标准详细介绍
  10. nginx 使用过程中一些基础性问题总结
  11. RAMDISK 内存盘工具推荐
  12. linux 安装 SVN server
  13. Linux top、VIRT、RES、SHR、SWAP(S)、DATA Memory Parameters Detailed
  14. 关于利用PHP访问MySql数据库的逻辑操作以及增删改查实例操作
  15. Go语言二叉树定义及遍历算法实现
  16. Android学习路-UI控件
  17. np.hsplit()
  18. [开源,学习,分享]UWP第三方简书客户端分享
  19. mysql 下数据库升级脚本的编写
  20. 【Leetcode】【Medium】Gray Code

热门文章

  1. 个人永久性免费-Excel催化剂功能第53波-无比期待的合并工作薄功能
  2. C#7.2 新增功能
  3. EF Core懒人小技巧之拒绝DbSet
  4. 开源项目托管到GitHub上
  5. 深入学习OpenCV检测及分割图像的目标区域
  6. handlerAdapter与方法返回值的处理
  7. tp3 的前端内置标签
  8. Java连接MySQL8.0以上版本数据库方式
  9. DDMS 视图 Emulator Control 为灰色
  10. 微信支付java开发