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