po编程——自动化测试面试必问
先来看一个在腾讯课堂首页搜索机构的操作步骤:
1:首先打开腾讯课堂的首页:https://ke.qq.com
2:点击课程或机构的下拉选择图标
3:选择机构
4:在搜索框输入要搜索的机构名称
5:点击查找图标查找机构,跳转到查找结果页面
6:检查查找出的机构名称
7:点击机构logo跳转详情页面
上述操作涉及到两个页面,腾讯课堂首页和搜索结果页,操作图示如下:
1:腾讯课堂首页

2:搜索结果页面

使用webdirver的api完成模拟上述步骤代码如下:
SearchCase.java
1 package com.lemon.auto.po;
2
3 import org.openqa.selenium.By;
4 import org.openqa.selenium.WebDriver;
5 import org.openqa.selenium.firefox.FirefoxDriver;
6
7 public class SearchCase {
8
9 public static void main(String[] args) {
10 //设置火狐的可执行文件的路径
11 System.setProperty("webdriver.firefox.bin", "D:/Program Files/Mozilla Firefox/firefox.exe");
12 //创建一个火狐驱动
13 WebDriver driver = new FirefoxDriver();
14
15 //1:打开腾讯课堂首页
16 driver.get("https://lemon.ke.qq.com");
17 //2:定位下拉图标,并点击
18 driver.findElement(By.cssSelector("i[class='icon-font i-v-bottom-small']")).click();
19 //3:定位课程或机构的下拉选择图标,并点击
20 driver.findElement(By.cssSelector("span[class='mod-search-dropdown-item']")).click();
21 //4:定位搜索输入框,并输入搜索内容“柠檬班”
22 driver.findElement(By.id("js_keyword")).sendKeys("柠檬班");
23 //5:定位搜索图标,并点击,进行搜索
24 driver.findElement(By.id("js_search")).click();
25 //6:获得机构名称
26 String agencyName = driver.findElement(By.cssSelector("h2[class='search-agency-name']")).getText();
27 System.out.println(agencyName);
28 //7:定位logo,并点击调整机构详情页面
29 driver.findElement(By.cssSelector("a[href='//lemon.ke.qq.com']")).click();
30
31 //关闭当前窗口
32 driver.close();
33 }
34 }
上述代码简单而清晰,但如果每个测试用例都这样去写的话,将会出现非常多的重复性代码,可维护性较低,因此,在使用Selenium WebDirver进行自动化开发时,可以使用po(页面对象)编程的思想,减少重复性代码、提高代码的可维护性。
一:po的概念与思想
po是page object的缩写,即页面对象。使用po是对页面进行抽象或者说建模的过程,需要把页面当作一个对象。
面向对象编程语言中,进行面向对象编程需要考虑以下两点:
1:对象的属性(全局变量)
2:对象的行为(函数)
po思想也是一样,对页面进行抽象时,把页面的一个一个的web元素设计为页面对象的属性,把页面上的操作(如点击、输入等)设计为页面对象的行为
二:po中元素的定位
Selenium提供了许多注解和Api可以方便的定位元素和初始化元素,如下是腾讯课堂首页下拉选择机构图标的声明方式:
1 @FindBy(css="i[class='icon-font i-v-bottom-small']")
2 @CacheLookup
3 public WebElement select_icon;
三行代码释义:
1、@FindBy(css="i[class='icon-font i-v-bottom-small']")
指定了要元素的定位方式,如上表示以cssSelector方式进行定位,还有其他7种写法@FindBy(id="xxx")、@FindBy(name="xxx")...
2、@CacheLookup
表示缓存查找到元素,重复使用可提高查询速度
3、public WebElement select_icon;
声明一个web元素类型的全局变量
三:po中元素的初始化
Po提供了 PageFactory.initElements()来初始化页面元素,把查找的元素赋值到我们定义的属性(全局变量)上面
为了非常方便的进行页面元素的初始化,我们把该方法放置到页面类型的构造方法中,当调用该构造方法创建页面对象时,会调用该方法同时初始化页面的元素
代码如下:
1 public KeqqHomePage() {
2 PageFactory.initElements(driver, this);
3 }
四:页面行为抽象
元素初始化后,通过操作元素(如点击,输入)即可完成页面的功能,po中对页面功能的抽象,则提现为声明一个一个的对象方法
如下是页面选择机构的行为的抽象:
1 public void selectOrg(){
2 //选择机构需要进行两步操作,首先点击下拉图标,然后点击机构选项,
3 //两步操作写入到该方法,页面对象调用该对象方法,则可完成选择结构的行为
4 select_icon.click();
5 org_item.click();
6 }
下面是对“腾讯课堂首页”页面进行抽象的完整代码:
KeqqHomePage.java
1 package com.lemon.auto.po;
2 import org.openqa.selenium.WebElement;
3 import org.openqa.selenium.support.CacheLookup;
4 import org.openqa.selenium.support.FindBy;
5 import org.openqa.selenium.support.PageFactory;
6
7 /**
8 * 腾讯课堂首页类
9 * @author tommy
10 * @date 2018年5月11日
11 * @email
12 */
13 public class KeqqHomePage extends BasePage {
14 //下拉图标
15 @FindBy(css = "i[class='icon-font i-v-bottom-small']")
16 @CacheLookup //缓存元素,重复使用提高效率
17 public WebElement select_icon; //首页上选择图标
18
19 //机构元素
20 @FindBy(css = "span[class='mod-search-dropdown-item']")
21 @CacheLookup
22 public WebElement org_item;//结构选项
23
24 //输入框
25 @FindBy(id = "js_keyword")
26 @CacheLookup
27 public WebElement search_input;
28
29 //搜索按钮
30 @FindBy(id = "js_search")
31 @CacheLookup
32 public WebElement search_btn;
33
34 //页面的url
35 private static final String HOME_PAGE_URL = "https://ke.qq.com";
36
37 //打开首页
38 public void openUrl() {
39 driver.get(HOME_PAGE_URL);
40 }
41
42 /**
43 * 关闭浏览器
44 */
45 public void close() {
46 driver.quit();
47 }
48
49 //默认构造方法
50 public KeqqHomePage() {
51 //当前页面、当前对象
52 PageFactory.initElements(driver, this);
53 }
54
55 //2:方法(行为)
56 /**
57 * 选择机构
58 */
59 public void selectOrg() {
60 //选择机构需要进行什么操作
61 select_icon.click();
62 org_item.click();
63 }
64
65 /**
66 * 输入内容并且搜索---》返回一个结果页面
67 */
68 public SearchResultPage typeContentAndSearch(String content) {
69 //输入框输入内容
70 search_input.sendKeys(content);
71 //搜索按钮点击
72 search_btn.click();
73 return new SearchResultPage();
74 }
75 }
其中继承的父类BasePage仅仅只包含一个静态全局变量driver,方便其他页面继承直接使用
BasePage.java
1 package com.lemon.auto.po;
2 import org.openqa.selenium.WebDriver;
3 import com.lemon.auto.BrowerSelector;
4
5 public class BasePage {
6 //全局的webdirver
7 protected static WebDriver driver = BrowerSelector.getWebDriver();
8 }
其中BrowerSelector.getWebDriver()方法是封装好的一个工具类,用来启动浏览器,得到driver对象用的,在后面的源代码网盘链接中可以下载到。
相同的方式对“结果页面”进行抽象,代码如下:
SearchResultPage.java
1 package com.lemon.auto.po;
2
3 import org.openqa.selenium.WebElement;
4 import org.openqa.selenium.support.CacheLookup;
5 import org.openqa.selenium.support.FindBy;
6 import org.openqa.selenium.support.PageFactory;
7
8 public class SearchResultPage extends BasePage {
9
10 //logo图标
11 @FindBy(css = "a[href='//lemon.ke.qq.com']")
12 @CacheLookup
13 public WebElement logo_icon;
14
15 //机构名label
16 @FindBy(css = "h2[class='search-agency-name']")
17 @CacheLookup
18 public WebElement agency_name_label;
19
20 public SearchResultPage() {
21 PageFactory.initElements(driver, this);
22 }
23
24 /**
25 * 校验搜索结果
26 */
27 public void checkSearchResult() {
28 System.out.println(agency_name_label.getText());
29 }
30
31 /**
32 * 到机构的详情页面
33 */
34 public void toAgencyDetail() {
35 logo_icon.click();
36 }
37
38 }
执行测试的类,代码如下:
Tester.java
1 package com.lemon.auto.po;
2
3 public class Tester {
4
5 public static void main(String[] args) throws InterruptedException {
6 //1:打开腾讯课堂首页,创建页面对象模型
7 KeqqHomePage homePage = new KeqqHomePage();
8 homePage.openUrl();
9 //2:选择机构
10 homePage.selectOrg();
11 //3:输入内容并且点击搜索
12 SearchResultPage resultPage = homePage.typeContentAndSearch("柠檬班");
13 //4:检测结果
14 resultPage.checkSearchResult();
15 //5:到机构的详情页面、
16 resultPage.toAgencyDetail();
17 Thread.sleep(10000);
18 //关闭浏览器
19 homePage.close();
20 }
21 }
总结:
po编程,实质上就是分离页面元素、封装页面元素操作的过程,将可能变化的页面元素单独映射到对象属性、将页面元素操作抽象成函数,让我们以面向对象方式理解抽象一个页面,实际上就是编程中解耦思想的应用,从而简化测试用例的步骤,提高自动化测试代码的可维护性。
附公开课视频和源码百度云链接:
https://pan.baidu.com/s/1GoZyigdWiHIQY3xy9nE2ww 密码:1fgl
po编程——自动化测试面试必问的更多相关文章
- linux驱动工程面试必问知识点
linux内核原理面试必问(由易到难) 简单型 1:linux中内核空间及用户空间的区别?用户空间与内核通信方式有哪些? 2:linux中内存划分及如何使用?虚拟地址及物理地址的概念及彼此之间的转化, ...
- 互联网公司面试必问的mysql题目(下)
这是mysql系列的下篇,上篇文章地址我附在文末. 什么是数据库索引?索引有哪几种类型?什么是最左前缀原则?索引算法有哪些?有什么区别? 索引是对数据库表中一列或多列的值进行排序的一种结构.一个非常恰 ...
- 互联网公司面试必问的Redis题目
Redis是一个非常火的非关系型数据库,火到什么程度呢?只要是一个互联网公司都会使用到.Redis相关的问题可以说是面试必问的,下面我从个人当面试官的经验,总结几个必须要掌握的知识点. 介绍:Redi ...
- 【面试必问】python实例方法、类方法@classmethod、静态方法@staticmethod和属性方法@property区别
[面试必问]python实例方法.类方法@classmethod.静态方法@staticmethod和属性方法@property区别 1.#类方法@classmethod,只能访问类变量,不能访问实例 ...
- 互联网公司面试必问的mysql题目(上)
又到了招聘的旺季,被要求准备些社招.校招的题库.(如果你是应届生,尤其是东北的某大学,绝对福利哦) 介绍:MySQL是一个关系型数据库管理系统,目前属于 Oracle 旗下产品.虽然单机性能比不上or ...
- 面试必问:JVM类加载机制详细解析
前言 在Java面试中,简历上有写JVM(Java虚拟机)相关的东西,JVM的类加载机制基本是面试必问的知识点. 类的加载和卸载 JVM是虚拟机的一种,它的指令集语言是字节码,字节码构成的文件是cla ...
- 一线大厂Java面试必问的2大类Tomcat调优
一.前言 最近整理了 Tomcat 调优这块,基本上面试必问,于是就花了点时间去搜集一下 Tomcat 调优都调了些什么,先记录一下调优手段,更多详细的原理和实现以后用到时候再来补充记录,下面就来介绍 ...
- python笔记39-unittest框架如何将上个接口的返回结果给下个接口适用(面试必问)
前言 面试必问:如何将上个接口的返回结果,作为下个接口的请求入参?使用unittest框架写用例时,如何将用例a的结果,给用例b使用. unittest框架的每个用例都是独立的,测试数据共享的话,需设 ...
- 高级测试工程师面试必问面试基础整理——python基础(一)(首发公众号:子安之路)
现在深圳市场行情,高级测试工程师因为都需要对编程语言有较高的要求,但是大部分又没有python笔试机试题,所以面试必问python基础,这里我整理一下python基本概念,陆续收集到面试中python ...
随机推荐
- Markdown语法简介
1.标题 在想要设置为标题的文字前面加#来表示一个#代表一级标题,总共六级 2.字体 加粗要加粗的文字左右分别用两个*号包起来 斜体要倾斜的文字左右分别用一个*号包起来 斜体加粗要倾斜和加粗的文字左右 ...
- C# 8中的范围类型(Range Type)
C# 8.0中加入了一个新的范围类型(Range Type). 这里我们首先展示一些代码,并一步一步为代码添加一些不同的东西, 为大家展示一下范围类型的功能和用法. 我们最原始的代码如下: stati ...
- 在Mac上使用vs-code快速上手c语言学习(入门文,老鸟退散)
天下事,合久必分.分久必合,你肯定想不到当你逃离到Mac平台这么多年之后,有一天你会再用微软的产品来写代码 :) 其实微软的产品虽然用户体验总是做不到最好,但整体上的确拉低了行业的进入门槛,对于编程也 ...
- 线段树(区间树)之区间染色和4n推导过程
前言 线段树(区间树)是什么呢?有了二叉树.二分搜索树,线段树又是干什么的呢?最经典的线段树问题:区间染色:正如它的名字而言,主要解决区间的问题 一.线段树说明 1.什么是线段树? 线段树首先是二叉树 ...
- 精读《react-easy-state 源码》
1. 引言 react-easy-state 是个比较有趣的库,利用 Proxy 创建了一个非常易用的全局数据流管理方式. import React from "react"; i ...
- RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.2-模块管理按子系统进行分类管理
在RDIFramework.NET以往的框架中,模块管理界面展示了整个框架所管理的所有模块,如果系统过多,达几十个甚至上百个子系统时,管理起来就非常的麻烦,不光加载效率会很低,页面展示也会很不友好.框 ...
- msf中exploit的web_delivery模块
背景:目标设备存在远程文件包含漏洞或者命令注入漏洞,想在目标设备上加载webshell,但不想在目标设备硬盘上留下任何webshell文件信息 解决思路:让目标设备从远端服务器加载webshell代码 ...
- 学习编写Dockerfile
前言 我们学习docker的话,其主要目的还是要用来改变我们部署应用程序的传统习惯,达到解放生产力,解放人力的目的.这篇则自己来熟悉一下dockerfile常用命令.并且尝试改变下生产环境手动部署应用 ...
- python-IO编程,文件读写
一.文件读写 1.打开文件 函数:open(name[. mode[. buffering]]) 参数: name:必须:文件的文件名(全路径或执行文件的相对路径.)) mode:可选:对文件的读写模 ...
- 配置多个 git 账号的 ssh密钥
背景 在工作中,我们通常会以 ssh 的方式配置公司的 git 账号,但是平时也会使用 github 管理自己的项目.因此,我们需要为自己的 github 创建一个新的 git 账号,这就需要生成新的 ...