前言
在发送请求的时候,我们希望在发送请求参数前,带上签名的值,或者返回的内容需要二次处理,解密后返回。
此功能我们可以用 hooks 钩子来实现
pip 安装插件
pip install pytest-yaml-yoyo
hooks 功能在v1.0.4版本上实现
response 钩子功能
requests 库只支持一个 response 的钩子,即在响应返回时可以捎带执行我们自定义的某些方法。
可以用于打印一些信息,做一些响应检查或想响应对象中添加额外的信息
# 作者-上海悠悠 微信/QQ交流:283340479
# blog地址 https://www.cnblogs.com/yoyoketang/
import requests
url = 'https://httpbin.org/get'
def response_status(resopnse, *args, **kwargs):
print('url', resopnse.url)
resopnse.status = 'PASS' if resopnse.status_code < 400 else 'FAIL'
res = requests.get(url, hooks={'response': response_status})
print(res.status)
以上是基于requests 库的钩子功能实现的基本方式
yaml 用例中添加response 钩子
在yaml 文件中添加response 钩子功能,跟上面代码方式差不多, 有2种方式
- 1.写到config 全局配置,每个请求都会带上hooks
- 2.写到单个请求的request 下,仅单个请求会带上hooks功能
先看单个请求的response 钩子
test_hook1.yml
# 作者-上海悠悠 微信/QQ交流:283340479
# blog地址 https://www.cnblogs.com/yoyoketang/
config:
name: post示例
teststeps:
-
name: post
request:
method: POST
url: http://httpbin.org/post
json:
username: test
password: "123456"
hooks:
response: ['hook_response']
extract:
url: body.url
validate:
- eq: [status_code, 200]
- eq: [headers.Server, gunicorn/19.9.0]
- eq: [$.code, 0]
-
name: post
request:
method: POST
url: http://httpbin.org/post
json:
username: test
password: "123456"
extract:
url: body.url
validate:
- eq: [status_code, 200]
- eq: [headers.Server, gunicorn/19.9.0]
- eq: [$.code, 0]
在conftest.py 中注册钩子函数
# 作者-上海悠悠 微信/QQ交流:283340479
# blog地址 https://www.cnblogs.com/yoyoketang/
def hook_response(response, *args, **kwargs):
# print(response.text) 原始数据
print("执行response hook 函数内容....")
class NewResponse:
text = '{"code": 0, "data": {"token": "yo yo"}}' # response.text解密
history = response.history
headers = response.headers
cookies = response.cookies
status_code = response.status_code
raw = response.raw
is_redirect = response.is_redirect
content = b'{"code": 0, "data": {"token": "yo yo"}}' # response.text解密
elapsed = response.elapsed
@staticmethod
def json():
# 拿到原始的response.json() 后解码
return {"code": 0, "data": {"token": "yo yo"}}
return NewResponse
my_builtins.hook_response = hook_response
由于上面用例只在第一个请求中使用了hooks功能,所以第二个请求的断言- eq: [$.code, 0]
会失败
钩子方法调用语法
- 1.层级是在request 下
- 2.hooks 关键字对应的是一个字典 {"response": []}
- 3.response 的值可以是单个函数名称,也可以是多个
func1, func2
,或者是一个list类型[func1, func2] - 4.response 的值必须是一个可以调用的函数,此函数需在conftest 中注册绑定到
my_builtins
模块 - 5.调用的函数第一个参数是
response
, 可以重写response内容(如需要对返回结果解密),也可以不用重写
request:
method: POST
url: http://httpbin.org/post
hooks:
response: ['hook_response']
config 全局使用
在config 中配置全局hooks功能,格式如下
config:
name: post示例
hooks:
response: ['hook_response']
test_hook2.yml完整示例
config:
name: post示例
hooks:
response: ['hook_response']
teststeps:
-
name: post
request:
method: POST
url: http://httpbin.org/post
json:
username: test
password: "123456"
hooks:
response: ['hook_response']
extract:
url: body.url
validate:
- eq: [status_code, 200]
- eq: [headers.Server, gunicorn/19.9.0]
- eq: [$.code, 0]
-
name: post
request:
method: POST
url: http://httpbin.org/post
json:
username: test
password: "123456"
extract:
url: body.url
validate:
- eq: [status_code, 200]
- eq: [headers.Server, gunicorn/19.9.0]
- eq: [$.code, 0]
全局配置hooks, 那么该用例下所有的请求都会带上hooks
请求预处理钩子
如果需要对请求参数预处理,我们还新增了一个request 请求钩子,可以获取到发送请求时的request参数
在conftest.py
# 作者-上海悠悠 微信/QQ交流:283340479
# blog地址 https://www.cnblogs.com/yoyoketang/
def func1(req):
print(f'请求预处理:{req}')
def func2():
print(f'请求预处理-----------')
my_builtins.func1 = func1
my_builtins.func2 = func2
在 yaml 文件中使用示例
config:
name: post示例
teststeps:
-
name: post
request:
method: POST
url: http://httpbin.org/post
json:
username: test
password: "123456"
hooks:
request: ['func1', 'func2']
response: ['hook_response']
extract:
url: body.url
validate:
- eq: [status_code, 200]
- eq: [headers.Server, gunicorn/19.9.0]
- eq: [$.code, 0]
-
name: post
request:
method: POST
url: http://httpbin.org/post
json:
username: test
password: "123456"
hooks:
response: ['hook_response']
extract:
url: body.url
validate:
- eq: [status_code, 200]
- eq: [headers.Server, gunicorn/19.9.0]
- eq: [$.code, 0]
在config 中设置全局hooks示例
config:
name: post示例
hooks:
request: ['func1', 'func2']
response: ['hook_response']
由于request 变量是pytest的一个内置fixture,此变量保留着,获取请求参数的函数使用req
代替。
利用request hook功能可以实现请求参数的预处理,比如请求body签名和加密处理等需求。