专栏首页测试人生一篇文章学会PageFactory模式

一篇文章学会PageFactory模式

前言

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

本文分享自微信公众号 - 软件测试君(backlight2018),作者:糖小幽

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-08-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • SpringBoot 动态修改定时任务频率

    调试情况如下: 1.调用start 2.调用change,并传入0/3 * * * * * 3.调用stop

    软件测试君
  • Selenium+java - 借助autolt完成上传文件操作

    上传文件是每个自动化测试同学会遇到,而且可以说是面试必考的问题,标准控件我们一般用sendkeys()就能完成上传,但是我们的测试网站的上传控件一般为自己封装的...

    软件测试君
  • Selenium中Page Object设计模式

    Page Object(页面对象)模式,是Selenium实战中最为流行,并且被做自动化测试同学所熟悉和推崇的一种设计模式之一。在设计测试时,把页面元素定位和元...

    软件测试君
  • Java EE之SSM框架整合开发 -- (5) Spring的事务管理

    答:在代码中显式调用beginTransaction()、commit()、rollback()等事务处理相关的方法,这就是编程式事务管理。

    浩Coding
  • SpringCloud技术指南系列(十二)API网关之Gateway使用

    API网关是一个更为智能的应用服务器,它的定义类似于面向对象设计模式中的Facade模式,它的存在就像是整个微服务架构系统的门面一样,所有的外部客户端访问都需要...

    品茗IT
  • 使用aop加解密http接口

    最近在写一个小程序接口,由于安全性比较高,因此需要给请求参数和响应进行加密处理。如果在每个方法上都加密解密,那样代码就显得太繁琐了而且工作量会加大。所以,我们会...

    Java旅途
  • Java命令模式(Command)

      将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化;对请求排队或记录日志,以及支持可撤销的操作,将”发出请求的对象”和”接收与执行这些请求的对象”...

    用户4919348
  • Visual Studio 2008 每日提示(十七)

    #161、在解决方案里显示(或不显示)编辑器中打开的文件 原文链接:How to have the Solution Explorer always show...

    Jianbo
  • 第七章:Trigger监听器和Job监听器

    监听器(listener)是你创建的对象,主要作用是接收和处理调度器回调的事件(event)。TriggerListener接收到与触发器(Trigger)相关...

    Throwable
  • 浅谈事务(一) (r5笔记第24天)

    关于事务,在Oracle中似乎是习以为常的,但是在学习MySQL的过程中,发现各种灵活的存储引擎,一个很大的焦点就是对于事务的支持,足以看出事务的实现还是有一定...

    jeanron100

扫码关注云+社区

领取腾讯云代金券