webUI自动化测试框架(三):代码分层-对象库层

来源:互联网 发布:网络彩票服务器在国外 编辑:程序博客网 时间:2024/06/05 03:34

前言:做UI自动化,不可避免的要和页面上的元素打交道,有的童鞋可能会选择把页面元素的定位,操作都写在测试代码中,当页面元素比较少,测试代码比较少的情况下还好,但是一旦页面元素多起来(实际运用中也不太可能少),测试代码一多,就难以阅读和维护了,因为元素定位的代码并不能直接体现我要定位的是哪个元素,当页面元素变更了,我要去代码中找到该元素定位的代码也是比较困难的,这样就带了维护问题。

这里引入我们这个框架主要的设计理念:PO模式,这个我也是学习的大牛前辈,PO模式全称为Page Object模式,是webdriver中的一种测试设计模式,主要是将每个页面设计为一个class,其中包含了页面中需要测试的元素(按钮,输入框等),这样在写脚本时,可以通过调用页面类来获取该页面的元素。并且,当该页面因为需求变更,带来的元素变更时,我们也不需要改测试代码,只需要改这个页面类就行了,从而使得测试代码与页面元素管理分离。这样就清晰多了,维护起来也很简单明了。

但是,如果页面多了,比如我一个后台系统,有100多个页面,总不能写100个类吧,那维护起来也够呛,所以我们基于PO模式,再将它改良一下。


如下,进入正题:

先看分层:


1.定义一个页面基础类,BasePage,因为所有的页面都有共同点,我们可以将他们抽象出来:每个页面都有元素,每个页面元素需要做的动作,该类主要要做的就是找到这些元素,并做出相应动作:

package com.etyero.object;import java.util.HashMap;import org.openqa.selenium.WebDriver;import org.openqa.selenium.WebElement;import com.etyero.utils.LogUtil;import com.etyero.utils.UIExecutorImpl;import com.etyero.utils.XMLUtil;/** * 基础页面类 *  * @author ljl */public class BasePage extends UIExecutorImpl {protected WebDriver driver;protected String pageName;// 页面名称protected String xmlPath;// 页面元素配置文件路径protected HashMap<String, Locator> locatorMap;//存储页面元素信息public LogUtil log;public BasePage(WebDriver driver, String pageName) throws Exception {super(driver);this.driver = driver;this.pageName = pageName;// 获取page.xml路径,page.xml在同级目录xmlPath = this.getClass().getResource("").getPath() + "page.xml";locatorMap = XMLUtil.readXMLDocument(xmlPath, pageName);}public void click(String locatorName) {super.click(getLocator(locatorName));}public void sendKey(String locatorName, String value) {super.sendKey(getLocator(locatorName), value);}public String getText(String locatorName) {return super.getText(getLocator(locatorName));}public WebElement getElement(String locatorName) {return super.getElement(getLocator(locatorName));}public boolean isElementDisplayed(String locatorName) {return super.isElementDisplayed(getLocator(locatorName));}public void switchWindow(String title) {super.switchWindow(title);}public void switchFrame(String locatorName) {super.switchFrame(getLocator(locatorName));}/** * 根据locatorName返回对应的locator *  * @author ljl */public Locator getLocator(String locatorName) {Locator locator = null;if (locatorMap != null) {locator = locatorMap.get(locatorName);}return locator;}}

2.BasePage类中定义了一个变量,HashMap<String, Locator>  locatorMap,这个变量主要存放了页面元素信息,key为页面元素名称,是我们自己定义的,方便我们知道这个元素是干嘛的,locator 保存了这个元素的定位方式(如By.id,By.xpath),定位地址(如By.id时的id),等待时长:

package com.etyero.object;/** * 封装页面元素,每个元素都有相应的定位地址(xpath路径或css或id),等待时间,定位方式,默认为By.xpath *  * @author ljl * */public class Locator {private String address; // 定位地址private int waitSec; // 等待时间private ByType byType; // 定位方式/** * 定位类型枚举 *  * @author ljl * */public enum ByType {by, xpath, linkText, id, name, className}public Locator() {}/** * Locator构造器,默认定位类型By.xpath,等待时长3s *  * @author ljl * @param element */public Locator(String address) {this.address = address;this.waitSec = 3;this.byType = ByType.xpath;}public Locator(String address, int waitSec) {this.waitSec = waitSec;this.address = address;this.byType = ByType.xpath;}public Locator(String address, int waitSec, ByType byType) {this.waitSec = waitSec;this.address = address;this.byType = byType;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public int getWaitSec() {return waitSec;}public void setWaitSec(int waitSec) {this.waitSec = waitSec;}public ByType getByType() {return byType;}public void setByType(ByType byType) {this.byType = byType;}}

3.有了BasePage和Locator类,但是我们的页面元素怎么管理呢,这里我们就要用到xml文件了,我们将要测试的页面定义为一个page节点,每个page节点对应一个页面,这样就不用写100个类了;每个page节点下,放该页面要测试的元素,每个元素我们给他定义好定位方式,定位地址,等待时长,以及元素名称,元素名称是为了方便我们知道这个元素是干嘛的,能快速找到该元素进行维护。page.xml如下:

<?xml version="1.0" encoding="UTF-8"?><map><page pageName="mainPage"><!--Locator lists --><locator type="xpth" timeOut="30" value="/html/body/div[1]/div[7]">客服热线</locator></page><page pageName="minePage"><!--Locator lists --><locator type="id" timeOut="3" value="icon_user">用户头像</locator><locator type="id" timeOut="3" value="user_name">用户名</locator></page><page pageName="loginPage"><!--Locator lists --><locator type="id" timeOut="30" value="txtuser">登录输入账号框</locator><locator type="id" timeOut="30" value="txtuserp">登录输入密码框</locator><locator type="id" timeOut="30" value="btnLogin">登录</locator><locator type="id" timeOut="30" value="spanMessge">错误提示</locator></page></map>

举个栗子:如上的loginPage,有账号,密码,登录按钮,错误提示四个要测试的元素,我们给账号元素定义了一个locator标签,对应的定位方式为用id定位,id的值为txtuser,等待时长30s,该元素名称我们给它取名为登录输入账号框,这样,当登录框的地址变了,我们可以快速找到,这个是登录的账号框,改掉id就行了。另外,解析xml文件用我们第二章中基础层的XMLUtil类方法。各司其职,清晰明了。

以上,对PO模式做了一个简单的改良,不用再写那么多页面类了,这也是我在大牛那学习的皮毛,相信有更好的方法,希望各位童鞋可以积极交流。



原创粉丝点击