python实战-setup_hooks/teardown_hooks

  • etup_hooks: 在 HTTP 请求发送前执行 hook 函数,主要用于准备工作;也可以实现对请求的 request 内容进行预处理。
  • teardown_hooks: 在 HTTP 请求发送后执行 hook 函数,主要用于测试后的清理工作;也可以实现对响应的 response 进行修改,例如进行加解密等处理。

def hook_prepare(request=None):
    print('执行准备函数')
    if request:
        request['json']['username']='800002'

def hook_teardown(response=None):
    print('执行结束函数')
    if response:
        response.status_code =300

 

2、在yml测试用例文件中,通过调用setup_hooks、teardown_hooks调用自定义的函数

#hooks函数应用
- config:
    name: 验证能否打开淘宝主页
    base_url: https://www.taobao.com/
    setup_hooks:
      - ${setup_case(case01 验证能否打开淘宝主页)}
    teardown_hooks:
      - ${teardown_case(case01 验证能否打开淘宝主页)}

- test:
    name: open hnxmxit mainpage api
    setup_hooks:
      - ${setup_step(case01 打开淘宝主页)}
    teardown_hooks:
      - ${teardown_step(case01 打开淘宝主页)}
    request:
      url: /
      method: GET
    validate:
      - eq: ['status_code',200]

前言
httprunner 3.x可以支持hook机制,在发送请求前做一些预处理或在请求完成后后置处理

setup_hook :主要用于处理接口的前置的准备工作,也可以对请求 request 参数签名加密等操作
teardown_hook:主要用于后置清理工作,也可以对返回 respone 解密等操作

测试步骤添加hook
# debugtalk.py

def hook_up():
    print("前置操作:setup!")/

def hook_down():
    print("后置操作:teardown!")

只在第一个步骤添加 setup_hooks 和 teardown_hooks
# blog地址 https://www.cnblogs.com/yoyoketang/

config:  

name: logincase
base_url: ${ENV(base_url)}
variables: {}
export:
   - token

teststeps:


    name: step1 login
    request:
        url: /api/v1/login/
        method: POST
        headers:
            Content-Type: application/json
            User-Agent: python-requests/2.18.4
        json:
            username: test
            password: 123456
    setup_hooks:
        - ${hook_up()}
    teardown_hooks:
        - ${hook_down()}
    extract:
        token: content.token         # 提取token
    validate:
        - eq: [status_code, 200]
        - eq: [headers.Content-Type, application/json]
        - eq: [content.msg, login success!]
        - eq: [content.code, 0]

对应的pytest脚本

# NOTE: Generated By HttpRunner v3.1.4
# FROM: testcases\demo_hook.yml

from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
class TestCaseDemoHook(HttpRunner):    config = Config("logincase").base_url("${ENV(base_url)}").export(*["token"])    teststeps = [
        Step(
            RunRequest("step1 login")
            .setup_hook("${hook_up()}")
            .post("/api/v1/login/")
            .with_headers(
                **{
                    "Content-Type": "application/json",
                    "User-Agent": "python-requests/2.18.4",
                }
            )
            .with_json({"username": "test", "password": 123456})
            .teardown_hook("${hook_down()}")
            .extract()
            .with_jmespath("body.token", "token")
            .validate()
            .assert_equal("status_code", 200)
            .assert_equal('headers."Content-Type"', "application/json")
            .assert_equal("body.msg", "login success!")
            .assert_equal("body.code", 0)
        ),
    ]


if __name__ == "__main__":
    TestCaseDemoHook().test_start()


从运行结果可以看到,setup_hooks 在 request 请求之前执行,teardown_hooks 在 response 之后,assert 断言之前执行

