文章目录
说明:此文档适用于全新发布的 HttpRunner 3.x 版本
httprunner 2.x请参考文章:https://blog.csdn.net/adorable_/article/details/110824819
一. httprunner简介
1.1 简介
HttpRunner是一款面向HTTP(s)协议的通用测试框架,只需编写维护一份 测试脚本,即可实现自动化测试、性能测试、持续集成等多种测试需求。
1.2 参考资料
github地址:https://github.com/HttpRunner/HttpRunner
3.x用户手册:https://docs.httprunner.org/user/gen_tests/
1.3 框架的优点
- 继承 Requests 的全部特性,轻松实现 HTTP(S) 的各种测试需求
- 测试用例与代码分离,采用YAML/JSON的形式描述测试场景,保障测试用例具备可维护性
- 测试用例支持分层机制,充分实现测试用例的复用
- 测试用例支持参数化和数据驱动机制
- 测试请求支持完善的hook机制
- 使用 skip 机制实现对测试用例的分组执行控制
- 使用 jmespath,提取和验证 json 响应从未如此简单
- 使用 pytest,数百个插件可供使用
- 支持热加载机制,在文本测试用例(debugtalk.py)中轻松实现复杂的动态计算逻辑
- 基于 HAR 实现接口录制和用例生成功能(har2case)
- 结合 Locust 框架,无需额外的工作即可实现分布式性能测试
- 执行方式采用 CLI 调用,可与 Jenkins 等持续集成工具完美结合
- 测试结果统计报告简洁清晰,附带详尽统计信息和日志记录
- 采用 allure 报告,可以生成美观且强大的测试报告
- 具有可扩展性,便于扩展实现 Web 平台化(HttpRunnerManager)
二. 安装
2.1 安装命令
pip install httprunner==3.1.4
2.2 检查是否安装成功
如果 HttpRunner 安装成功,有 4 个命令可用:
- httprunner:核心命令,可以使用 HttpRunner 的所有命令
- hrun:httprunner run 命令的别名,运行 YAML/JSON/pytest 格式的测试用例
- hmake:httprunner make 命令的别名,将 YAML/JSON 格式的 testcases 转换成 pytest 格式的测试用例
- har2case:httprunner har2case 命令的别名,将 HAR 文件转换为 YAML/JSON 格式的测试用例
查看 HttpRunner 版本:
hrun -V
3.1.4
查看所有可用的命令:
三. 录制接口请求
如果不知道如何去写单独api的自动化脚本,那么可以通过录制功能去实现,首先下载pip install har2case
,然后通过fiddler去抓取对应的接口,选中对应的接口,点击左上角的File—>Export Sessions—>(可以选择导出选中的也可以导出所有),然后导出成HTTPArchive v1.2,选中这个,然后导出保存为demo.har
再用以下命令转换成测试脚本
3.1 生成pytest测试脚本:
获取.har文件后,可以使用内置命令har2case将其转换为 HttpRunner 测试用例。
har2case 命令帮助:
(hrun3) F:\httprunner项目\demo>har2case -h
usage: har2case har2case [-h] [-2y] [-2j] [--filter FILTER] [--exclude EXCLUDE] [har_source_file]
positional arguments:
har_source_file Specify HAR source file # 指定 .har 源文件
optional arguments:
-h, --help show this help message and exit # 显示此帮助信息并退出
-2y, --to-yml, --to-yaml
Convert to YAML format, if not specified, convert to pytest format by default. # 转换为 YAML 格式的用例,如果你没有特殊指定,默认转化为 pytest 格式的用例
-2j, --to-json Convert to JSON format, if not specified, convert to pytest format by default. # 转换为 JSON 格式的用例,如果你没有特殊指定,默认转化为 pytest 格式的用例
--filter FILTER Specify filter keyword, only url include filter string will be converted. # 指定过滤关键字,只有包含过滤字符串的 url 的 API 才会被转换
--exclude EXCLUDE Specify exclude keyword, url that includes exclude string will be ignored, multiple keywords
can be joined with '|' # 指定忽略关键字,如果 url 包含该关键字,则会被忽略,如果需要过滤多个关键字,使用`|`(竖线)分隔
默认生成pytest测试脚本:
har2case demo.har
可以查看到Python文件内容:
# NOTE: Generated By HttpRunner v3.1.4
# FROM: demo.har
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
class TestCaseDemo(HttpRunner):
config = Config("testcase description").verify(False)
teststeps = [
Step(
RunRequest("/WebServices/MobileCodeWS.asmx/getMobileCodeInfo")
.post(
"http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx/getMobileCodeInfo"
)
.with_headers(
**{
"Host": "ws.webxml.com.cn",
"Connection": "keep-alive",
"Content-Length": "30",
"Cache-Control": "max-age=0",
"Upgrade-Insecure-Requests": "1",
"Origin": "http://ws.webxml.com.cn",
"Content-Type": "application/x-www-form-urlencoded",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"Referer": "http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?op=getMobileCodeInfo",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9",
}
)
.with_data({"mobileCode": "18740817426", "userID": ""})
.validate()
.assert_equal("status_code", 200)
.assert_equal('headers."Content-Type"', "text/xml; charset=utf-8")
),
]
if __name__ == "__main__":
TestCaseDemo().test_start()
因为httprunner封装了pytest,所有既可以用hrun去运行,也可以用pytest去运行。
hrun运行:
pytest运行:
3.2 生成yml文件
har2case -2y demo.har
可以查看到yml文件内容:
config:
name: testcase description
variables: {}
verify: false
teststeps:
- name: /WebServices/MobileCodeWS.asmx/getMobileCodeInfo
request:
data:
mobileCode: '18240887426'
userID: ''
headers:
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: max-age=0
Connection: keep-alive
Content-Length: '30'
Content-Type: application/x-www-form-urlencoded
Host: ws.webxml.com.cn
Origin: http://ws.webxml.com.cn
Referer: http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?op=getMobileCodeInfo
Upgrade-Insecure-Requests: '1'
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36
method: POST
url: http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx/getMobileCodeInfo
validate:
- eq:
- status_code
- 200
- eq:
- headers.Content-Type
- text/xml; charset=utf-8
3.3 生成json文件
har2case -2j demo.har
可以查看到json文件内容:
{
"config": {
"name": "testcase description",
"variables": {},
"verify": false
},
"teststeps": [
{
"name": "/WebServices/MobileCodeWS.asmx/getMobileCodeInfo",
"request": {
"url": "http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx/getMobileCodeInfo",
"method": "POST",
"headers": {
"Host": "ws.webxml.com.cn",
"Connection": "keep-alive",
"Content-Length": "30",
"Cache-Control": "max-age=0",
"Upgrade-Insecure-Requests": "1",
"Origin": "http://ws.webxml.com.cn",
"Content-Type": "application/x-www-form-urlencoded",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"Referer": "http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?op=getMobileCodeInfo",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9"
},
"data": {
"mobileCode": "18240887426",
"userID": ""
}
},
"validate": [
{
"eq": [
"status_code",
200
]
},
{
"eq": [
"headers.Content-Type",
"text/xml; charset=utf-8"
]
}
]
}
]
}
以上转换出的pytest、yaml、json这3种格式的文件效果都是一样的,用hrun都可以运行,但是用pytest执行的话只可以运行.py的文件。
四. 脚手架快速生成项目
在软件开发上(bai当然也包括前端开发)的脚手架指的就是:有人帮你把这个开发过程中要用到的工具、环境都配置好了,你就可以方便地直接开始做开发,专注你的业务,而不用再花时间去配置这个开发环境,这个开发环境就是脚手架。
4.1 快速生成项目
httprunner startproject 项目名
4.2 项目框架
- debugtalk.py 放置在项目根目录下(借鉴了pytest的conftest文件的设计)
- .env 放置在项目根目录下,可以用于存放一些环境变量
- reports 文件夹:存储 测试报告
- testcases 用于存放测试用例
- har 可以存放录制导出的.har文件
五. 框架结构
5.1 httprunner中的三种case形式
HttpRunner v3.x支持三种测试用例格式pytest,YAML和JSON。强烈建议以pytest格式而不是以前的YAML/JSON格式编写和维护测试用例。
相互转换格式关系如下图所示:
上图是来自官方的用例格式关系图,可以看出来,httprunner再对于第三方导出的har文件进行了转换处理,有的人喜欢转换成json,有的人喜欢转换成yaml。但是最终,还是通过解析json格式的文件,生成pytest的python文件。
5.2 用例结构
特性:
- 每个testcase都是HttpRunner的子类
- 必须有两个类属性:config和teststeps。
- 单个teststeps列表中的单个Step内部通过链式调用(RunRequest().get().with_params().with_headers().with_cookies().validate().assert_equal())
知识点:
- config:配置测试用例级设置,包括基础url、验证、变量、导出。
- teststeps:teststep的列表(list[Step]),每个步骤对应于一个API请求,也可以调用另一个testcase。此外,还支持variables/extract/validate/hooks机制来创建极其复杂的测试场景。
- 链调用:可以看到一个case的请求,经过了各个环节的调用,这也是httprunner 3.x版本一大亮点。现在的ide编辑器越来越强大,比如你使用pycharm的话,都不用你怎么记忆用例的格式,顺手就…(点)出来了,这或许也是官方推荐使用pytest的另一个原因吧。
六. 测试用例-config
每个测试用例都应该有一个config部分,您可以在其中配置测试用例级别的设置。
6.1 name(必填)
指定测试用例名称。这将显示在执行日志和测试报告中。
运行后,在debug日志里,可以看的用例名称被展示出来。
6.2 base_url(可选)
指定SUT的通用架构和主机部分,例如https://postman-echo.com。如果base_url指定,则teststep中的url只能设置相对路径部分。如果要在不同的SUT环境之间切换,这将特别有用。
6.3 variables(可选)
指定测试用例的公共变量。每个测试步骤都可以引用未在步骤变量中设置的配置变量。换句话说,步骤变量比配置变量具有更高的优先级。
6.4 verify (可选)
指定是否验证服务器的TLS证书。如果我们想记录测试用例执行的HTTP流量,这将特别有用。通常设置为False,当请求https请求时,就会跳过验证。如果你运行时候发现抛错SSLError,可以检查一下是不是verify没传,或者设置了True。
SSLError(SSLCertVerificationError(1,'[SSL:CERTIFICATE_VERIFY_FAILED]证书验证失败:证书链中的自签名证书(_ssl.c:1076)')
6.5 export (可选)
指定导出的测试用例会话变量。将每个测试用例视为一个黑盒,config variables是输入部分,而configexport是输出部分。特别是,当一个测试用例在另一个测试用例的步骤中被引用,并且将被提取一些会话变量以在后续测试步骤中使用时,则提取的会话变量应在配置export部分中进行配置。将测试用例的某些变量指定为全局变量。(PS:不配置export在另一个引用类中进行该累的变量调用时,直接export也是可以的,最好还是配置一下)。
七. 测试用例-teststep
7.1 对于测试步骤而言
7.1.1 RunRequest(name)
RunRequest 在一个步骤中用于向API发出请求,并对响应进行一些提取或验证。
7.1.2 name
RunRequest 的参数用于指定测试步骤名称,该名称将显示在执行日志和测试报告中。
7.1.3 .with_variables
指定测试步骤变量。每个步骤的变量都是独立的,因此,如果要在多个步骤中共享变量,则应在配置变量中定义变量。此外,步骤变量将覆盖配置变量中具有相同名称的变量。(PS:注意参数传递的格式使用**{},使用关键字参数解包的方式进行参数传递给with_variables),参数引用使用"变量名, 如果是函数引用使用{函数名()}"
7.1.4 .method(url)
指定HTTP方法和SUT的URL。这些对应于method和url参数requests.request。
如果base_url在config中设置,则url只能设置相对路径部分。如果在Config中设置了baseurl,method
中只能设置相对路径,可选参数为get/post/put/delete/等。
7.1.5 .with_params
指定请求网址的查询字符串。这对应于的params参数requests.request。
7.1.6 .with_headers
为请求指定HTTP标头。这对应于的headers参数requests.request。
7.1.7 .with_cookies
指定HTTP请求cookie。这对应于的cookies参数requests.request。
7.1.8 .with_data
指定HTTP请求正文。这对应于的data参数requests.request。
7.1.9 .with_json
在json中指定HTTP请求正文。这对应于的json参数requests.request。
7.1.10 .extract(数据提取)
.with_jmespath:使用jmespath提取JSON响应主体。
with_jmespath(jmes_path:文字,var_name:文字)
- jmes_path:jmespath表达式,有关更多详细信息,请参考 JMESPath 教程
- var_name:存储提取值的变量名,可以在后续测试步骤中引用它
7.1.12 .validate
.assert_XXX:使用jmespath提取JSON响应主体并使用期望值进行验证。
assert_XXX(jmes_path:文本,期望值:任何,消息:文本=“”)
- jmes_path:jmespath表达式,有关更多详细信息,请参考JMESPath教程
- expected_value:指定的期望值,变量或函数引用也可以在此处使用
- 消息(可选):用于指示断言错误的原因
常见比较方式:
- equals: 是否相等
- less_than: 小于
- less_than_or_equals: 小于等于
- greater_than_or_equals: 大于等于
- not_equals: 不等于
- string_equals: 字符串相等
- length_equals: 长度相等
- length_greater_than: 长度大于
- length_greater_than_or_equals: 长度大于等于
- length_less_than: 长度小于
- length_less_than_or_equals: 长度小于等于
- contains: 预期结果是否被包含在实际结果中
- contained_by: 实际结果是否被包含在预期结果中
- type_match: 类型是否匹配
- regex_match: 正则表达式是否匹配
- startswith: 字符串是否以什么开头
- endswith: 字符串是否以什么结尾
7.2 引用其他case的情况
7.2.1 RunTestCase(name)
RunTestCase 在一个步骤中用于引用另一个测试用例调用。
7.2.2 name
RunTestCase 的参数用于指定测试步骤名称,该名称将显示在执行日志和测试报告中。
7.2.3 .with_variables
指定测试步骤变量。每个步骤的变量都是独立的,因此,如果要在多个步骤中共享变量,则应在配置变量中定义变量。此外,步骤变量将覆盖配置变量中具有相同名称的变量。
7.2.4 .call
指定引用的测试用例类。你在引用另一个测试用例的step中的参数时,需要先指定引用的测试用例类。
7.2.5 .export
指定会话变量名称以从引用的测试用例中导出。导出的变量可以通过后续测试步骤step进行引用。导出的是step中的jmespath提取的变量,export之后,这个变量是全局变量,但是不能再confg中进行设置,因为测试类的引用是在step中进行的,而类的初始化是先初始化config,然后初始化teststeps,所以参数的传递在step之间。
八. 参数化
参数化有三种方式,具体内容如下:
8.1 parameters 字段
第一种,使用httprunner改造过的pytest参数化,通过parameters这个字段去引用
@pytest.mark.parametrize("param",Parameters(
{
"first": ["first", "second"],
"second": ['random string','string number']
}
))
8.2 读取csv文件
第二种,通过csv文件httprunner可以读取同目录下的csv文件
#代码中如此书写
@pytest.mark.parametrize("param", Parameters(
{"username-password": "${parameterize(data.csv)}"}
))
# 使用csv文件进行参数化的时候,Parameters的键里每一个-代表一个参数分割。例如username 和 password是两个参数
# 相应的,csv文件中的列名应该和参数名一致
数据文件
username,password
name1,1212
name2,4545
8.3 debugtalk.py文件中的函数
第三种,通过debugtalk.py进行构建
代码中这样调用:
@pytest.mark.parametrize("param", Parameters(
{"username": "${get_username()}"}
))
#以上方式是使用debugtalk中的方法返回值
在debugtalk里面定义:
def get_username():
return [
{"username": "111111"},
{"username": "222222"},
{"username": "333333"},
{"username": "444444"},
{"username": "555555"},
{"username": "666666"},
]
九. 测试报告
3.x版本httprunner可以使用两种测试报告(本质上是用的pytest)
9.1 pytest-html和pytest普通用法一致
HTTPrunner 安装之后自带 pytest-html插件,当你想生成 HTML 测试报告时,可以添加命令参数–html。
pytest case文件.py --html=report.html
通过–html生成的 HTML 报告包含了多个文件夹,如果你要创建一个单独的 HTML 文件,可以添加另一个命令参数–self-contained-html。
pytest case文件.py --html=report.html --self-contained-html
9.2 使用allure需要安装httprunner插件
安装:pip install httprunner[allure]
执行命令:
pytest case名称.py --alluredir ./预计存放数据的路径
allure generate 数据存放路径 -o 报告输出路径 --clean
- –alluredir=DIR:生成 allure 报告到指定目录
- –clean-alluredir: 如果指定目录已存在则清理该文件夹
- –allure-no-capture:不要将 pytest 捕获的日志记录(logging)、标准输出(stdout)、标准错误(stderr)附加到报告中