06.1 PO模式
2024年10月28日大约 6 分钟
06.1 PO模式
1. 分析存在的问题
- 问题
- 元素定位的代码对页面特别依赖,一旦页面发生变化所有用到该页面的元素定位代码都需要进行修改
- 存在大量元素定位代码冗余
2. 认识PO模式
- PO模式:Pack Objectt的缩写,PO模式是自动化测试项目开发实践的最佳设计模式之一
PO模式-页面对象
编写步骤
- 定义页面元素实例属性
- 根据测试用例场景定义好所要用到的元素的实例属性
- 定义页面业务实例方法
- 一个页面可能存在多个业务方法,如登陆页面:登陆、找回密码等
- 抽取定位信息到实例属性
- 将元素定位的信息抽离到实例属性中进行统一管理,方便维护
- 定义页面元素实例属性
3. 使用PO模式对代码进行封装
1. 发现问题
PO页面定位元素受隐式等待影响
- 运行效率低:隐式等待依赖于界面的加载
- 解决方式:给所有的元素等待操作加上显示等待
模拟输入可能受输入框默认值影响输入的测试数据
- 影响测试结果:输入数据就会变成:默认值+输入数据
- 解决方式:每个模拟输入之前加上清除动作
2. PO-二次封装-元素定位
- 给所有的元素等待操作加上显示等待
- 对工具原有提供的方法或函数添加个性化设置的代码, 保障原有作用的情况下加上了个性化功能的封装
- 直接在页面对象中添加
- 代码冗余 -> 共性代码:定位
- 编写麻烦
3. PO-二次封装-模拟输入
所有模拟输入之前添加清除操作
- 代码冗余
- 编写麻烦
二次封装
4. PO模式训练
ID | 模块 | 优先级 | 测试标题 | 预置条件 | 步骤描述 | 测试数据 | 预期结果 | 测试结果 |
---|---|---|---|---|---|---|---|---|
01 | 搜索商 品 | P0 | 验证根据关 键 字搜索商 品 | 1. 打开TPSHOP 首页 | 在首页搜索输入框中输入关键 字点击【搜索】按钮 | 关键字:小米 | 1. 成功搜索到小米 相关的商品信 息 |
需求
对Tpshop首页进行PO封装 通过调用二次封装后元素定位方法和模拟输入的方法实现定位和输入
4. 数据驱动
1. 认识数据驱动
1. 数据驱动概念
以数据来驱动整个测试用例的执行,也就是测试数据决定测试结果
模块 标题 优先级 前置条件 操作步骤 测试数据 期望结果 实际结果 登陆 验证密码错误登陆是否成功 高 打开TPSHOP首页 1.点击首页【登陆】
2.输入用户名
3.输入密码
4.输入验证码
5.点击【登陆】用户名:正确
密码:error1.弹出提示:密码错误! 登陆 验证输入错误格式账号登陆 是否成功 高 打开TPSHOP首页 1.点击首页【登陆】
2.输入用户名
3.输入密码
4.输入验证码
5.点击【登陆】用户名:12asdasd
密码:1234561.弹出提示:账号格式不匹配! 测试功能点时,操作步骤一样,要测试该功能点各种业务规则,设计的重点在车上数据
注意:数据驱动技术可以将用户把关注点放在对测试数据的构建和维护上,而不是直接维护脚本,可以利用同样的过程对不同的数据输入进行测试
2. UI自动化测试数据驱动实现方式
提取数据
测试数据 期望结果 用户名:正确账号 密码:error 1.弹出提示:密码 错误! 用户名:12asdasd密码:123456 1.弹出提示:账号 格式不匹配! 读取数据
- 封装读取测试数据的方法
- 读取数据
- 组织成参数化所要求的数据格式
- 封装读取测试数据的方法
UnitTest参数化
- 测试用例引入参数化
- 通过调用读取测试数据的方法来获取数据
- @parameterized.expand()
- 测试用例引入参数化
- 常见数据存储方式
- 从文件读取数据,如JSON、excel、xml、txt等格式文件
- 从数据库中读取数据
- 调用接口、本地封装代码获取
2. PO数据驱动实现
1. 组织Tpshop登陆测试数据
login_case_data.json
测试标题 测试数据 期望结果 验证密码错误登 陆 用户名:正确账号 密码:error 1.弹出提示:密码错 误! 验证格式错误登 陆 用户名:12asdasd 密码:123456 1.弹出提示:账号格 式不匹配! 注意:如需要添加其它测试点,只需要到json文件中补 充对应的测试数据即可
2. 封装测试数据读取函数
利用json模块读load()取出所有json文件数据
遍历出测试数据第一层键值
遍历第一层时,没遍历一个键值再获取其键值并存储
[["15800000001","error","8888","密码错误"], ["158","123456","8888","账号格式不匹配"]]
封装测试数据读取函数 - 实现代码
注意
- object.values() 获取所有键值
- list(object.values()) 将获取的键值 强制转换成列表
- 定义case_data空列表用于存储每 次遍历得到的测试数据
3. 测试用例参数化引入
- 利用参数化技术,读取不同的数据组来执行同样的测试过程,验证不同的测试结果
5. 总结
UI自动化测试中数据驱动的核心是:
- 利用参数化技术使用同样的测试步骤来执行不同的测试数据,验证各种测试情况
- 将测试数据和测试脚本分离,编写完成操作脚本后,将重点放到数据 的维护和构建上
数据存储的方式有多种,并不限于json文件存储形式,只要最终提供给参数化的数据是符合规定格式的即可。
PO是什么
- PO:Page Object(⻚⾯对象),将⾃动化涉及的⻚⾯或模块封装成对象。
PO能解决什么问题?
- 代码复⽤性
- 便于维护(脚本层与业务分离)-- 如果元素信息发⽣变化了,也不⽤去修改脚本。
PO如何做?
- Base层
- 存放所有⻚⾯公共⽅法。
- Page层
- 基于⻚⾯或模块单独封装当前⻚⾯要操作的对象
- Script层
- 脚本层+unittest
- Base层
⾮PO模式代码实现
import unittest
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.by import By
class TestLogin(unittest.TestCase):
def setUp(self) -> None:
self.driver = webdriver.Chrome()
self.driver.maximize_window()
self.driver.get("http://192.168.10.31:9003/Home/user/login.html")
self.driver.implicitly_wait(10)
def tearDown(self) -> None:
sleep(5)
self.driver.quit()
def test01_login(self):
# 输入用户名
self.driver.find_element(By.CSS_SELECTOR, "#username").send_keys("13600001111")
# 输入密码
self.driver.find_element(By.CSS_SELECTOR, "#password").send_keys("123456")
# 输入验证码
self.driver.find_element(By.CSS_SELECTOR, "#verify_code").send_keys("8888")
# 点击登录
self.driver.find_element(By.CSS_SELECTOR, ".J-login-submit").click()
# 退出
self.driver.find_element(By.PARTIAL_LINK_TEXT, '退出').click()