前言

上一小节我们已经学习了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. 【较复杂bfs】洪水-C++

    描述 魔法森林的地图是R行C列的矩形.能通行的空地表示为'.',C君倾倒洪水的地点标记为'*',无法通行的巨石阵标记为'X',海狸的巢穴标记为'D',而画家和三只小刺猬的初始位置标记为'S'. 每一分 ...

  2. 字符串的排列(剑指offer)

    题目描述: 输入一个字符串,按字典序打印出该字符串中字符的所有排列.例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba. 思路: 利用 ...

  3. springboot3(目录结构)

    2.springboot中的目录结构 1.基本信息 - static :保存所有的静态资源,css.js.img - templates :保存所有的模版页面(springboot内嵌tomcat,默 ...

  4. InstantiationException:mybatis.spring.transaction.SpringManagedTransactionFactory

    问题表现 Error creating bean with name 'sqlSessionFactory' Invocation of init method failed; nested exce ...

  5. 手把手教你破解文件密码、wifi密码、网页密码

    手把手教你破解文件密码.wifi密码.网页密码 1.破解文件密码: 有时候我们在网上下载一个压缩包后,必须要关注或者支付一定费用才给你解压密码,实属比较恶心.在这里手把手叫你实现破解文件解压密码. 1 ...

  6. python带有GIL解释器锁

    1.GIL是什么?GIL的全称是Global Interpreter Lock(全局解释器锁),来源是python设计之初的考虑,为了数据安全所做的决定. 2.每个CPU在同一时间只能执行一个线程(在 ...

  7. 配置 IDEA 远程连接应用服务器

    当调试 Web 应用时,经常需要使用 ide 远程连接,来进行 debug 调试.使用 Springboot 内置服务器和使用 Tomcat 服务器是常见的应用部署方式,可以用不同的配置方式来启动远程 ...

  8. 牛客第三场 J LRU management

    起初看到这道题的时候,草草就放过去了,开了另一道题,结果开题不顺利,总是感觉差一点就可以做出来,以至于一直到最后都没能看这道题qaq 题意:类似于操作系统上讲的LRU算法,有两个操作,0操作代表访问其 ...

  9. 【SVN】SVN Working copy is too old

    前天在使用 SVN 客户端 CornerStone 的时候遇到了这个问题,代码不能提交了…… 遇到这个问题的时候怎么办? 解决办法: 找到报错对应的文件夹,里面有个 .svn 的文件夹,去掉再 com ...

  10. logging模块 旗舰版

    函数式简单配置 import logging logging.debug('debug message') logging.info('info message') logging.warning(' ...