po,页面对象编程

先来看一个在腾讯课堂首页搜索机构的操作步骤:

1:首先打开腾讯课堂的首页:https://ke.qq.com

2:点击课程或机构的下拉选择图标

3:选择机构

4:在搜索框输入要搜索的机构名称

5:点击查找图标查找机构,跳转到查找结果页面

6:检查查找出的机构名称

7:点击机构 logo 跳转详情页面

上述操作涉及到两个页面,腾讯课堂首页和搜索结果页,操作图示如下:

1:腾讯课堂首页
image.png

2:搜索结果页面
image.png

使用 webdirver 的 API 完成模拟上述步骤代码如下:

SearchCase.java

package com.lemon.auto.po;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;

public class SearchCase {

	public static void main(String[] args) {
		//设置火狐的可执行文件的路径
		System.setProperty("webdriver.firefox.bin", "D:/Program Files/Mozilla Firefox/firefox.exe");
		//创建一个火狐驱动
		WebDriver driver = new FirefoxDriver();
		//1:打开腾讯课堂首页
		driver.get("https://lemon.ke.qq.com");
		//2:定位下拉图标,并点击
		driver.findElement(By.cssSelector("i[class='icon-font i-v-bottom-small']")).click();
		//3:定位课程或机构的下拉选择图标,并点击
	driver.findElement(By.cssSelector("span[class='mod-search-dropdown-item']")).click();
		//4:定位搜索输入框,并输入搜索内容“柠檬班”
		driver.findElement(By.id("js_keyword")).sendKeys("柠檬班");
		//5:定位搜索图标,并点击,进行搜索
		driver.findElement(By.id("js_search")).click();
		//6:获得机构名称
		String agencyName = driver.findElement(By.cssSelector("h2[class='search-agency-name']")).getText();
		System.out.println(agencyName);
		//7:定位logo,并点击调整机构详情页面
	driver.findElement(By.cssSelector("a[href='//lemon.ke.qq.com']")).click();
		//关闭当前窗口
		driver.close();
	}
}

上述代码简单而清晰,但如果每个测试用例都这样去写的话,将会出现非常多的重复性代码,可维护性较低,因此,在使用 Selenium WebDirver 进行自动化开发时,可以使用 po(页面对象)编程的思想,减少重复性代码、提高代码的可维护性。

一:po 的概念与思想

po 是 page object 的缩写,即页面对象。使用 po 是对页面进行抽象或者说建模的过程,需要把页面当作一个对象。

面向对象编程语言中,进行面向对象编程需要考虑以下两点:

1:对象的属性(全局变量)

2:对象的行为(函数)

po 思想也是一样,对页面进行抽象时,把页面的一个一个的 Web 元素设计为页面对象的属性,把页面上的操作(如点击、输入等)设计为页面对象的行为

二:po 中元素的定位

Selenium 提供了许多注解和 API 可以方便的定位元素和初始化元素,如下是腾讯课堂首页下拉选择机构图标的声明方式:

	@FindBy(css="i[class='icon-font i-v-bottom-small']")
	@CacheLookup 
	public WebElement select_icon; 

三行代码释义:

  1. @FindBy(css="i[class='icon-font i-v-bottom-small']")

指定了要元素的定位方式,如上表示以 cssSelector 方式进行定位,还有其他 7 种写法@FindBy(id="xxx")、@FindBy(name="xxx")...

  1. @CacheLookup

表示缓存查找到元素,重复使用可提高查询速度

  1. public WebElement select_icon;

声明一个 Web 元素类型的全局变量

三:po 中元素的初始化

Po 提供了 PageFactory.initElements()来初始化页面元素,把查找的元素赋值到我们定义的属性(全局变量)上面

为了非常方便的进行页面元素的初始化,我们把该方法放置到页面类型的构造方法中,当调用该构造方法创建页面对象时,会调用该方法同时初始化页面的元素

代码如下:

public KeqqHomePage() {
		PageFactory.initElements(driver, this);
}

四:页面行为抽象

元素初始化后,通过操作元素(如点击,输入)即可完成页面的功能,po 中对页面功能的抽象,则提现为声明一个一个的对象方法

如下是页面选择机构的行为的抽象:

public void selectOrg(){
		//选择机构需要进行两步操作,首先点击下拉图标,然后点击机构选项,
两步操作写入到该方法页面对象调用该对象方法则可完成选择结构的行为
		select_icon.click();
		org_item.click();
	}

下面是对“腾讯课堂首页”页面进行抽象的完整代码:

KeqqHomePage.java