testcases\demo_hook_test.py 2021-06-21 18:45:17.051 | INFO     | httprunner.runner:test_start:451 - 
Start to run testcase: logincase, TestCase ID: 8043485f-1c2f-4e00-b00b-f951dc8cf6fa
2021-06-21 18:45:17.054 | INFO     | httprunner.runner:__run_step:292 - run step begin: step1 login >>>>>>
2021-06-21 18:45:17.056 | INFO     | httprunner.runner:__call_hooks:112 - call hook actions: setup request
2021-06-21 18:45:17.056 | DEBUG    | httprunner.runner:__call_hooks:121 - call hook function: ${hook_up()}
前置操作:setup!
2021-06-21 18:45:17.197 | DEBUG    | httprunner.client:request:186 - client IP: 192.168.1.125, Port: 30848
2021-06-21 18:45:17.200 | DEBUG    | httprunner.client:request:194 - server IP: 49.235.92.12, Port: 8201
2021-06-21 18:45:17.202 | DEBUG    | httprunner.client:log_print:40 -
....
2021-06-21 18:45:17.205 | INFO     | httprunner.client:request:218 - status_code: 200, response_time(ms): 139.3 ms, response_length: 0 bytes
2021-06-21 18:45:17.207 | INFO     | httprunner.runner:__call_hooks:112 - call hook actions: teardown request
2021-06-21 18:45:17.210 | DEBUG    | httprunner.runner:__call_hooks:121 - call hook function: ${hook_down()}
后置操作:teardown!
2021-06-21 18:45:17.211 | INFO     | httprunner.response:extract:176 - extract mapping: {'token': '392cb8c08440bde6f7ed72745e052a5c3f090aff'}
2021-06-21 18:45:17.213 | INFO     | httprunner.response:validate:246 - assert status_code equal 200(int)       ==> pass

请求 request 预处理
针对请求request 发出去的参数预处理,也可以用到 setup_hooks,需传一个内置 request 参数,debugtalk.py代码如下

# debugtalk.py
def request_sign(request):
    """请求sign签名"""
    print("请求body:",request.get("req_json"))
    # 新增 sign 参数
    request["req_json"]["sign"] = "sign xxxxxxxxxxxxxxx"
    print("sign 签名后请求body:", request.get("req_json"))
yaml脚本引用函数${request_sign($request)}

config:
    name: logincase
    base_url: ${ENV(base_url)}
    variables: {}
    export:
        - token

teststeps:
-
    name: step1 login
    request:
        url: /api/v1/login/
        method: POST
        headers:
            Content-Type: application/json
            User-Agent: python-requests/2.18.4
        json:
            username: test
            password: 123456
    setup_hooks:
        - ${request_sign($request)}
    extract:
        token: content.token         # 提取token
    validate:
        - eq: [status_code, 200]
        - eq: [headers.Content-Type, application/json]
        - eq: [content.msg, login success!]
        - eq: [content.code, 0]
1


pytest脚本

# NOTE: Generated By HttpRunner v3.1.4
# FROM: testcases\demo_hook.yml


from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase


class TestCaseDemoHook(HttpRunner):

    config = Config("logincase").base_url("${ENV(base_url)}").export(*["token"])

    teststeps = [
        Step(
            RunRequest("step1 login")
            .setup_hook("${request_sign($request)}")
            .post("/api/v1/login/")
            .with_headers(
                **{
                    "Content-Type": "application/json",
                    "User-Agent": "python-requests/2.18.4",
                }
            )
            .with_json({"username": "test", "password": 123456})
            .extract()
            .with_jmespath("body.token", "token")
            .validate()
            .assert_equal("status_code", 200)
            .assert_equal('headers."Content-Type"', "application/json")
            .assert_equal("body.msg", "login success!")
            .assert_equal("body.code", 0)
        ),
    ]


if __name__ == "__main__":
    TestCaseDemoHook().test_start()


运行后查看日志可以看到,已经签名成功

