pytest + yaml 框架 -6.hooks 钩子功能实现
迪丽瓦拉
2024-03-06 06:14:44
0

前言

在发送请求的时候,我们希望在发送请求参数前,带上签名的值,或者返回的内容需要二次处理,解密后返回。
此功能我们可以用 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: postrequest:method: POSTurl: http://httpbin.org/postjson:username: testpassword: "123456"hooks:response: ['hook_response']extract:url:  body.urlvalidate:- eq: [status_code, 200]- eq: [headers.Server, gunicorn/19.9.0]- eq: [$.code, 0]
-name: postrequest:method: POSTurl: http://httpbin.org/postjson:username: testpassword: "123456"extract:url:  body.urlvalidate:- 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.historyheaders = response.headerscookies = response.cookiesstatus_code = response.status_coderaw = response.rawis_redirect = response.is_redirectcontent = b'{"code": 0, "data": {"token": "yo yo"}}'  # response.text解密elapsed = response.elapsed@staticmethoddef json():# 拿到原始的response.json() 后解码return {"code": 0, "data": {"token": "yo yo"}}return NewResponsemy_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: POSTurl: http://httpbin.org/posthooks: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: postrequest:method: POSTurl: http://httpbin.org/postjson:username: testpassword: "123456"hooks:response: ['hook_response']extract:url:  body.urlvalidate:- eq: [status_code, 200]- eq: [headers.Server, gunicorn/19.9.0]- eq: [$.code, 0]
-name: postrequest:method: POSTurl: http://httpbin.org/postjson:username: testpassword: "123456"extract:url:  body.urlvalidate:- 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: postrequest:method: POSTurl: http://httpbin.org/postjson:username: testpassword: "123456"hooks:request: ['func1', 'func2']response: ['hook_response']extract:url:  body.urlvalidate:- eq: [status_code, 200]- eq: [headers.Server, gunicorn/19.9.0]- eq: [$.code, 0]
-name: postrequest:method: POSTurl: http://httpbin.org/postjson:username: testpassword: "123456"hooks:response: ['hook_response']extract:url:  body.urlvalidate:- 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签名和加密处理等需求。

相关内容