前言
本文抛砖引玉,通过以下几个测试框架的封装示例,一步步引导你实现属于自己的 yaml 测试框架:
-
加法测试
-
计算测试
-
接口测试
-
Web 测试
关于本插件的基本介绍,请参见前文《pytest-yaml-sanmu(一):把yaml作为测试文件的pytest插件》
关于本插件的简单示例,请参见前文《pytest-yaml-sanmu(二):使用hook自定义yaml用例的执行方式》
yaml 实现 API 测试
注:
本文 API 测试 特指 HTTP API 测试
1. 步骤分析
HTTP 是一个无状态协议,其通讯过程可简要描述为:发送请求、回复响应,
所以,API 测试步骤主要包含 2 种类型:
-
构造请求
-
断言响应
注:
在复杂的项目场景下,可能包含更多的类型
其中,
第一个步骤根据用例内容,构造 HTTP 请求,并发送到 API 服务器,得到 HTTP 响应
第二个步骤根据用例内容,判断 HTTP 响应的内容是否正确
从更加抽象的角度来看,
第一个步骤是访问目标系统,
第二个步骤是断言上一步骤的结果
由此可见,用例步骤能否保持正确的顺序是非常重要的
此外,尽管一个步骤就可以完成接口请求,但是一个用例中可能需要多次调用不同的接口
由此可见,用例步骤能否保持弹性兼容也是非常重要的
在理想情况下,
一个测试用例中可以发送 N 次请求,并执行 M 次断言,其中 N>=1, N>=1
2. 安装依赖
pip install requests responses-validator
其中:
-
requests 用来发送 HTTP 请求
-
responses-validator 用来断言 HTTP 响应
二者都支持函数式调用,这使得我们仅需从 yaml 的测试步骤中读取到正确的参数,传递给依赖即可
关于 requests 的参数和用法可以参考《Python接口测试库:Requests用法大全》
关于 responses-validator 的参数和用法可以参考《用更适合yaml的方式对requests响应进行断言》
3. 设计用例
根据步骤分析、和依赖的用法,
设计 yaml 版 API 测试用例如下:
test_name: 访问百度首页
steps:
- request: # 步骤 1:发送请求
method: get
url: https://www.baidu.com
- response: # 步骤 2:断言响应(成功)
status_code: 200
text: "*baidu*"
- response: # 步骤 3:另一个断言(失败)
status_code: 404
4. 实现 hook
接下来根据用例内容,实现 hook,使得每个步骤都能够正确地执行
实现 API 测试 hook
执行结果如下:
API 测试执行结果
从执行结果中可以看到:
-
不同类型的测试步骤均可识别、处理
-
相同类型的测试步骤可以有多个
-
接口的请求、断言,均由其他库实现,非本插件的职责
至此,用于 API 测试的 yaml 用例已成功实现
yaml 实现 Web 测试
1. 步骤分析
和 API 测试最大的不同的是,Web 测试属于有状态测试,
步骤之间往往有着巨大的依赖和影响,所以一个 Web 测试通常包含大量的测试步骤;
还有,Web 测试通常使用 Selenium 进行浏览器控制,
selenium 没有提供像 requests 那样的统一传参接口,所以在执行Web测试时,需要根据实时状态灵活调用不同的方法、传递不同的参数;
此外,对浏览器进行自动化操作之后,其结果并不会进行返回,而是作用在 Web 页面的现实效果上,
所以不能直接对操作进行断言,而是需要再一次主动从页面中获取结果,然后再进行断言,
而某个操作会产生什么效果,这个效果如何表现,如何获取,如何验证,就是另一个复杂的话题了;
由此可见,Web 自动化测试的显著特点有:
-
步骤多
-
参数多变
-
断言难度大
注:
在实际项目中通常会对 selenium 进行二次封装,以减少步骤和参数,从而降低一定难度
但是受限于 Web 项目自身的特点,封装后的效率和难度依旧无法和 API 测试相比
2. 安装依赖
pip install selenium webdriver-helper
其中:
-
selenium 用来自动化操作浏览器
-
webdriver-helper 用来加速下载浏览器驱动
如果你已经可以高速访问国外各网址,则不需要安装 webdriver-helper
3. 设计用例
鉴于 web 测试的复杂度,我们可以先写出 python 版的用例
python 版本 web 测试用例
如图所示,web 测试用例步骤大致可分为 3 类:
-
外部函数
-
driver 中的成员方法
-
find_element 返回值中的成员方法
参数类型可分为 3 类:
-
无参数
-
位置参数
-
关键字参数
为了降低难度,该用例没有使用断言
接下来,根据 python 版本 web 测试用例,设计 yaml 版 Web 测试用例如下:
test_name: 使用百度搜索
steps:
- get_webdriver:
- implicitly_wait: 10
- get: https://www.baidu.com
- find_element:
by: xpath
value: '//*[@id="kw"]'
action: # 此非selenium原生参数,需要二次处理
send_keys: '大红灯笼高高挂'
- find_element:
by: xpath
value: '//*[@id="su"]'
action: # 此非selenium原生参数,需要二次处理
click:
- get_screenshot_as_file: page.png
- quit:
4. 实现 hook
接下来根据用例内容,实现 hook,使得每个步骤都能够正确执行
实现 WEB 测试 hook
执行结果如下
web 测试执行结果
本次用例没有使用断言,于是对执行结果进行了截图记录
生成截图如下
web 测试截图记录
至此,用于 Web 测试的 yaml 用例已成功实现
小结
通过目前这两个例子,想必你已经更直观地感受了通过 yaml 编写测试用例的步骤和思路。
并且验证了本插件可以用于 API 测试、Web 测试等实际业务场景中。
尽管如此,还有几点温馨提示:
-
本文初衷是介绍 pytest 插件的用法,对具体用例内容和步骤处理仅为简单演示。实战中还请根据实际情况调整用例格式 hook 内容;
-
不论是接口请求还是浏览器控制,均不属于 pytest 范畴,更不属于 pytest 插件范畴。还请针对性研习对应的依赖库精进用法;
-
本插件的主要功能是使用 yaml 作为测试用例,如果遇到复杂用例不知如何使用 yaml 表示,还请先写出 python 版本用例,再依样改写
-
本插件目前还不能完全使用 yaml 代替 python 作为用例,更加复杂的用例或使用了 python 高级特性的用例,还请继续使用 python 来写
好消息是,本插件实现了 @pytest.mark
,基于此,支持了 pytest 以下特性:
-
用例标记 、筛选
-
参数化测试
-
请求 fixture
-
预期失败
-
跳过执行
-
用例排序(需安装另外插件)
后续还将尽力支持更多的pytest原生特性
原创不易,喜欢请星标+点赞+在看,关注公众号《测试开发研习社》,不错过技术干货,谢谢鼓励!