Pytest requests 二次封装,灵活进行HTTP请求 —— Python 实践

        在自动化测试、接口调试等场景中,requests 是 Python 中非常常用的 HTTP 客户端库。为了提高代码的可维护性与复用性,我们通常会 requests 进行二次封装。本文将详细介绍如何对 requests 库进行封装,实现一个支持变量替换、日志记录、Allure 报告集成等功能的 HTTP 请求类。

🧾 一、项目背景

        在实际开发和测试过程中,频繁地使用原始 requests.get()、requests.post() 等方法容易导致代码重复、逻辑混乱。通过封装 requests,我们可以统一请求入口、自动处理变量、记录日志、生成测试报告等,提升整体开发效率和代码质量。

🛠️ 二、封装目标

本次封装的目标包括:

  • 支持多种 HTTP 方法(GET、POST、PUT、DELETE 等)
  • 支持变量替换(如 ${username} 替换为缓存中的值)
  • 自动记录请求日志
  • 集成 Allure 报告展示请求详情
  • 支持合并字典参数(headers、timeout 等)

📦 三、依赖模块介绍

import typing as t
import allure
import urllib3
from requests import Session, Response
from common.cache import cache
from common.json import json, loads, dumps
from common.regular import sub_var, findalls
from utils.logger import logger
  • typing:用于类型注解,增强代码可读性和 IDE 智能提示。
  • allure:用于在测试报告中动态添加请求信息。
  • urllib3:禁用 SSL 警告。
  • requests.Session:保持会话状态,提高请求效率。
  • common.cache:缓存模块,用于变量替换。
  • common.regular:正则处理模块,用于提取和替换变量。
  • utils.logger:日志模块,记录请求过程。

🔧 四、核心类设计 —— HttpRequest

该类继承自 requests.Session,实现了请求的统一处理流程。

1. 初始化方法 __init__

def __init__(self, *args: t.Union[t.Set, t.List], **kwargs: t.Dict[t.Text, t.Any]):
    super(HttpRequest, self).__init__()
    self.exception = kwargs.get("exception", Exception)
  • 继承 Session 实现会话保持。
  • 可选传入异常类,默认为 Exception。

2. 发送请求方法 send_request

这是整个封装的核心方法,负责处理请求的构建、发送及结果处理。

参数解析

method = kwargs.get('method', 'GET').upper()
baseurl = cache.get('baseurl', '')
url = baseurl + kwargs.get('route', '')
  • 从 kwargs 中获取请求方法、路由路径,并拼接完整 URL。
  • 使用 cache 获取基础地址,便于环境切换。

变量替换

replace_variables(kwargs, cache)
  • 调用 replace_variables 函数递归替换所有变量占位符,例如 ${token} 替换为缓存中的 token 值。(replace_variables 方法下方有写)

构造请求参数

request_data = self.mergedict(
    kwargs.get('RequestData', {}),
    headers=kwargs.get('headers', None)
)
  • 合并请求体和头部信息,确保结构统一。

JSON 格式化数据

if 'data' in kwargs:
    request_data['json'] = kwargs['data']
    request_data.pop('data', None)
  • 如果传入了 data 字段,则将其转换为 json 格式发送。

发送请求

response = self.dispatch(method, url, **request_data)
  • 调用 dispatch 分发具体请求方法。

Allure 报告记录

# Allure 报告描述
description_html = f"""
<font color=red>请求方法:</font>{method}<br/>
<font color=red>请求地址:</font>{url}<br/>
<font color=red>请求头:</font>{str(response.headers)}<br/>
<font color=red>请求参数:</font>{json.dumps(kwargs, ensure_ascii=False)}<br/>
<font color=red>响应状态码:</font>{str(response.status_code)}<br/>
<font color=red>响应时间:</font>{str(response.elapsed.total_seconds())}<br/>
"""
allure.dynamic.description_html(description_html)
  • 将请求详细信息写入 Allure 测试报告,便于排查问题。

异常捕获

except self.exception as e:
    logger.exception(f"请求发送失败: {str(e)}")
    raise e

3. 请求分发方法 dispatch

def dispatch(self, method: t.Text, *args: t.Union[t.List, t.Tuple], **kwargs: t.Dict) -> Response:
    handler = getattr(self, method.lower())
    return handler(*args, **kwargs)
  • 根据请求方法名动态调用对应的 get、post 等方法。

4. 字典合并方法 mergedict

@staticmethod
def mergedict(data: t.Dict, **kwargs: t.Dict) -> t.Dict:
    result = data.copy()
    for key, value in kwargs.items():
        if key in ['headers', 'timeout']:
            result[key] = value
    return result
  • 合并额外的关键字参数到请求数据中,如 headers 和 timeout。

🔁 五、变量替换函数 replace_variables

def replace_variables(data, cache):
    if isinstance(data, dict):
        for key, value in data.items():
            if isinstance(value, str):
                data[key] = sub_var(findalls(value), value, cache)
            elif isinstance(value, dict):
                replace_variables(value, cache)
            elif isinstance(value, list):
                for i, item in enumerate(value):
                    if isinstance(item, str):
                        value[i] = sub_var(findalls(item), item, cache)
                    elif isinstance(item, dict):
                        replace_variables(item, cache)
  • 递归遍历字典和列表,替换字符串中的变量占位符。

🧪 六、示例演示

if __name__ == '__main__':
    http_request = HttpRequest()
    response = http_request.send_request(
        method='GET',
        route='/api/data',
        RequestData={'param1': 'value1'}
    )
    print(response.status_code)
    print(response.text)
  • 运行后会在控制台看到详细的请求日志,并在 Allure 报告中查看完整的请求信息。

Allure 报告示例:

✅ 七、总结

通过对 requests 的封装,我们实现了如下功能:

  • 多种 HTTP 方法支持
  • 动态变量替换
  • 日志记录
  • Allure 报告集成
  • 参数自动合并处理

这种封装方式不仅提高了代码的复用性和可维护性,也大大提升了测试脚本的健壮性和可读性。

📌 其余参考

1. 安装依赖包

pip install requests allure-python-commons python-dotenv

2. 缓存模块参考(common/cache.py)

class Cache:
    def __init__(self):
        self._store = {}

    def get(self, key, default=None):
        return self._store.get(key, default)

    def set(self, key, value):
        self._store[key] = value

cache = Cache()

3. 正则模块参考(common/regular.py)

import re

def findalls(text):
    return re.findall(r'\$\{(.*?)\}', text)

def sub_var(matches, text, cache):
    for var in matches:
        value = cache.get(var, '')
        text = text.replace('${%s}' % var, str(value))
    return text
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值