Httprunner接口测试框架入门(看这一篇足够了哦~)
文章目录
- 前言
- 一、httprunner是什么
- 二、安装python、Httprunner、allure-pytest
- 三、生成脚手架
- 四、charles录制har文件,并用httprunner命令转成.py文件
- 五、运行httprunner文件
- 六、httprunner内置函数使用
- 1、httprunner命名规范
- 2、httprunner的模块引入
- 3、待测接口命名
- 4、设置请求方式
- 5、.with_headers:headers入参传递
- 6、config:设置全局化参数
- 6.1、.base_url():设置全局化项目地址
- 7、.with_variables(**{ }):定义局部变量,仅在当前step可用
- 8、${变量}:引用设置的变量
- 9、.with_cookies:设置cookie值
- 10、with_data:data参数传参
- 11、with_json:json参数传参
- 12、extract().with_jmespath():拿到接口的response,用作后续接口使用
- 13、取出的参数,如何运用到其他step中
- 14、.validate():httprunner内置的断言功能
- 15、RunTestCase、call():业务解耦和调用方法
- 七、debugtalk.py:辅助函数
- 八、生成allure报告
- 九、数据驱动
前言
一、httprunner是什么
HttpRunner 是一款面向 HTTP(S) 协议的通用测试框架,继承request的全部特性,只需编写维护一份 YAML/JSON 脚本,即可实现自动化测试、性能测试、线上监控、持续集成等多种测试需求。
1.httprunner的优点
<1>、在charles或者其他抓包工具中,保存的har文件,在httprunner内支持har文件转换成.py文件 或者是优雅的yaml文件
<2>、httprunner内置了loguru日志模块:https://www.jianshu.com/p/5aead7b6a7a9
<3>、httprunner内置了locust模块,支持接口测试同时,又支持了性能测试(locust具体怎么执行,可以参考我的另一篇博客):https://blog.csdn.net/weixin_46457203/article/details/123001840
<4>、httprunner内置了jmespath模块,如果response过多,用jmespath模块取数据会更加的便捷
<5>、可以通过一行命令,快速的生成一个接口测试框架(hrun的脚手架功能)
<6> httprunner内置了pytest框架,使用pytest命令就可以运行httprunner脚本。
二、安装python、Httprunner、allure-pytest
python的安装,这里不过多讲解
第一个是安装httprunner,第二个是安装allure报告
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple httprunner
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple allure-pytest
之后下载allure报告插件:https://repo.maven.apache.org/maven2/io/qameta/allure/allure-commandline/2.13.2/
下载以后解压,allure文件的路径配置到环境变量-path里
查看httprunner的版本
httprunner -V
三、生成脚手架
在pycharm中使用命令:
httprunner startproject [filename]
1、新建一个项目名为:ERP_Project的工程
输入完命令,敲回车,会自动生成完整的项目
2、查看项目的目录层级
har: har文件夹存放har文件,har文件可以通过charles或者其他抓包工具来获取
reports:存放测试报告
testcases:存放测试用例的文件集(在脚手架生成后,会自动带入两个yaml示例文件)
debugtalk.py: 在这里写入的方法,可以拿到测试用例中调用
四、charles录制har文件,并用httprunner命令转成.py文件
1、录制脚本,导出har文件
我这里录制的是 Gitee上的开源项目:http://erp2.hzb-it.com/
<1> 打开charles,过滤域名
<2>抓取一条业务用例: 登录—>组织和人员—>职位管理—>新增职位为:测试工程师
<3>过滤charles的静态文件,导出所有的接口,格式为.har
选择 Sequence——>将被抓取的域名放到 Filter里面
过滤js、css静态文件-选中,右击鼠标,点击clear(如果没有,就忽略)
选中,点击clear
<4>选中所有的文件,选择导出har文件
选择har文件进行导出
2、har文件转成.py文件(转成的用例,记得放到testcases文件夹)
将har文件放入脚手架的har目录下
使用命令,将目标目录har下的ERP_project.har文件转成 py文件
har2case ERP_Project/har/ERP_Project.har
在当前目录下,就会多出.py文件
3、har文件转成生成yaml文件
har2case ERP_Project/har/ERP_Project.har -2y
4、har文件转成生成json文件
har2case ERP_Project/har/ERP_Project.har -2j
五、运行httprunner文件
使用pytest命令运行
方式一:
pytest ERP_Project_test.py
方式二(可打印详细的日志到控制台):
pytest -s ERP_Project_test.py
使用httprunner命令运行
方式一:
六、httprunner内置函数使用
1、httprunner命名规范
- 类名开头必须是Test
- 定义的测试类,需要继承httprunner
- teststeps为测试步骤,每一个测试步骤叫做step
- step里的RunRequest,是待测的API名字,可按照接口名称填写\
- .py文件的尾缀,必须是_test
2、httprunner的模块引入
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
Httprunner:导入Httprunner类,后面的测试类,继承于Httprunner
Config:全局设置,可以设置全局变量,例-variables(**);可以忽略Request库的警告,例-verify(False)
Step:测试步骤,每一个的接口测试用例,对应着一个step
RunRequest:每一个测试步骤的接口名称命名,可以是中文
RunTestCase:每一个测试步骤的接口名称命名,可以是中文。不同于RunRequest的是,RunTestCase只可以用于调用其他hrun文件时使用
3、待测接口命名
RunRequest("/app/common/login")
命名接口,这里可以写对应的业务接口名称
比如,我这里命名为:登录
4、设置请求方式
.get,表明这是一个get请求方式的接口
.post,表明这是一个post请求方式的接口
后面需要跟上完整的API路径名
可通过ctrl+鼠标左击,进入方法内
httprunner支持:get、post、put、head、delete、options、patch等请求方式
5、.with_headers:headers入参传递
请求接口的headers入参放在这里,在with_headers方法内,需要加上**来读取。
例:
.with_headers(
**{
"Host": "erp2.hzb-it.com",
"Content-Length": "27",
"Accept": "application/json, text/plain, */*",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36",
"Content-Type": "application/x-www-form-urlencoded",
"Origin": "http://erp2.hzb-it.com",
"Referer": "http://erp2.hzb-it.com/",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9",
"Connection": "keep-alive",
}
)
6、config:设置全局化参数
config = Config("testcase description").verify(False).variables(**{
"Host":"erp2.hzb-it.com",# todo:定义全局变量
})
此时定义了一个名为Host的全局变量,整体的httprunner都可以调用
想要定义多个全局变量,也可以在这里设置
6.1、.base_url():设置全局化项目地址
7、.with_variables(**{ }):定义局部变量,仅在当前step可用
设置局部变量语法:
1、在RunRequest()后
2、在RunTestCase()后
.with_variables(**{"Content-Length":"27"})
7.1、引用局部变量
"Content-Length": "${Content-Length}",
8、${变量}:引用设置的变量
在需要使用的地方,填入:${变量名},就可以引用参数
这里调用了Host、Accept全局参数
9、.with_cookies:设置cookie值
请求接口的cookies入参放在这里,在with_cookies方法内,需要加上**来读取。
.with_cookies(
**{
"access-token": "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NDczNTk0NDEsInVzZXJEZXRhaWxzIjoie1wicm9sZXNcIjpbe1wiY29kZVwiOlwic3VwZXJhZG1pblwiLFwibmFtZVwiOlwi6LaF57qn566h55CG5ZGYXCIsXCJpZFwiOjF9LHtcImNvZGVcIjpcInhpbmd6aGVuZ1wiLFwibmFtZVwiOlwi6KGM5pS_XCIsXCJpZFwiOjExfV0sXCJwYXNzd29yZFwiOlwiJDJhJDEwJE5Fc3JOeUJJUEdFTHg5RHBJYm0veC5Wd0FNT3pobVg0Y09mTzRqendSSmY2WGl6WXJ4akkyXCIsXCJpZGVudGl0eVwiOjEsXCJuYW1lXCI6XCLnrqHnkIblkZhcIixcImlkXCI6MSxcInN0YXRlXCI6MSxcInVzZXJuYW1lXCI6XCJhZG1pblwifSJ9.xLw2cSbOIxQOWhXRgarGcI55U8B353_c0vDS7M-puJ8"
}
)
10、with_data:data参数传参
引言:指定HTTP请求正文。这对应于的data参数requests.request
.with_data({"username": "admin", "password": "123"})
11、with_json:json参数传参
在json中指定HTTP请求正文。这对应于的json参数requests.request。
但要记得在headers声明json传参:{‘Content-Type’:‘application/json;charset=utf8’}
.with_data({"username": "admin", "password": "123"})
12、extract().with_jmespath():拿到接口的response,用作后续接口使用
httprunner的响应集,整体被命名为:body
我是怎么知道的?可以通过运行hrun,来看下控制台呀
运行命令:pytest ERP_Project_test.py
它的最外面,就是body,所以,我们取值的时候,就要带上body
12.1 response body怎么取关联接口的响应值?
举例:我想取图中的data参数
extract().with_jmespath("body.data","data")
这样就可以取到参数了。body是最外层,data处于body的下一级,所以用的是body.data
第二个参数是命名取到的变量为:data
12.2 response headers怎么取值?
extract().with_jmespath('headers.Server', 'cookies')
12.3 response cookies怎么取值?
extract().with_jmespath(cookies."key","edit-key")
12.4 怎么确保取的值正确?
运行一遍httprunner:
pytest -s ERP_Project_test.py
在下图,就可以清晰的看到,data参数被取出来了
12.5 如果response清单返回列表数据,该怎么取值?
可以通过数组下标的方式取值
比如下面,就是取的body下的data下的list下标为0的quantity数据
extract().with_jmespath("body.data.list[0].quantity","quantity")
13、取出的参数,如何运用到其他step中
${变量名}就可以使用,举例
"access-token": "${data}"
14、.validate():httprunner内置的断言功能
httprunner的断言信息会自动生成:断言响应状态码、断言响应body的文本信息等
.assert_equal():断言文本信息是否相等,也可以自定义断言
比如:取出响应状态码进行断言
.assert_equal("status_code", 200)
取出响应headers参数进行断言
.assert_equal('headers."Content-Type"', "application/json")
取出响应body参数,与预期的匹配的文本信息进行断言
.assert_equal("body.name", "管理员")
.assert_greater_than():断言获取到的值,是否大于预期设定的值
断言取出的值,是否大于20
.assert_greater_than("body.data.totalCount", 20)
.assert_endswith():断言获取到的值,在字符串末尾是否与预期设定的值一致
断言ss 是否在字符串末尾
.assert_endswith("body.message", "ss")
.assert_startswith():断言获取到的值,在字符串开始是否与预期设定的值一致
断言su 是否在字符串开始
.assert_startswith("body.message", "su")
查看更多的断言方式
按住ctrl+鼠标左键,查看
15、RunTestCase、call():业务解耦和调用方法
A文件:ERP_Login_test.py,只有一个login的step
# NOTE: Generated By HttpRunner v3.1.6
# FROM: testcases\ERP_PROJECT.har
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
class TestCaseErpProject(HttpRunner):
config = Config("testcase description").base_url("http://erp2.hzb-it.com/").verify(False).variables(**{ # todo: .base_url()设置项目全局地址
"Host":"erp2.hzb-it.com",
"Accept":"application/json, text/plain, */*" # todo:定义全局变量
})
teststeps = [
Step(
RunRequest("登录")
.with_variables(**{"Content-Length":"27"}) #todo:定义局部变量
.post("app/common/login")
.with_headers(
**{
"Host": "${Host}", # todo: 引用Host变量
"Content-Length": "${Content-Length}", # todo:引用局部变量
"Accept": "${Accept}", # todo: 引用Accept变量
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36",
"Content-Type": "application/x-www-form-urlencoded",
"Origin": "http://erp2.hzb-it.com",
"Referer": "http://erp2.hzb-it.com/",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9",
"Connection": "keep-alive",
}
)
.with_data({"username": "admin", "password": "123"})
.extract().with_jmespath("body.data","data")
.validate()
.assert_equal("status_code", 200)
.assert_equal('headers."Content-Type"', "application/json;charset=UTF-8")
.assert_equal("body.msg", "提交成功")
.assert_equal("body.errCode", 0)
),
]
if __name__ == "__main__":
TestCaseErpProject().test_start()
B文件: ERP_Project_test.py,是登录后的操作,依赖于A文件
RunTestCase()和call()使用语法:
1、RunTestCase()是只有在调用A文件的时候,才可以使用(业务解耦、login解耦等)
2、call():call,调用另一个.py文件的内容。在导入模块时,需要注意,使用别名,不然的话,hrun会识别成两条case
# NOTE: Generated By HttpRunner v3.1.6
# FROM: testcases\ERP_PROJECT.har
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
from ERP_Project.testcases.ERP_Login_test import TestCaseErpProjects as Login
class TestCaseErpProject(HttpRunner):
config = Config("testcase description").base_url("http://erp2.hzb-it.com/").verify(False).variables(**{ # todo: .base_url()设置项目全局地址
"Host":"erp2.hzb-it.com",
"Accept":"application/json, text/plain, */*" # todo:定义全局变量
})
teststeps = [
Step(
RunTestCase("login")
.call(Login)
.export("data")
),
Step(
RunRequest("/app/common/base/enumList")
.get("http://erp2.hzb-it.com/app/common/base/enumList")
.with_headers(
**{
"Host": "erp2.hzb-it.com",
"Accept": "application/json, text/plain, */*",
"access-token": "${data}",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36",
"Referer": "http://erp2.hzb-it.com/",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9",
"Cookie": "access-token=${data}",
"Connection": "keep-alive",
}
)
.with_cookies(
**{
"access-token": "${data}"
}
)
.validate()
.assert_equal("status_code", 200)
.assert_equal('headers."Content-Type"', "application/json")
),
]
if __name__ == "__main__":
TestCaseErpProject().test_start()
15.1、如果用例运行报错,如下:
当使用pytest -s xx.py 运行文件时,报错提示
解决办法:
在运行文件的根目录下,新建一个conftest.py,内容为:
import os
import sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__),'..')))
七、debugtalk.py:辅助函数
debugtalk.py创建小方法,可用于hrun的step中
1、函数的封装
1.1、uuid函数
def get_random_request_id():
return uuid.uuid4()
1.2、睡眠函数
def sleep(n_secs):
time.sleep(n_secs)
2、引用函数
引用debugtalk.py文件方法,不需要导入debugtalk.py文件
2.1、.teardown_hook() :退出后调用,teardown方法
.teardown_hook("${sleep(5)}") #todo:调用debugtalk.py文件方法,执行方法后,等待5s
八、生成allure报告
hrun ERP_Project_test.py --alluredir=allure # 生成allure 数据
allure generate ./allure/ -o ./reports --clean # 生成allure报告到reports文件夹里
九、数据驱动
我先在ERP_Login_test文件中,加了username的全局变量
导入pytest、hrun的数据驱动模块
import pytest
from httprunner import Parameters
9.1、单组数据驱动
@pytest.mark.parametrize( # TODO:数据驱动
'param',
Parameters({"username": ["admin", "admin1", "admin2"],
}
),
) # todo: 切换三个账号,执行用例.
def test_start(self, param):
super().test_start(param)
因为admin1和admin2不存在这样的账号,所以登录失败了
9.2、多组数据驱动
我先在ERP_Login_test文件中,加了password的全局变量
当数据配置多组,会形成笛卡尔积,即3*3,九组测试用例输出
@pytest.mark.parametrize( # TODO:数据驱动
'param',
Parameters({"username": ["admin", "admin1", "admin2"],
"password":["123","1234","12345"],# todo:数据配置多组,会形成笛卡尔积,即 3*3,九组测试用例输出
}
),
) # todo: 切换三个账号,执行用例.
def test_start(self, param):
super().test_start(param)
9.3、引用debugtalk.py写好的方法做数据驱动
@pytest.mark.parametrize( # TODO:数据驱动
'param',
Parameters({#"username": ["admin", "admin1", "admin2"],
"userName": "${get_userName()}", # todo: 也可以引用debugtalk.py写好的方法去调用
"password":["123","1234","12345"],
}
),
) # todo: 切换三个账号,执行用例.
def test_start(self, param):
super().test_start(param)
更多推荐
所有评论(0)