package com.lemon.auto.po;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.CacheLookup;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;

/**
 * 腾讯课堂首页类
 * @author tommy
 * @date 2018年5月11日
 * @email 
 */
public class KeqqHomePage extends BasePage {
	//下拉图标
	@FindBy(css = "i[class='icon-font i-v-bottom-small']")
	@CacheLookup //缓存元素,重复使用提高效率
	public WebElement select_icon; //首页上选择图标

	//机构元素
	@FindBy(css = "span[class='mod-search-dropdown-item']")
	@CacheLookup
	public WebElement org_item;//结构选项

	//输入框
	@FindBy(id = "js_keyword")
	@CacheLookup
	public WebElement search_input;

	//搜索按钮
	@FindBy(id = "js_search")
	@CacheLookup
	public WebElement search_btn;
	//页面的url
	private static final String HOME_PAGE_URL = "https://ke.qq.com";
	//打开首页
	public void openUrl() {
		driver.get(HOME_PAGE_URL);
	}

	/**
	 * 关闭浏览器
	 */
	public void close() {
		driver.quit();
	}

	//默认构造方法
	public KeqqHomePage() {
		//当前页面、当前对象
		PageFactory.initElements(driver, this);
	}

	//2:方法(行为)
	/**
	 * 选择机构
	 */
	public void selectOrg() {
		//选择机构需要进行什么操作
		select_icon.click();
		org_item.click();
	}

	/**
	 * 输入内容并且搜索---》返回一个结果页面
	 */
	public SearchResultPage typeContentAndSearch(String content) {
		//输入框输入内容
		search_input.sendKeys(content);
		//搜索按钮点击
		search_btn.click();
		return new SearchResultPage();
	}
}

其中继承的父类 BasePage 仅仅只包含一个静态全局变量 driver,方便其他页面继承直接使用
BasePage.java

package com.lemon.auto.po;
import org.openqa.selenium.WebDriver;
import com.lemon.auto.BrowerSelector;

public class BasePage {
	//全局的webdirver
	protected static WebDriver driver = BrowerSelector.getWebDriver();
}

其中 BrowerSelector.getWebDriver()方法是封装好的一个工具类,用来启动浏览器,得到 driver 对象用的,在后面的源代码网盘链接中可以下载到。
相同的方式对“结果页面”进行抽象,代码如下:
SearchResultPage.java

package com.lemon.auto.po;

import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.CacheLookup;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;

public class SearchResultPage extends BasePage {

	//logo图标
	@FindBy(css = "a[href='//lemon.ke.qq.com']")
	@CacheLookup
	public WebElement logo_icon;

	//机构名label
	@FindBy(css = "h2[class='search-agency-name']")
	@CacheLookup
	public WebElement agency_name_label;

	public SearchResultPage() {
		PageFactory.initElements(driver, this);
	}

	/**
	 * 校验搜索结果
	 */
	public void checkSearchResult() {
		System.out.println(agency_name_label.getText());
	}

	/**
	 * 到机构的详情页面
	 */
	public void toAgencyDetail() {
		logo_icon.click();
	}
}

执行测试的类,代码如下:
Tester.java

package com.lemon.auto.po;

public class Tester {

	public static void main(String[] args) throws InterruptedException {
		//1:打开腾讯课堂首页,创建页面对象模型
		KeqqHomePage homePage = new KeqqHomePage();
		homePage.openUrl();
		//2:选择机构
		homePage.selectOrg();
		//3:输入内容并且点击搜索
		SearchResultPage resultPage = homePage.typeContentAndSearch("柠檬班");
		//4:检测结果
		resultPage.checkSearchResult();
		//5:到机构的详情页面、
		resultPage.toAgencyDetail();
		Thread.sleep(10000);
		//关闭浏览器
		homePage.close();
	}
}

po 编程,实质上就是分离页面元素、封装页面元素操作的过程,将可能变化的页面元素单独映射到对象属性、将页面元素操作抽象成函数,让我们以面向对象方式理解抽象一个页面,实际上就是编程中解耦思想的应用,从而简化测试用例的步骤,提高自动化测试代码的可维护性。

附公开课视频和源码百度云链接:
https://pan.baidu.com/s/1GoZyigdWiHIQY3xy9nE2ww 密码:1fgl

  • web自动化
    22 引用 • 76 回帖 • 1 关注
  • PO
    1 引用 • 12 回帖
  • Java
    12 引用 • 167 回帖 • 2 关注
1 操作
happy 在 2020-07-29 16:29:46 更新了该帖
12 回帖
请输入回帖内容 ...