前言

上一小节我们已经学习了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的使用,这里仅为读者提供了思路,有兴趣的同学可以继续拓展,笔者能力有限,如果觉得文章好,还请添加关注我哦

Selenium+java - PageFactory设计模式的更多相关文章

  1. 浅析selenium的PageFactory模式 PageFactory初始化pageobject

    1.首先介绍FindBy类: For example, these two annotations point to the same element: @FindBy(id = "foob ...

  2. 浅析selenium的PageFactory模式

    前面的文章介绍了selenium的PO模式,见文章:http://www.cnblogs.com/qiaoyeye/p/5220827.html.下面介绍一下PageFactory模式. 1.首先介绍 ...

  3. 记我的第二次自动化尝试——selenium+pageobject+pagefactory实现自动化下单、退款、撤销回归测试

    需求: 系统需要做下单.退款.撤销的回归测试,有下单页面,所以就想到用selenium做WEB UI 自动化 项目目录结构: common包上放通用的工具类方法和浏览器操作方法 pageobject包 ...

  4. maven+selenium+java+testng+jenkins自动化测试

    最近在公司搭建了一套基于maven+selenium+java+testng+jenkins的自动化测试框架,免得以后重写记录下 工程目录 pom.xml <project xmlns=&quo ...

  5. Selenium+java - 手把手一起搭建一个最简单自动化测试框架

    写在前面 我们刚开始做自动化测试,可能写的代码都是基于原生写的代码,看起来特别不美观,而且感觉特别生硬. 来看下面一段代码,如下图所示: 从上面图片代码来看,具体特征如下: driver对象在测试类中 ...

  6. selenium第一课(selenium+java+testNG+maven)

    selenium介绍和环境搭建 一.简单介绍 1.selenium:Selenium是一个用于Web应用程序测试的工具.Selenium测试直接运行在浏览器中,就像真正的用户在操作一样.支持的浏览器包 ...

  7. 基于java的设计模式入门(1)——为什么要学习设计模式

    大年初一,楼主在这里给大家拜年,祝大家码上升职加薪,码上有对象结婚,码上有车有房,幸福安康. 过完年,回学校注册报道之后,大概就要回深圳到公司开始实习了.提高自己,无非就有两种方式,一是看书学习,二是 ...

  8. Selenium+Java+TestNG环境配置

    1. JDK 2.eclipse+TestNG >TestNG安装.   Name:testng  Location:http://beust.com/eclipse.如图: 3.seleniu ...

  9. Java 反射 设计模式 动态代理机制详解 [ 转载 ]

    Java 反射 设计模式 动态代理机制详解 [ 转载 ] @author 亦山 原文链接:http://blog.csdn.net/luanlouis/article/details/24589193 ...

随机推荐

  1. css的优先级 和 权重问题 以及 !important 优先级

    css的优先级 和 权重问题 以及 !important 优先级 css选择有多少种? 行内样式(style="") id选择器(#) class选择器(类,伪类) 元素选择器(标 ...

  2. 洛谷 P1463、POI2002、HAOI2007 反素数

    题意: 求最小的$x\in[1,N]$,使得$x$为$g(x)$最大的数 中最小的一个. 分析: 1.$x$不会有超过$10$个不同质因子.理由:$2 \times 3\times 5...\time ...

  3. 理解 Spring 定时任务的 fixedRate 和 fixedDelay 的区别

    用过 Spring 的 @EnableScheduling 的都知道,有三种方式,即 @Scheduled 注解的 fixedRate(fixedRateString), fixedDelay(fix ...

  4. 个人永久性免费-Excel催化剂功能第83波-遍历文件夹内文件信息特别是图像、音视频等特有信息

    在过往的功能中,有体现出在Excel上管理文件的极大优势,在文件的信息元数据中,有图片和音视频这两类特有的属性数据,此篇对过往功能的一个补充,特别增加了图片和音视频信息的遍历功能. 使用场景 在文件管 ...

  5. join,列表和字典用for循环的删除,集合,深浅拷贝

    1.join() 将列表转换成字符串,并且每个字符之间用另一个字符连接起来,join后面必须是可迭代的对象(字符串,列表,元组,字典,集合),数字不能迭代 例如: s = ['a','b','c'] ...

  6. 《VR入门系列教程》之7---DK2和Crescent Bay

    The DK2     于2014年春,Oculus发布了第二代开发版头显设备,代号为DK2.与DK1相比,Oculus Rift DK2的外观有很大改进,并且轻了许多,体积仍然比较大,可以罩住大部分 ...

  7. linux初学者-Apache篇

     linux初学者-Apache篇          Apache提供了超文本传输协议http,httpd是Apache超文本传输协议的主服务器.下文将对httpd的安装和配置进行简单的叙述.     ...

  8. Spring MVC中的 权限拦截定义 以及 权限拦截的研发步骤

    权限拦截 (拦截器: 对请求进行区分) 1 实现的价值(作用) 用户未登录:访问没用登录的URL,拦截到以后 跳转回登录 用户未登录:访问登录的URL,直接放行到后续流程处理框架,进行后续的操作 用户 ...

  9. rem的基准字体大小的设置

    1.移动端 UI 给的设计稿通常是640px.720px.750px的宽度,但是我们要做适配,兼容不同的终端,rem布局是比较常用的一种方式,比较关键的是确定根节点的字体大小. 这里以640px为例, ...

  10. 从“n!末尾有多少个0”谈起

    在学习循环控制结构的时候,我们经常会看到这样一道例题或习题.问n!末尾有多少个0?POJ 1401就是这样的一道题. [例1]Factorial (POJ 1401). Description The ...