目录
注:本文使用的httprunner v4.3.0版本与v3.X版本的使用略有不同
1、httprunner概述
- HttpRunner 是一款面向 HTTP(S) 协议的通用测试框架,继承request的全部特性,只需编写维护一份 YAML/JSON 脚本,即可实现自动化测试、性能测试、线上监控、持续集成等多种测试需求。
1.1、httprunner的优点
- 可使用抓包工具导入请求为har文件,在httprunner内支持har文件转换成json、yaml、pytest文件 。
- httprunner集成了loguru日志模块,添加日志更加方便。
- httprunner集成了locust模块,支持了性能测试:
- httprunner支持响应结果参数提取,接口参数关联。
- 生成脚手架功能
- httprunner集成了pytest框架,支持pytest的所有命令
2、httprunner的安装
- 说明:以下命令是安装官网最新版本的编译工具:
- 此处安装的是一个exe文件,v4版本后httprunner可作为一个外部工具使用,可用于生成脚手架,用例执行,用例转换,要在具体的代码中使用还需重新安装httprunner库
pip install httprunner
- 安装指定版本
pip install httprunner==4.3.0
- 查看版本号,检查是否安装成功
hrp -v
3、基本命令的使用
3.1、生成脚手架
- 命令:
hrp startproject prodject_name
- har: har文件夹存放har文件,har文件可以通过charles或者其他抓包工具来获取
- reports:存放测试报告
- testcases:存放测试用例的文件集(在脚手架生成后,会自动带入两个yaml示例文件)
- debugtalk.py: 在这里写入的方法,可以拿到测试用例中调用
3.2、将har文件转换为测试用例文件
- 1、从fiddler中导出请求为har文件
- 2、将har用例转换为py、yaml、json格式的用例
- 查看hrp帮助命令
hrp --help
- 查看转换帮助命令
hrp convert --help
- 可以看到转换成不同的用例格式的命令
# 转换为json格式
hrp convert demo.har --to-json# 转换为pytest格式
hrp convert demo.har --to-pytest# 转换为yaml格式
hrp convert demo.har --to-yaml
3.3、执行测试用例
- 使用命令执行测试用例
hrp run demo_test.json
hrp run demo_test.yaml
hrp run demo_test_test.py
3.4、为项目创建虚拟环境,然后安装httprunner库
- 1、进入项目目录,创建虚拟环境env_demo
virtualenv env_demo
- 2、激活虚拟环境
cd env_demo\Scripts
activate
- 3、安装httprunner库
pip install httprunner==4.3.0
- 4、安装httprunner库之后可以使用pytest相关所有命令,如:
# 使用pytest执行测试用例
pytest demo_test.py
# 使用pytest执行测试用例,并在控制台输出详细日志信息
pytest -s demo_test.py
3.4、执行测试用例生成测试报告
- httprunner 集成了pytest,支持allure。但是httprunner 默认并未安装 allure,需要另外安装。
- 安装有两种方式:
- 1、安装allure 的pytest依赖库allure-pytest
pip install allure-pytest
- 2、安装httprunner的allure依赖库httprunner[allure]
pip install "httprunner[allure]"
- 1、使用hrun命令(是安装的httprunner库中带有的,不是外部安装的hrp)生成测试报告
hrun testcase --alluredir=allure-results --clean-alluredir
参数说明:
- --alluredir=DIR::生成 allure 报告的结果数据到指定目录
- --clean-alluredir:在生成结果数据之前清理--alluredir参数指定的目录
- --allure-no-capture:pytest 捕获的日志记录(logging)、标准输出(stdout)、标准错误(stderr)不会附加到报告中
- 2、生成测试报告
- 说明:生成测试有两种方式:
- 1、根据结果数据文件生成HTML形式的allure报告,然后再pycharm中使用浏览器打开生成的这个HTML文件
- 2、直接使用allure服务生成allure报告,该方式是在本地启动一个allure报告服务,报告直接在浏览器端开关
- 说明:生成测试有两种方式:
- 方式一:
- 命令:
allure generate allure-results-path -o allure-report-path -c
参数说明:
-o 指定生成报告的文件夹
-c 在生成报告之前先清理之前的报告目录
- 方式二:
- 命令
allure serve allure-results-path
4、httprunner各个模块的使用
4.1、httprunner命名规范
- 类名开头必须是Test,且必须继承httprunner
- teststeps为测试步骤,每一个测试步骤叫做Step
- Step里的RunRequest,是每个Step测试的API
- 测试用例文件的后缀必须是_test.py
4.2、httprunner的各个模块介绍
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
- HttpRunner:所有的测试用例类必须继承于HttpRunner
- Config:当前测试用文件的全局配置,可以配置全局变量,base_url,导出变量
- Step:测试步骤,每一条测试用例对应一个Step
- RunRequest:每一条测试用例的执行封装
- RunTestCase:用于在当前测试用例类中引入其他测试用例并执行,实现了不同接口之间的参数关联
不同模块之间相互关系,以及使用方式:
class TestCaseDemoTest(HttpRunner):
config = Config("testcase description")
teststeps = [
Step(
RunRequest("")
),
Step(
RunTestCase("")
),
]
4.3、使用RunRequest完成一次接口的请求
4.3.1、测试用例名
- 支持中文
RunRequest("auth")
示例:
4.3.2、请求方式
- httprunner支持:get、post、put、head、delete、options、patch等请求方式
示例:
- get:表示这是一个get请求方式的接口
- post:表示这是一个post请求方式的接口
接口里面参数可以是完整的api URL地址,也可以是只有资源路径的URL地址(这时需要再Config中配置base_url)
如:
或者
4.3.3、请求头信息添加
- 请求接口的headers的参数使用with_headers存放格式为字典格式,但是需要加上**才能正常获取到参数。
.with_headers(
**{
":method": "POST",
":path": "/auth-ws/auth/auth",
":scheme": "https",
"accept": "application/json, text/javascript, */*; q=0.01",
"accept-encoding": "gzip, deflate, br",
"accept-language": "zh-CN,zh;q=0.9",
"content-length": "59",
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
}
)
4.3.4、cookie信息添加
- 请求接口的cookie的参数使用with_cookies存放格式为字典格式,但是需要加上**才能正常获取到参数。
with_cookies(
**{
"JSESSIONID": "dgssdggdfhdfghEF6B9487sdgsg4FE",
"lc_cookieid": "a393cbfcfsdfsd94c2537a2",
"lc_sub_client": "h5",
"ngx-auth-ws": "307fdsf192efdsfsdsdgsdsd99bfsd730e",
}
)
4.3.5、请求参数添加
1、data类型的参数
- 使用with_data()函数添加
.with_data(
{
"password": "admin",
"userName": "test",
"validateCode": "1",
}
)
2、json类型的参数
- 使用with_json()函数添加
.with_json(
{
"password": "admin",
"userName": "test",
"validateCode": "1",
}
)
4.3.6、参数提取
- 使用with_jmespath()函数来完成响应参数的提取
1、响应头参数提取
extract().with_jmespath('headers.Server', 'server')
2、 cookies参数提取
extract().with_jmespath("cookies.token","token")
3、 body参数的提取
- 注意:在httprunner中响应体的数据都被封装在了body下,所以在提取响应体的内容时需要加上body
- 1、提取字符串类型的参数,直接一级一级的提取,示例:
.extract().with_jmespath("body.data.sitePortalUrl", "sitePortalUrl")
- 2、提取列表类型的中的某个参数,需要指出具体的下标,示例:
.extract().with_jmespath("body.data.info_list[0]", "name")
4.3.7、断言
- httprunner内置了非常丰富的断言方法,具体使用如下:
- 1、断言状态码相等
.validate().assert_equal("status_code", 200, "assert response status code")
- 2、断言获取到的值,是否大于预期值
.validate().assert_greater_than("body.data.count", 100)
5、全局变量的配置与使用
- 全局变量的配置在Config中配置,配置后可以在当前测试文件中的所有Step中使用;如:
config = Config("登录流程").variables(
**{
"userName": "13000000000",
"password": "222",
}
)
- 在测试用例中使用:
- 变量的提取:使用:$变量名 或 ${变量名的方式}
.with_data(
{
"password": "$password",
"userName": "$userName",
"validateCode": "1",
}
6、局部变量的配置与使用
- 局部变量配置在RunRequest或RunTestCase中使用,只针对当前配置的测试用例使用,使用变量方式如上:
Step(
RunRequest("用户名密码正确正常登录").with_variables(
**{
"userName": "13000000000",
"password": "222",
}
)
7、辅助函数的使用
- 要想在测试用例文件的某个地方使用自定义的函数,流程如下:
- 1、先在debugtalk.py文件中自定义函数,如:sum(a, b)函数
- 2、在测试用例文件引用的方式是:${sum($a, $b)}
示例:
- 1、在debugtalk.py文件中定义函数
- 2、在接口请求数据中使用该函数
.with_data(
{
"password": "$password",
"userName": "${get_username($username)}",
"validateCode": "1",
}
)
8、接口参数关联使用
8.1、获取当前用例文件其他已执行Step提取的参数
- 注意:下面的Step都是在login.py文件中
- 获取接口/auth-ws/auth/auth响应的sitePortalUrl参数
Step(
RunRequest("auth").with_variables(
**{
"userName": "13000000000",
"password": "222",
}
)
.post("/auth-ws/auth/auth")
.with_headers(
**{
":method": "POST",
":path": "/auth-ws/auth/auth",
":scheme": "https",
"accept": "application/json, text/javascript, */*; q=0.01",
"accept-encoding": "gzip, deflate, br",
"accept-language": "zh-CN,zh;q=0.9",
"content-length": "59",
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
}
)
.with_cookies(
**{
"JSESSIONID": "dasdsadasBdasds444dsadE",
"lc_cookieid": "asdnksajdkaslsapkfposakf7a2",
"lc_sub_client": "h5",
"ngx-auth-ws": "3dsajdfghiaushassadase",
}
)
.with_data(
{
"password": "$password",
"userName": "${get_username($username)}",
"validateCode": "1",
}
)
.extract()
.with_jmespath("body.data[0].sitePortalUrl", "sitePortalUrl")
.validate()
.assert_equal("status_code", 200, "assert response status code")
- 使用接口/auth-ws/auth/auth响应的提取出的sitePortalUrl参数
Step(
RunRequest("login")
.post("/platform-ms/api/user/login")
.with_headers(
**{
"content-type": "application/json; charset=UTF-8",
}
)
.with_json(
{
"ticket": "${get_ticket($sitePortalUrl)}"
}
)
.extract()
.with_jmespath("headers.token", "token")
.validate()
.assert_equal("status_code", 200, "assert response status code")
)
8.2、获取执行引用测试用例提取出的参数
- 说明:在addMaterial_test_test.py文件引用执行login.py文件,并获取login文件中提取的token变量
9、数据驱动
- 使用数据驱动模块,需要导入pytest、Parameters模块
import pytest
from httprunner import Parameters
9.1、单组数据驱动
- 注意:Parameters模块中的数据同样可以来自执行debugtalk.py中的函数返回
from httprunner import HttpRunner, Config, Step, RunRequest, Parameters
import pytest
class TestCaseAuthTest(HttpRunner):
config = Config("登录流程").base_url("http://test.com/")
teststeps = [
Step(
RunRequest("auth")
.post("/auth-ws/auth/auth")
.with_headers(
**{
":method": "POST",
":path": "/auth-ws/auth/auth",
":scheme": "https",
"accept": "application/json, text/javascript, */*; q=0.01",
"accept-encoding": "gzip, deflate, br",
"accept-language": "zh-CN,zh;q=0.9",
"content-length": "59",
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
}
)
.with_cookies(
**{
"JSESSIONID": "2D4166B552B9487E",
"lc_cookieid": "a393cbfc2",
"lc_sub_client": "h5",
"ngx-auth-ws": "307f4c81190d0fe99b30e",
}
)
.with_data(
{
"password": "$password",
"userName": "$username",
"validateCode": "1",
}
)
.extract()
.with_jmespath("body.data[0].sitePortalUrl", "sitePortalUrl")
.validate()
.assert_equal("status_code", 200, "assert response status code")
)
]
@pytest.mark.parametrize(
"param",
Parameters(
{
"userName": ["test1", "test2", "test3"]
# 也可通过调用debugtalk.py文件中函数获取
# "userName": "${get_username()}"
}
)
)
def test_start(self, param):
super().test_start(param)
9.2、多组数据驱动
- 数据配置多组,对配置的数据进行笛卡尔积计算,如:3*3,最后需要执行九组测试用例
from httprunner import HttpRunner, Config, Step, RunRequest, Parameters
import pytest
class TestCaseAuthTest(HttpRunner):
config = Config("登录流程").base_url("http://test.com/")
teststeps = [
Step(
RunRequest("auth")
.post("/auth-ws/auth/auth")
.with_headers(
**{
":method": "POST",
":path": "/auth-ws/auth/auth",
":scheme": "https",
"accept": "application/json, text/javascript, */*; q=0.01",
"accept-encoding": "gzip, deflate, br",
"accept-language": "zh-CN,zh;q=0.9",
"content-length": "59",
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
}
)
.with_cookies(
**{
"JSESSIONID": "87D154FE",
"lc_cookieid": "a393c2537a2",
"lc_sub_client": "h5",
"ngx-auth-ws": "307f4c8e99b43730e",
}
)
.with_data(
{
"password": "$password",
"userName": "$username",
"validateCode": "1",
}
)
.extract()
.with_jmespath("body.data[0].sitePortalUrl", "sitePortalUrl")
.validate()
.assert_equal("status_code", 200, "assert response status code")
)
]
@pytest.mark.parametrize(
"param",
Parameters(
{
"userName": ["test1", "test2", "test3"]
"passWord": [123, 456, 789]
}
)
)
def test_start(self, param):
super().test_start(param)
10、文件上传
- httprunner使用的是requests-toolbelt模块完成文件上传功能,但是httprunner并没有安装这个库,需要单独安装,使用以下方式安装:
- 注意:如果使用pip install requests-toolbelt安装可能因为安装到了最新版本requests-toolbelt模块从而导致与httprunner使用的requests-toolbelt版本不相同而导致错误
pip install "httprunner[upload]"
- 使用pip install "httprunner[upload]"安装的库版本是0.9.1的,这时可能和库中的urllib3发生版本不匹配(如果urllib3库是2.0.0版本以上就会冲突),所以需要将urllib3库删除了再重新安装低版本的,如:1.25.11
pip install urllib3==1.25.11
示例如下:
from httprunner import HttpRunner, Config, Step, RunRequest
class TestCaseAddmaterialTest(HttpRunner):
config = Config("testcase description")
teststeps = [
Step(
RunRequest("上传文件")
.post("http://test.com/platform-ms/api/upload/uploadFile")
.with_headers(
**{
"Accept": "application/json, text/plain, */*",
"Accept-Encoding": "gzip, deflate, br",
"Authorization": "${get_token()}",
"Content-Type": "multipart/form-testdatas; boundary=----WebKitFormBoundaryi26ZrOKdu2tMFYa7",
}
)
.with_params(
**{
"businessKey": "material",
"picUrl": "(binary)"
}
)
.upload(**{"file": r"E:\WorkPlace\test\demo\CS.png", "title": "测试图片上传"})
.validate()
.assert_equal("status_code", 200, "assert response status code")
)