webUI自動化測試框架(三):代碼分層-對象庫層

前言:做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模式做了一個簡單的改良,不用再寫那麼多頁面類了,這也是我在大牛那學習的皮毛,相信有更好的方法,希望各位童鞋可以積極交流。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章