一、HTTPRUNNER2.x
1.1、工具介绍
- HttpRunner 是一款面向 HTTP(S) 协议的通用测试框架,只需编写维护一份 YAML/JSON 脚本,即可实现自动化测试、性能测试、线上监控、持续集成等多种测试需求。
1.2、设计思想
- 充分复用优秀的框架组装成更强大完整的框架
- 必须遵循 约定大于配置 的准则,在自动化测试中充分体现
- 追求投入产出比,一份投入即可实现多种测试需求
1.3、核心功能
- 继承Requests的全部功能
- 采用json/yaml格式作为测试用例数据载体
- 支持debugtalk.py辅助函数,增强脚本实践中的灵活性,实现动态计算逻辑
- 支持测试用例分层,实现测试用例复用:数据层、业务(逻辑层)层
- 支持unittest框架的setup、teardown处理机制:hook机制
- 支持har录制脚本生成测试用例(har2case)
- 结合locust框架,支持分布式性能测试
- 支持CLI命令行调用模式,便于jenkins集成
- 展示层:测试结果统计及优美的HTML报告+日志
- 扩展性:支持二次开发及实现web平台化
1.4、关于分层测试思想
区分一下自动化测试分层和测试框架分层、项目结构分层
- 所谓自动化测试分层,根据投入与产出比自上而下:UI(系统测试)、服务(api/集成测试)、底层(单元测试)
- 测试框架分层,能实现自动化测试的有:接口、UI、性能等;均采用测试数据与脚本分离策略
-
- 接口自动化测试框架分层:数据层(测试数据/用例)、业务层(逻辑层)、公共层(业务调用的公共方法)
-
- UI自动化测试框架分层(以PO设计模式为例):页面对象层(包含元素定位)、业务逻辑层(调用页面对象)、测试数据层(数据与脚本分离)
- 实现测试分层后搭建工程结构:业务层(调用或组装测试用例)、数据层(数据与测试用例/脚本分离)、公共库(基础类公共方法)、工具层(日志系统、数据库处理、报告处理)、展示层(HTML报告展示)、持久层(譬如用例、html报告等是否存放数据库)
二、搭建开发环境
我们是测试,为啥叫开发环境?因为测试的所有脚本及数据调试都是在本地开发测试完成,故而叫开发环境。测试环境适用于投产前的测试验证。
2.1、python环境
虽然官方支持了python2和python3,但是在咱们实际开发中,建议还是使用python3且在3.6及以上版本。
2.2、httprunner安装方式
为啥要指定安装版本?因为当前httprunner托管在PyPI上的稳定版已经是3.x版本了。
- pip install httprunner==2.3.2
版本升级
- pip install -U HttpRunner
安装校验
- hrun -V 或者–help
- har2case -V
2.3、关于python开发环境
实际开发过程中,建议养成良好的开发模式,在不同工程中创建不同的python虚拟开发环境,一则便于管理,二则便于工程迁移
创建虚拟环境的几种方式,有很多:推荐anaconda或者python -m venv
- python -m venv /path虚拟路径
三、基础概念
建议:在想使用某个工具/框架之前,先理解它的原理/设计思想,再弄明白与之对应理论概念。
- 测试用例(testcase)、测试步骤(teststep)、测试用例集(testsuite)
-
- 测试用例集testsuite下有testcases包含多个testcase
{ "config": { "name": "测试用例集:业务名称", "variables": { "token": "存放公共变量,可以在testcases下testcase中使用", }, "base_url": "${ENV(URL)}" }, "testcases": [{ "name": "可以是某个测试用例或api", "testcase": "testcases/homeIndex.json" }, { "name": "支持组装多个测试用例", "testcase": "testcases/myPractiecs.json" } ] }
AI 代码解读
-
- 测试用例testcase下有一个或多个test,它又能包含api、testcase;关于teststeps是在har2case转换录制的har文件才有的内容,如下示例:
{ "config": { "name": "可以描述一个业务场景或者单个用例业务", "base_url": "https://www.xxx.com" }, "teststeps": [{ "name": "接口业务名称描述", "skip": "skip login", "request": { "url": "/xx/xx/passwordLogin", "method": "POST", "headers": { "Content-Type": "application/json;charset=UTF-8", "User-Agent": "IeltsBroV3/10.0.0 (com.yasiBro.v2; build:5; iOS 13.3.0) Alamofire/4.9.0" }, "json": { "password": "111111", "deviceid": "99B5D095-67AD-4B79-A995-6C869A895873", "mobile": "13800138000", "pushToken": "d90e1e770a37ac3464930c968fed9885", "deviceName": "iPhone 8 Plus", "verifyCode": "", "loginType": 0, "channel": 0, "deviceType": "ios", "zone": "86" } }, "extract": [{ "token": "content.content.token" }], "validate": [{ "eq": [ "status_code", 200 ] } ] }] }
AI 代码解读
-
- 框架中正常演示的是
[{ "config": { "name": "全局设置.", "variables": { "user_agent": "存放灵活变量" }, "verify": false } }, { "test": { "name": "调用api拿到响应token", "api": "api/login.yml", "extract": { "token": "content.content.token" }, "validate": [{ "eq": [ "status_code", 200 ] }] } }, { "test": { "name": "请求某个业务接口", "api": "api/get_status.yml", "validate": [{ "eq": [ "status_code", 200 ] }] } } ]
AI 代码解读
-
- api的写法
{ "name": "登录接口", "base_url": "${ENV(URL)}", "variables": { "expected_status_code": 200 }, "request": { "url": "/xxx/xxx/passwordLogin", "method": "POST", "json": { "appVersion": 9, "channel": 1, "deviceName": "HUAWEI EML-AL00", "deviceType": "android", "deviceid": "0795cd72-3e05-40ba-9733-5df1c1fa0970", "loginType": 0, "mobile": "${ENV(MOBILE)}", "password": "${ENV(PASSWORD)}", "pushToken": "25b9b066dc939b9863fe9feb3fca654d", "systemVersion": "8.1.0", "zone": 86 } }, "validate": [{ "eq": [ "status_code", 200 ] }] }
AI 代码解读
这个框架还是建议使用yaml格式作为测试用例数据载体,看这个括号都眼花缭乱,维护起来也比较麻烦,yaml是一种dict or list的结果,可读性更好!
- api示例如下(是不是清晰可人):
name: 登录接口 base_url: ${ENV(URL)} variables: expected_status_code: 200 request: url: /hcp/apiLogin/passwordLogin method: POST json: appVersion: 9.0 channel: 1 deviceName: HUAWEI EML-AL00 deviceType: android deviceid: 0795cd72-3e05-40ba-9733-5df1c1fa0970 loginType: 0 mobile: ${ENV(MOBILE)} password: ${ENV(PASSWORD)} pushToken: 25b9b066dc939b9863fe9feb3fca654d systemVersion: 8.1.0 zone: 86 validate: - eq: [status_code, 200]
AI 代码解读
3.1、快速应用
上面已经对httprunner框架的基础概念有了了解,使用它的特性,就可以快速开展测试工作。
- 简要说明如何快速使用这个框架吧(文字描述版)
第一步:抓包,charles导出har数据包 第二步:转换,har2case xxx.har 默认json格式,-2y参数表示yaml格式 第三步:执行,hrun xxx.yml ,执行完毕当前目录下生成reports/xxx.html报告
AI 代码解读
3.2、应该要掌握的知识点
3.2.1、hook机制
测试用例testcase,config新增关键字:setup_hooks、teardown_hooks,表示在测试用例执行前后用于准备或清理工作
- setup_hooks
- teardown_hooks
-
- 测试用例层testcase
- config: name: 基础配置 request: base_url: http://127.0.0.1:8080/ setup_hooks: - ${hook_print(setup)} teardown_hooks: - ${hook_print(teardown)}
AI 代码解读
-
- 测试步骤层teststep
- test: name: 获取请求状态 request: url: /get_status method: GET teardown_hooks: - ${get_status($response)} validate: - eq: ["status_code", 500]
AI 代码解读
3.2.2、环境变量
应用场景:除了信息安全方面的考虑,还应该考虑如何切换环境、切换配置,故而需要使用全局或局部变量
- 该框架中可以在任意目录下新增.env文件(作用于当前执行目录),设置环境变量
ACCOUNT=13800013800 PASSWD=111111 BASEURL=https://www.baidu.com
AI 代码解读
- 引用:{ENV(ACCOUNT)}\{ENV(PASSWD)}${ENV(BASEURL)}
3.2.3、数据驱动
这里不再演示,在其他文章或网络都有详细使用说明,只说它支持的方式。
- 在 YAML/JSON 中直接指定参数列表,借用httprunner使用文档中的例子演示
config: name: "demo" testcases: testcase1_name: testcase: /path/to/testcase1 parameters: # 如下就是直接的列表形式,如果是字典多列表,参数使用-连接:user_agent-version,参数为嵌套列表的字典 user_agent: ["iOS/10.1", "iOS/10.2", "iOS/10.3"] testcase2_name: testcase: /path/to/testcase2 parameters: # 如果是字典多列表,参数使用-连接:user_agent-version,参数为嵌套列表的字典 user_agent-version: - ["iOS/10.1", "10.1"] - ["iOS/10.2", "10.2"]
AI 代码解读
- 通过内置的 parameterize(可简写为P)函数引用 CSV 文件
config: name: "demo" testcases: testcase1_name: testcase: /path/to/testcase1 parameters: # 数据量比较大的时候使用 user_id: ${P(data/user_id.csv)}
AI 代码解读
- 调用 debugtalk.py 中自定义的函数生成参数列表,此方式比较灵活
def get_account(num): accounts = [] for index in range(1, num+1): accounts.append( {"username": "user%s" % index, "password": str(index) * 6}, ) return accounts
AI 代码解读
-
- debugtalk定义的函数在测试用例文件中引用如下${func_name(parameters)}:
config: name: "demo" testcases: testcase1_name: testcase: /path/to/testcase1 parameters: username-password: ${get_account(10)}
AI 代码解读
3.2.4、关键字应用
这里引用的包括但不局限用例的组成部分
- extract提取关键字,提取当前接口响应参数作为下个接口的请求参数,参数关联时使用
- validate响应断言
- parameters全局参数
- setup_hooks、teardown_hooks框架支持的hook机制,它的函数放置在debugtalk中,
- variables测试步骤中定义的变量,作用域当前文件,但是支持从testsuite覆盖testcase
- base_url在testcase中path部分可以是完整地址,但是不能在有base_url的情况下
- api可以在testcase中调用api层的测试用例
- testcase同api有一样的效果
- output整个用例输出的参数列表
这里演示的用例文件都是yaml格式为准
api演示示例,包含上面的基本关键字,先写debugtalk函数
def set_up(): """在config层做准备工作""" print("我在config层做准备") def tear_down(): """在config层做准备工作""" print("我在config层清理数据") def output_request(request): """setup,打印请求参数""" print(request) def output_response(response): """teardown,打印响应结果""" print(response.text)
AI 代码解读
再组织api文件,两份:有单个的api及testcase
-
- 单个api
name: 登录接口 base_url: 接口请求地址 variables: expected_status_code: 200 mobile: 你的账号 passwd: 你的密码 request: url: /xxx/xxx/passwordLogin method: POST json: appVersion: 9.0 channel: 1 deviceName: HUAWEI EML-AL00 deviceType: android deviceid: 0795cd72-3e05-40ba-9733-5df1c1fa0970 loginType: 0 mobile: $mobile password: $passwd pushToken: 25b9b066dc939b9863fe9feb3fca654d systemVersion: 8.1.0 zone: 86 validate: - eq: [status_code, $expected_status_code]
AI 代码解读
-
- 测试用例
- config: name: "集合关键字使用" variables: user_agent: 'iOS/10.3' verify: False setup_hooks: - ${set_up()} teardown_hooks: - ${tear_down()} output: - user_agent - test: name: 第一次登录 api: api/login.yml extract: token: content.content.token validate: - eq: ["status_code", 200] output: - token - test: name: 第二次登录 api: api/login.yml setup_hooks: - ${output_request($request)} teardown_hooks: - ${output_response($response)} extract: token: content.content.token validate: - eq: ["status_code", 200] # output无效 output: - token
AI 代码解读
执行看结果,控制台
3.2.4、工程结构
以上涉及的文件在工程结构是:api目录、debugtalk、testcase必须在同级目录;
而在hrun使用手脚架创建的工程结构是分api、testcases、testsuites、.env等,本身独立的api/xxx.yml是可以单独运行的,如何执行testcases层调用到api层呢非得进入testcases才能到且在当前目录有api层?但是为什么testsuites层能调到testcases层再到api层呢?
那么结论就是,在使用共同调用login获取token的testcases,其实是放在testsuite中调用api,然后在传给testcases? 这是错误的,错误的!!!
综上:httprunner框架通过–startproject创建的工程结构是支持api、testcases、testsuites同级调用的,也就是说需要在/根路径<工程>执行testsuites、testcases、api下的yml测试用例文件。
四、httprunner扩展
有时在debugtalk.py中也会使用框架的api类来执行测试用例
- 执行测试用例,可以是目录也可以是文件,也可以是目录和用例的混合:[“path”,“test_file”]
from httprunner.api import HttpRunner runner = HttpRunner( failfast=True, save_tests=True, log_level="INFO", log_file="test.log" ) summary = runner.run(path_or_tests)
AI 代码解读
- 也可以通过调用api生成测试报告,因为响应结果中有html报告中用到的元素
from httprunner import report report_path = report.gen_html_report( summary, report_template="/path/to/custom_report_template", report_dir="/path/to/reports_dir", report_file="/path/to/report_file_path" )
AI 代码解读