请求body: {'username': 'test', 'password': 123456}
sign 签名后请求body: {'username': 'test', 'password': 123456, 'sign': 'sign xxxxxxxxxxxxxxx'}
2021-06-21 18:58:57.876 | DEBUG    | httprunner.client:request:186 - client IP: 192.168.1.125, Port: 31471
2021-06-21 18:58:57.878 | DEBUG    | httprunner.client:request:194 - server IP: 49.235.92.12, Port: 8201
2021-06-21 18:58:57.881 | DEBUG    | httprunner.client:log_print:40 -
================== request details ==================
method   : POST
url      : http://127.0.0.1:8000/api/v1/login/
headers  : {
    "User-Agent": "python-requests/2.18.4",
    "Accept-Encoding": "gzip, deflate",
    "Accept": "*/*",
    "Connection": "keep-alive",
    "Content-Type": "application/json",
    "HRUN-Request-ID": "HRUN-911bb03a-a24a-40a6-ad32-9d62a9d000fd-137716",
    "Content-Length": "72"
}
cookies  : {}
body     : {
    "username": "test",
    "password": 123456,
    "sign": "sign xxxxxxxxxxxxxxx"
}

返回 response 处理
如果需要在接口返回后,对返回的结果处理,可以添加respone请求参数,比如我把返回的状态码200改成了203

# debugtalk.py

def response_status(response):
    """修改返回状态码"""
    print("返回response status_code:", response.status_code)
    response.status_code = 203
    print("修改后返回response status_code:", response.status_code)



yaml 引用示例

setup_hooks:
        - ${request_sign($request)}
    teardown_hooks:
        - ${response_status($response)}



pytest引用示例

            

.with_json({"username": "test", "password": 123456})
            .teardown_hook("${response_status($response)}")



运行结果

2021-06-21 19:07:13.729 | INFO     | httprunner.client:request:218 - status_code: 200, response_time(ms): 157.17 ms, response_length: 0 bytes
2021-06-21 19:07:13.731 | INFO     | httprunner.runner:__call_hooks:112 - call hook actions: teardown request
2021-06-21 19:07:13.736 | DEBUG    | httprunner.runner:__call_hooks:121 - call hook function: ${response_status($response)}
返回response status_code: 200
修改后返回response status_code: 203

httprunner 3.x 版本在 config 中不支持setup_hook和teardown_hook
 

 

