httprunner3.x 测试用例编写(python)
httprunner是采用yaml/json文件编写测试用例,然后运行,但是3.x后引入了pytest框架,我们即便使用yaml和json文件,最后的执行也是转成.py文件执行。
所以3.x版本推荐直接编写代码,相对来说,代码编写比文件编写要好太多,因为httprunner3.x的语法关联性特别强;以下就是针对代码编写用的一些常用操作。
附上示例代码:
from httprunner import (HttpRunner, Config, Step, RunRequest, RunTestCase) class TestCaseLogin(HttpRunner): config = ( Config("login") .variables( **{"user_name": "${ENV(USERNAME)}", "password": "${ENV(PASSWORD)}" } ) .base_url("${ENV(HOSTURL)}") .verify(False) # .export(*["foo3"]) ) teststeps = [ Step( RunRequest('login') .with_variables(**{'length': 32, 'status_code': 201, 'status': 1}) .post('/client/user/auth') .with_headers(**{"Content-Type": "application/json"}) .with_json({"scenario": "client", "company_id": 5940, "user_name": "$user_name", "password": "$password", "device_type": "2", "device": ""}) .extract() .with_jmespath("body.data.token", "token") .validate() .assert_equal('status_code', '$status_code', '断言失败') .assert_equal('body.status', '$status', '断言失败') .assert_length_equal('body.data.token', '$length', '断言失败') ) ] if __name__ == '__main__': TestCaseLogin().test_start()
config部分:
config = ( Config("login") .variables( **{"user_name": "${ENV(USERNAME)}", "password": "${ENV(PASSWORD)}" } ) .base_url("${ENV(HOSTURL)}") .verify(False) # .export(*["foo3"]) )
Config(): 设置名称,也就是name,它是必填的
- .verify(): 针对https接口,忽略证书的操作,放布尔值,全局变量
- .base_url():是放请求地址的,也就是域名, 全局变量
- .variables():设置变量,可在此处设置全局变量,用于下面的用例引用它
- .export(): 提取关联参数,全局变量

注意:Config()中设置的均为全局变量,整个.py文件中都可以引用的
teststeps部分:
teststeps = [ Step( RunRequest('login'). .with_variables(**{'length': 32, 'status_code': 201, 'status': 1}) .post('/client/user/auth') .with_headers(**{"Content-Type": "application/json"}) .with_json({"scenario": "client", "company_id": 5940, "user_name": "$user_name", "password": "$password", "device_type": "2", "device": ""}) .extract() .with_jmespath("body.data.token", "token") .validate() .assert_equal('status_code', '$status_code', '断言失败') .assert_equal('body.status', '$status', '断言失败') .assert_length_equal('body.data.token', '$length', '断言失败') ) ]

RunRequest():设置名称,也就是name,它是必填的,设置完它后,才能引下面的一些方法
- .with_variables():设置局部变量,个人建议你可以把接口一些预期结果放在这里
- .post()/put/get/options/delete/head/patch:接口的请求方式;设置好请求方式后,再就可以设置接口的一系列信息
| 请求方式中的方法 | 注释信息 |
| .with_headers() | 设置头部信息 |
| .with_json() | 放json请求数据 |
| .with_params() | 针对跟在url后面的参数 |
| .with_data() | 放data请求数据 |
| .set_timeout() | 设置超时时间 |
| .set_verify() | 针对https,忽略证书 |
| .with_cookies() | 设置cokkies信息 |
| .set_allow_redirects() | 重定向,传布尔型值 |

.extract():引入提取参数方法
- .with_jmespath(“body.data.token”, “token”)
栗子:.with_jmespath(“body.data.token”, “token”)

.validate():引入断言校验方法
- .assert_equal() # 断言相等
栗子: .assert_equal(‘status_code’, ‘$status_code’, ‘断言失败’)

- equal: 等于
- contained_by: 实际结果是否被包含在预期结果中
- contains: 预期结果是否被包含在实际结果中
- endswith: 以…结尾
- greater_or_equals: 大于等于
- greater_than: 大于
- length_equal: 长度等于
- length_greater_or_equals: 长度大于等于
- length_greater_than: 长度大于
- length_less_or_equals: 长度小于等于
- length_less_than: 长度小于
- less_or_equals: 小于等于
- less_than: 小于
- not_equal: 不等于
- regex_match: 字符串是否符合正则表达式匹配规则
- startswith: 以…开头
- string_equals: 字符串相等
- type_match: 类型是否匹配
teststeps列表中的Setp可以设置多个,针对业务的接口处理起来是比较方便的:
from httprunner import (HttpRunner, Config, Step, RunRequest, RunTestCase) class TestCaseLogin(HttpRunner): config = ( Config("login") .variables( **{"user_name": "${ENV(USERNAME)}", "password": "${ENV(PASSWORD)}" } ) .base_url("${ENV(HOSTURL)}") .verify(False) # .export(*["foo3"]) ) teststeps = [ Step( RunRequest('login') .with_variables(**{'length': 32, 'status_code': 201, 'status': 1}) .post('/client/user/auth') .with_headers(**{"Content-Type": "application/json"}) .with_json({"scenario": "client", "company_id": 5940, "user_name": "$user_name", "password": "$password", "device_type": "2", "device": ""}) .extract() .with_jmespath("body.data.token", "token") .validate() .assert_equal('status_code', '$status_code', '断言失败') .assert_equal('body.status', '$status', '断言失败') .assert_length_equal('body.data.token', '$length', '断言失败') ), Step( RunRequest('index') .with_variables(**{'status_code': 200, 'status': 1}) .get('/client/user/index') .with_headers(**{"Content-Type": "application/json", 'token': '$token'}) .extract() .validate() .assert_equal('body.status', '$status', '断言失败') .assert_equal('status_code', '$status_code', '断言失败') .assert_equal('body.data.user_info.author_name', '$user_name', '断言失败') ) ] if __name__ == '__main__': TestCaseLogin().test_start()
需要注意的是:下个Step中的的请求需要上个Setp中的数据,在上个个Setp中使用 .with_jmespath()提取后做下数据关联即可。
直接使用pytest命令运行 pytest -v -s testcase_student_login_test.py
F:\TESTING\apiWebStudent\demo\testcases>pytest -v -s testcase_student_login_test.py ================================================================================= test session starts ================================================================================= rootdir: F:\TESTING\apiWebStudent\demo\testcases plugins: allure-pytest-2.8.24, cov-2.8.1, emoji-0.2.0, forked-1.3.0, html-2.1.1, metadata-1.11.0, rerunfailures-9.1.1, xdist-2.1.0 collected 1 item testcase_student_login_test.py::TestCaseLogin::test_start 2021-03-24 20:09:42.844 | INFO | httprunner.loader:load_dot_env_file:127 - Loading environment variables from F:\TESTING\a piWebStudent\demo\.env 2021-03-24 20:09:42.845 | DEBUG | httprunner.utils:set_os_environ:33 - Set OS environment variable: USERNAME 2021-03-24 20:09:42.846 | DEBUG | httprunner.utils:set_os_environ:33 - Set OS environment variable: PASSWORD 2021-03-24 20:09:42.847 | DEBUG | httprunner.utils:set_os_environ:33 - Set OS environment variable: HOSTURL 2021-03-24 20:09:42.855 | INFO | httprunner.runner:test_start:451 - Start to run testcase: login, TestCase ID: af0ab4dd-726d-40fe-bb59-07aa640ddde1 2021-03-24 20:09:42.858 | INFO | httprunner.runner:__run_step:292 - run step begin: login >>>>>> 2021-03-24 20:09:43.072 | DEBUG | httprunner.client:request:186 - client IP: 10.10.12.173, Port: 52360 2021-03-24 20:09:43.074 | DEBUG | httprunner.client:request:194 - server IP: 10.10.50.86, Port: 443 2021-03-24 20:09:43.076 | DEBUG | httprunner.client:log_print:40 - ================== request details ================== method : POST url : https://api-ss4.9second.com/user/auth headers : { "User-Agent": "python-requests/2.25.0", "Accept-Encoding": "gzip, deflate", "Accept": "*/*", "Connection": "keep-alive", "Content-Type": "application/json", "HRUN-Request-ID": "HRUN-af0ab4dd-726d-40fe-bb59-07aa640ddde1-782860", "Content-Length": "124" } cookies : {} body : { "scenario": "client", "company_id": 5940, "user_name": "account666", "password": "000000", "device_type": "2", "device": "" } 2021-03-24 20:09:43.078 | DEBUG | httprunner.client:log_print:40 - ================== response details ================== status_code : 201 headers : { "Server": "openresty/1.15.8.2", "Date": "Wed, 24 Mar 2021 12:09:13 GMT", "Content-Type": "application/json; charset=UTF-8", "Transfer-Encoding": "chunked", "Connection": "keep-alive", "Strict-Transport-Security": "max-age=15724800; includeSubDomains", "X-Powered-By": "PHP/7.3.9", "Location": "http://api-ss4.9second.com/user/auth/view?id=id", "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "X-Requested-With, Token", "Access-Control-Allow-Methods": "GET,POST,OPTIONS" } cookies : {} encoding : UTF-8 content_type : application/json; charset=UTF-8 body : { "status": 1, "data": { "is_set": 0, "id": 66666, "token": "d12d1f33caead6ca5898080acaa9cab0", "user_type": 0, "company_id": 4444, "is_default_avatar": 1 }, "errMsg": "", "errCode": 0, "script": { "start_time": 1616587753.136119, "end_time": 1616587753.258823, "duration": "122.68806" } } 2021-03-24 20:09:43.080 | INFO | httprunner.client:request:218 - status_code: 201, response_time(ms): 212.09 ms, response_length: 0 bytes 2021-03-24 20:09:43.081 | INFO | httprunner.response:extract:176 - extract mapping: {'token': 'd12d1f33caead6ca5898080acaa9cab0'} 2021-03-24 20:09:43.082 | INFO | httprunner.response:validate:246 - assert status_code equal 201(int) ==> pass 2021-03-24 20:09:43.087 | INFO | httprunner.response:validate:246 - assert body.status equal 1(int) ==> pass 2021-03-24 20:09:43.088 | INFO | httprunner.response:validate:246 - assert body.data.token length_equal 32(int) ==> pass 2021-03-24 20:09:43.089 | INFO | httprunner.runner:__run_step:304 - run step end: login <<<<<< 2021-03-24 20:09:43.093 | INFO | httprunner.runner:__run_step:292 - run step begin: index >>>>>> 2021-03-24 20:09:43.266 | DEBUG | httprunner.client:request:186 - client IP: 10.10.12.173, Port: 52360 2021-03-24 20:09:43.268 | DEBUG | httprunner.client:request:194 - server IP: 10.10.50.86, Port: 443 2021-03-24 20:09:43.270 | DEBUG | httprunner.client:log_print:40 - ================== request details ================== method : GET url : https://api-ss4.9second.com/user/index headers : { "User-Agent": "python-requests/2.25.0", "Accept-Encoding": "gzip, deflate", "Accept": "*/*", "Connection": "keep-alive", "Content-Type": "application/json", "token": "d12d1f33caead6ca5898080acaa9cab0", "HRUN-Request-ID": "HRUN-af0ab4dd-726d-40fe-bb59-07aa640ddde1-783094" } cookies : {} body : None 2021-03-24 20:09:43.272 | DEBUG | httprunner.client:log_print:40 - ================== response details ================== status_code : 200 headers : { "Server": "openresty/1.15.8.2", "Date": "Wed, 24 Mar 2021 12:09:13 GMT", "Content-Type": "application/json; charset=UTF-8", "Transfer-Encoding": "chunked", "Connection": "keep-alive", "Vary": "Accept-Encoding", "Strict-Transport-Security": "max-age=15724800; includeSubDomains", "X-Powered-By": "PHP/7.3.9", "Set-Cookie": "_csrf=a92c9384d740c42cc66dde5823c262f27b5d9712fa89a505f64daaaef1842592a%3A2%3A%7Bi%3A0%3Bs%3A5%3A%22_csrf%22%3Bi%3A1%3Bs%3A32%3A%225PpYkG4hYa-BH_zbG-olbkCNSgG17UYB%2 2%3B%7D; path=/; HttpOnly", "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "X-Requested-With, Token", "Access-Control-Allow-Methods": "GET,POST,OPTIONS", "Content-Encoding": "gzip" } cookies : { "_csrf": "a92c9384d740c42cc66dde5823c262f27b5d9712fa89a505f64daaaef1842592a%3A2%3A%7Bi%3A0%3Bs%3A5%3A%22_csrf%22%3Bi%3A1%3Bs%3A32%3A%225PpYkG4hYa-BH_zbG-olbkCNSgG17UYB%22%3B%7D" } encoding : UTF-8 content_type : application/json; charset=UTF-8 body : { "status": 1, "data": { "user_info": { "avatar": "https://f3-xz.veimg.cn/ss/v5/images/avatar.png", "author_name": "account666", "area_num": "86", "mobile": "17744444444", "is_bind_weixin": 0, "gender": 1, "company_name": "\u1d4b\u8bd6\u4f01\u7e1a", "company_logo": "https://file-xz.veimg.cn/lms/uploads/2020/09/16003904176464.jpg", "store_name": "", "department_name": "\u10e8\u95e8\u4e09\u90e8\u95e8\u5e09\u90e8\u95e8\u4e09\u90e8\u45e8\u4e09", "post_name": "\u1ad8\u7ea7\u6d4b\u2bd5\u0de5\u7a0b\u5e08", "entry_time": "", "nickname": "", "is_set": 1, "is_confirm_mobile": 0, "notify_count": "0", "user_id": 444000, "is_course_class": false, "user_type": 0, "school_name": "\u6i4b\u8bd5\u5f01\u4e1a", "score_level": "\u5214\u5f3a\u6752\u94dc", "is_authentication": 0 }, "stat_data": { "learn_duration": 0, "learn_course": 0, "credit": 0, "rank": 42 }, "holidays_content": "", "permission": [], "is_show_rank": 0 }, "errMsg": "", "errCode": 0, "script": { "start_time": 1616587753.310073, "end_time": 1616587753.462878, "duration": "152.79102" } } 2021-03-24 20:09:43.274 | INFO | httprunner.client:request:218 - status_code: 200, response_time(ms): 172.13 ms, response_length: 0 bytes 2021-03-24 20:09:43.275 | INFO | httprunner.response:validate:246 - assert body.status equal 1(int) ==> pass 2021-03-24 20:09:43.277 | INFO | httprunner.response:validate:246 - assert status_code equal 200(int) ==> pass 2021-03-24 20:09:43.278 | INFO | httprunner.response:validate:246 - assert body.data.user_info.author_name equal account35(str) ==> pass 2021-03-24 20:09:43.279 | INFO | httprunner.runner:__run_step:304 - run step end: index <<<<<< 2021-03-24 20:09:43.281 | INFO | httprunner.runner:test_start:460 - generate testcase log: F:\TESTING\apiWebStudent\demo\logs\af0ab4dd-726d-40fe-bb59-07aa640ddde1.run.log PASSED ============================================================================ 1 passed in 0.79s =============================================================================
从上面的运行结果来看,我们可以清晰的看到接口的请求参数和返回数据、断言反馈及提取的关联参数等。
你也可以直接:hrun testcase_student_login_test.py 或者 hrun testcase_student_login_test.py -v -s 命令,可自行实操下,你会发现第一命令显示的数据就是运行成功,第二个命令运行后和上面使用pytest命令显示的是一致的。
以上总结或许能帮助到你,或许帮助不到你,但还是希望能帮助到你,如有疑问、歧义,评论区留言会及时修正发布,谢谢!
–
未完,待续…
一直都在努力,希望您也是!
转载请附带原文链接 ( https://www.cnblogs.com/lifeng0402/articles/14575862.html ),否则追究法律责任,谢谢!


浙公网安备 33010602011771号