httprunner4.x使用(含代码)
1.运用脚手架创建项目
进入项目路径,运行命令,新增一个Httprunner项目
1 | hrp startproject demotest |
运行完成,在目录下可看到如下文件
各文件意义如下(demo就是demotest,只是名称不一样)
脚手架项目有几个有效的测试用例,可以直接编辑直接执行命令 hrp run demotest运行,若命令运行成功,说明Python版本及Httprunner依赖包没有冲突,可正常使用。
2.测试用例有录制的用例和手工编写的用例两种方法
方法(1)录制生成用例
步骤1,导出har文件
通过fiddler/Charles等抓包工具进行抓包,生成har文件(charles导入)
Charles导出会更好用一些
fiddler点击File--Export Sessions--Selected Sessions,选择Httparchive v1.2格式,导出文件到项目目录的 har 文件
步骤2,转化为测试用例文件
httprunner4.x将所有转换功能都集中在 hrp convert一个指令中,通过执行 hrp conver -h可以查询该功能指令的简介和用法。
除了转换成JSON/YAML/pytest类型的文件,Httprunner4.x还支持将HAR包转换成gotest测试用例
执行hrp convert xxx.har --to-pytest命令,会先将xxx.har文件转换成 xxx_test.json文件,然后再将xxx_test.json转化成xxx_test_test.py文件。
hrp convert支持指定目录输出,--output-dir后接测试用例期望输出的目录路径,用于将转换生成的测试用例输出到对应的文件夹中
1 | hrp convert fidd.har - - to - pytest - - output - dir . / cases 输出文件到当前目录下cases文件 |
测试时如果报错WRN skip file expectExtensions=[".json"] path=***.har)
查询了各种原因,根据hrp conver -h查询到的,可能出现在指令问题上
尝试修改指令后,成功!!!!!!!!!!!!!!
1 | hrp convert - - from - har C:\study\httprunner\hruns\demotest\har\fidd.har |
在文件夹中可看到生成的json文件
同理,转换成pytest文件
1 | hrp convert - - from - har C:\study\httprunner\hruns\demotest\har\jen.har - - to - pytest - - output - dir C:\study\httprunner\hruns\demotest\testcases |
执行命令后,生成json和py文件,如下图
步骤3.执行测试用例
httprunner3.x用hrun命令执行,httprunner4.x用 hrp run命令执行
Httprunner4.x也可以用hrun命令执行测试用例文件,但hrp控制台打印日志比较详细,而且hrp可以执行文件夹中的所有测试用例
1 | hrp run jen_test_test.py |
执行测试用例同时生成测试报告,通过hrp run -h可知为 hrp run 文件 -g
进入项目下执行指令(不管在哪个路径下运行,同一根目录下会生成results文件夹)
1 | hrp run jen_test_test.py - g |
运行后,results文件夹里面内含报告
文件html 打开后显示如下
allure报告(安装allure)
https://blog.csdn.net/seanyang_/article/details/129195363
方法(2)手工编写测试用例
1.
在httprunner中,测试用例组织主要基于三个概念:
测试用例集(testsuite):对应一个YAML/JSON/Python文件,包含单个或多个测试用例文件。通俗来将,测试用例集就是「一堆」测试用例。对应地,HttpRunner 除了支持指定单个文件来运行某一测试用例,也支持指定多个文件或指定文件夹来运行一整个测试用例集
测试用例(testcase):对应一个YAML/JSON/Python文件,包含单个或多个测试步骤。
测试步骤(teststep):对应YAML/JSON/Python中 teststeps 下的一个节点,描述单次接口测试的全部内容,包括发起接口请求、解析响应结果、检验结果等。
YAML/json/pytest结构的测试用例,用例整体结构都包含两部分
config:每个测试用例都包含config部分,作为整个测试用例的全局配置项,用于配置用例
teststep:包含测试步骤相关信息,测试用例存在顺序关系,运行时从前往后依次运行各个测试步骤,其中测试步骤可以引用其他测试用例
用例配置项(config)名称 | 含义 |
name(必填) | 用例名称描述,在log和报告中显示 |
verify(非必填) | 客户端是否进行SSL校验(todo) |
base_url(非必填) | 测试用例中的通用HOST,例如http://httprunner.com,若base_url被绑定,测试步骤中的url只能写相对路径 |
headers(非必填) | 定义测试用例级别的请求头 |
environs(非必填) | 配置环境变量(若未指定,则会从.env文件导入) |
variable(非必填) | 定义为全局变量,作用域为整个用例,每个测试步骤都可以引用config variables.测试步骤中step variables优先级别高于config varaibles |
parameters(非必填) | 全局参数,用于实现数据化驱动,作用域为整个用例 |
parameters_setting(非必填) | 配置参数驱动的具体策略 |
think_time(非必填) | 配置思考时间的具体策略、超时时间限制等 |
websocket(非必填) | 配置websocket断开重连的最大次数和间隔等(todo) |
export(非必填) | 导出当前测试用例中的变量 |
weight(非必填) | 性能测试中,分配给当前测试用例的虚拟用户权重 |
path(非必填) | 当前测试用例所在路径(通常不需要手工填写) |
测试步骤类型 | 含义 | 适用的测试步骤 |
name(必填) | 用例名称描述,在log和报告中显示 | |
request(必填) |
用于发起HTTP请求的步骤类型,包含method/url/params/headers/cookie等请求信息 (method和url必填) HTTP的请求方式有GET、POST、HEAD、PUT、DELETE、CONNECT、OPTIONS、TRACE、PATCH,比较常用的请求方式是POST和GET |
|
api(非必填) | 用于引用API的步骤类型 | |
testcase(非必填) | 用于引用其他测试用例的步骤类型 | |
transaction(非必填) | 用于定义一个事务 | |
rendezvous(非必填) | 集合点 | |
think_time(非必填) | 思考时间 | |
WebSocket(非必填) | 用于发起WebSocket请求的步骤类型 | |
variables(非必填) | 局部变量 | 通用 |
setup_hook(非必填) | 前置函数 | request/api/websocket |
teardown_hook(非必填) | 后置函数 | request/api/websocket |
extract(非必填) | 变量提取。参数提取格式,变量名:body.属性名,指从响应体body里提取属性的值 | request/api/websocket |
validate(非必填) | 结果校验 | request/api/websocket |
export(非必填) | 导出变量 | testcase |
代码部分
1213.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | config: name: classinfo variables: {} verify: false teststeps: - name: "getclass" request: method: GET url: http: / / 127.0 . 0.1 : 8080 / api / mgr / sq_mgr / params: action: list_course pagenum: "1" pagesize: "20" headers: Accept: application / json, text / plain, * / * Accept - Encoding: gzip, deflate, br Accept - Language: zh - CN,zh;q = 0.9 Connection: keep - alive Host: 127.0 . 0.1 : 8080 Referer: http: / / 127.0 . 0.1 : 8080 / mgr / ps / mgr / index.html User - Agent: Mozilla / 5.0 (Windows NT 10.0 ; Win64; x64) AppleWebKit / 537.36 (KHTML, like Gecko) Chrome / 101.0 . 0.0 Safari / 537.36 X - CSRFToken: ABjPB9CYXuc0dPy8Wu2hJppDVu1sdhWRrfoWPBM7DimSrMtkHVUAoNAXeWqOIh0d cookies: csrftoken: ABjPB9CYXuc0dPy8Wu2hJppDVu1sdhWRrfoWPBM7DimSrMtkHVUAoNAXeWqOIh0d sessionid: b1g42w3ynatxpphy0fhahpdi7g4pn2vg extract: msg: body.msg cookie: header. Set - Cookie validate: - check: status_code assert : equals expect: 200 msg: assert response status code - eq: [ "body.msg" , "成功" ] |
转化为pytest文件
1 | hrp convert - - from - yaml C:\study\httprunner\yaml\ 1213.yml - - to - pytest - - output - dir C:\study\httprunner\yaml |
运行后生成文件T1213_test_test.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | # NOTE: Generated By HttpRunner v4.3.5 # FROM: 1213_test.json from httprunner import HttpRunner, Config, Step, RunRequest class TestCaseT1213Test(HttpRunner): config = Config( "classinfo" ) teststeps = [ Step( RunRequest( "getclass" ) .get( "http://127.0.0.1:8080/api/mgr/sq_mgr/" ) .with_params( * * { "action" : "list_course" , "pagenum" : "1" , "pagesize" : "20" }) .with_headers( * * { "Accept" : "application/json, text/plain, */*" , "Accept-Encoding" : "gzip, deflate, br" , "Accept-Language" : "zh-CN,zh;q=0.9" , "Connection" : "keep-alive" , "Host" : "127.0.0.1:8080" , "Referer" : "http://127.0.0.1:8080/mgr/ps/mgr/index.html" , "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36" , "X-CSRFToken" : "ABjPB9CYXuc0dPy8Wu2hJppDVu1sdhWRrfoWPBM7DimSrMtkHVUAoNAXeWqOIh0d" , } ) .with_cookies( * * { "csrftoken" : "ABjPB9CYXuc0dPy8Wu2hJppDVu1sdhWRrfoWPBM7DimSrMtkHVUAoNAXeWqOIh0d" , "sessionid" : "b1g42w3ynatxpphy0fhahpdi7g4pn2vg" , } ) .extract() .with_jmespath( "header.Set-Cookie" , "cookie" ) .with_jmespath( "body.msg" , "msg" ) .validate() .assert_equal( "status_code" , 200 , "assert response status code" ) .assert_equal( "body.msg" , "成功" ) ), ] if __name__ = = "__main__" : TestCaseT1213Test().test_start() |
11.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | { "config" : { "name" : "classinfo" }, "teststeps" : [ { "name" : "getclass" , "request" : { "method" : "GET" , "url" : "http://127.0.0.1:8080/api/mgr/sq_mgr/" , "params" : { "action" : "list_course" , "pagenum" : "1" , "pagesize" : "20" }, "headers" : { "Accept" : "application/json, text/plain, */*" , "Accept-Encoding" : "gzip, deflate, br" , "Accept-Language" : "zh-CN,zh;q=0.9" , "Connection" : "keep-alive" , "Host" : "127.0.0.1:8080" , "Referer" : "http://127.0.0.1:8080/mgr/ps/mgr/index.html" , "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36" , "X-CSRFToken" : "ABjPB9CYXuc0dPy8Wu2hJppDVu1sdhWRrfoWPBM7DimSrMtkHVUAoNAXeWqOIh0d" , "sec-ch-ua-platform" : "\"Windows\"" }, "cookies" : { "csrftoken" : "ABjPB9CYXuc0dPy8Wu2hJppDVu1sdhWRrfoWPBM7DimSrMtkHVUAoNAXeWqOIh0d" , "sessionid" : "b1g42w3ynatxpphy0fhahpdi7g4pn2vg" } }, "validate" : [ { "check" : "status_code" , "assert" : "equals" , "expect" : 200 , "msg" : "assert response status code" }, { "check" : "body.msg" , "assert" : "equals" , "expect" : "成功" , "msg" : "assert response body msg" } ] } ] } |
转化为pytest文件
1 | hrp convert - - from - json C:\study\httprunner\json\ 11.json - - to - pytest - - output - dir C:\study\httprunner\json |
运行后生成文件T11_test_test.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | # NOTE: Generated By HttpRunner v4.3.5 # FROM: 11_test.json from httprunner import HttpRunner, Config, Step, RunRequest class TestCaseT11Test(HttpRunner): # 11为原json文件的文件名 config = Config( "classinfo" ) teststeps = [ Step( RunRequest( "getclass" ) .get( "http://127.0.0.1:8080/api/mgr/sq_mgr/" ) .with_params( * * { "action" : "list_course" , "pagenum" : "1" , "pagesize" : "20" }) .with_headers( * * { "Accept" : "application/json, text/plain, */*" , "Accept-Encoding" : "gzip, deflate, br" , "Accept-Language" : "zh-CN,zh;q=0.9" , "Connection" : "keep-alive" , "Host" : "127.0.0.1:8080" , "Referer" : "http://127.0.0.1:8080/mgr/ps/mgr/index.html" , "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36" , "X-CSRFToken" : "ABjPB9CYXuc0dPy8Wu2hJppDVu1sdhWRrfoWPBM7DimSrMtkHVUAoNAXeWqOIh0d" , "sec-ch-ua-platform" : '"Windows"' , } ) .with_cookies( * * { "csrftoken" : "ABjPB9CYXuc0dPy8Wu2hJppDVu1sdhWRrfoWPBM7DimSrMtkHVUAoNAXeWqOIh0d" , "sessionid" : "b1g42w3ynatxpphy0fhahpdi7g4pn2vg" , } ) .validate() .assert_equal( "status_code" , 200 , "assert response status code" ) .assert_equal( "body.msg" , "成功" , "assert response body msg" ) ), ] if __name__ = = "__main__" : TestCaseT11Test().test_start() |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?