(my-env) root@autodl-container-242a4285b3-3647fd99:~/autodl-tmp/YOLOv10# pip install numpy==1.19 Looking in indexes: http://mirrors.aliyun.com/pypi/simple Collecting numpy==1.19 Downloading http://mirrors.aliyun.com/pypi/packages/f1/2c/717bdd12404c73ec0c8c734c81a0bad7048866bc36a88a1b69fd52b01c07/numpy-1.19.0.zip (7.3 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 7.3/7.3 MB 11.5 MB/s eta 0:00:00 Installing build dependencies ... done Getting requirements to build wheel ... done Preparing metadata (pyproject.toml) ... error error: subprocess-exited-with-error × Preparing metadata (pyproject.toml) did not run successfully. │ exit code: 1 ╰─> [24 lines of output] Running from numpy source directory. <string>:460: UserWarning: Unrecognized setuptools command, proceeding with generating Cython sources and expanding templates Traceback (most recent call last): File "/root/miniconda3/envs/my-env/lib/python3.9/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 389, in <module> main() File "/root/miniconda3/envs/my-env/lib/python3.9/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 373, in main json_out["return_val"] = hook(**hook_input["kwargs"]) File "/root/miniconda3/envs/my-env/lib/python3.9/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 175, in prepare_metadata_for_build_wheel return hook(metadata_directory, config_settings) File "/tmp/pip-build-env-yngvw6of/overlay/lib/python3.9/site-packages/setuptools/build_meta.py", line 377, in prepare_metadata_for_build_wheel self.run_setup() File "/tmp/pip-build-env-yngvw6of/overlay/lib/python3.9/site-packages/setuptools/build_meta.py", line 522, in run_setup super().run_setup(setup_script=setup_script) File "/tmp/pip-build-env-yngvw6of/overlay/lib/python3.9/site-packages/setuptools/build_meta.py", line 320, in run_
最新发布
03-09
<think>嗯,用户遇到了安装numpy 1.19版本时出现“Preparing metadata (pyproject.toml) did not run successfully”的错误。首先,我需要回忆一下这类错误的常见原因。根据引用[2]中的信息,类似的问题通常与缺少编译依赖项或内存不足有关。可能用户的环境在编译过程中遇到了问题,导致元数据无法正确生成。 接下来,我应该分步骤考虑可能的解决方案。首先,检查Python版本是否兼容numpy 1.19。因为较新的Python版本可能不再支持旧的库版本。比如,numpy 1.19可能不支持Python 3.10或更高版本,用户可能需要降级Python或使用更高版本的numpy。 然后,升级构建工具是一个常见的解决方法。用户可能没有安装最新版本的pip、setuptools或wheel,这会导致编译过程中的兼容性问题。建议用户运行升级命令,确保这些工具都是最新的。 安装系统依赖项也很重要。在Linux系统上,编译numpy需要安装一些开发库,比如gcc、gfortran、python3-dev等。用户可能需要通过包管理器安装这些依赖项。例如,在Ubuntu上,可以使用apt-get命令安装这些包。 如果内存不足,特别是轻量级服务器或虚拟机环境,可以考虑增加交换空间。使用dd命令创建交换文件,然后启用它,这样可以临时扩展可用内存,避免编译过程中因内存不足而失败。 另外,使用预编译的二进制文件可能绕过编译步骤。用户可以通过指定--only-binary参数强制pip安装wheel包,或者从第三方源如PyPI上下载合适的whl文件手动安装。 最后,如果以上方法都不奏效,用户可能需要考虑使用更高版本的numpy,因为旧版本可能不再维护,存在兼容性问题。同时,使用虚拟环境可以隔离项目依赖,避免系统环境的影响。 需要确保每个步骤都清晰,并且用户能够逐步操作。还要提醒用户注意错误日志,根据具体的错误信息调整解决方案。例如,如果错误信息中提到了特定的缺失头文件,可能需要安装对应的开发包。此外,针对不同的操作系统,安装依赖项的命令会有所不同,需要区分Linux、macOS和Windows的解决方案。 总结下来,应该分六个步骤,从检查环境到使用替代安装方法,覆盖所有可能的原因,并给出具体的命令示例,方便用户执行。同时,引用相关的参考资料,如引用[2]中提到的内存不足解决方案,来增强建议的可信度。</think>### 解决pip安装numpy 1.19时元数据准备失败的方法 #### 1. **检查Python版本兼容性** - numpy 1.19要求Python 3.6-3.8,若使用Python 3.9+会因兼容性问题导致编译失败[^2]。 - **操作**: ```bash python --version # 查看当Python版本 ``` - 若版本过高,可创建虚拟环境指定低版本Python: ```bash conda create -n py38 python=3.8 conda activate py38 ``` #### 2. **升级构建工具** - 旧版`pip/setuptools`可能导致编译过程异常。 - **操作**: ```bash pip install --upgrade pip setuptools wheel ``` #### 3. **安装系统编译依赖** - 缺少C/C++编译器或Fortran库会中断编译。 - **Linux(Ubuntu/Debian)**: ```bash sudo apt-get install build-essential gfortran python3-dev ``` - **macOS**: ```bash brew install gcc openblas ``` - **Windows**:需安装[Microsoft C++ Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/)。 #### 4. **增加交换空间(针对内存不足)** - 内存不足时,可通过扩展交换空间缓解。 - **操作**: ```bash sudo fallocate -l 4G /swapfile # 创建4GB交换文件 sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile ``` #### 5. **使用预编译二进制文件** - 跳过源码编译步骤,直接安装官方或第三方预构建的whl文件。 - **方法1**:强制使用二进制安装 ```bash pip install numpy==1.19 --only-binary=:all: ``` - **方法2**:手动下载whl文件 - 从[PyPI](https://pypi.org/project/numpy/1.19.0/)选择与系统匹配的whl文件: ```bash pip install numpy-1.19.0-cp38-cp38-win_amd64.whl # 示例路径 ``` #### 6. **尝试更高版本或虚拟环境** - 若仍失败,建议升级到numpy更高版本(如1.21+)或使用`conda`管理依赖: ```bash conda install numpy=1.19 ``` - 使用虚拟环境隔离依赖: ```bash python -m venv numpy_env source numpy_env/bin/activate # Linux/macOS numpy_env\Scripts\activate # Windows pip install numpy==1.19 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值