接口自动化项目实战(8):请求封装

8. 请求封装

8.1. 主函数

复制代码
 def run_main(self, name, url, case_name, header, method, cookies=None, file=None, **kwargs):
        """
        接口请求主函数
        :param url: 请求地址
        :param data: 请求体
        :param header: 请求头
        :param method: 请求方法
        :return: response的json格式
        """
        try:
            # 收集日志报告信息
            logs.info(f"接口名称:{name}")
            logs.info(f"接口请求地址:{url}")
            logs.info(f"请求方法:{method}")
            logs.info(f"测试用例名称:{case_name}")
            logs.info(f"请求头:{header}")
            logs.info(f"Cookies:")
            # 请求参数处理
            req_params = json.dumps(kwargs, ensure_ascii=False)
            if 'data' in kwargs.keys():
                logs.info(f'请求参数:{kwargs}')
            elif 'json' in kwargs.keys():
                logs.info(f'请求参数:{kwargs}')
            elif 'params' in kwargs.keys():
                logs.info(f'请求参数:{kwargs}')
        except Exception as e:
            logs.error(e)
        response = self.send_request(method=method, url=url, headers=header, cookies=cookies, files=file, verify=False,
                                     **kwargs)
        return response

8.1.1. 代码详解

  1. 方法签名部分

    def run_main(self, name, url, case_name, header, method, cookies=None, file=None, **kwargs):

|------------|----|-----------|------------------------------------------------------------------------------------------------------------------------|
| 参数 | 必填 | 说明 | 示例 |
| self | - | 类实例本身 | - |
| name | ✅ | 接口名称 | "用户登录" |
| url | ✅ | 请求地址 | "http://127.0.0.1:8787/dar/user/login " |
| case_name | ✅ | 测试用例名称 | "TC001_正确登录" |
| header | ✅ | 请求头字典 | {"Content-Type": "application/json"} |
| method | ✅ | HTTP 请求方法 | "POST" / "GET" |
| cookies | ❌ | Cookie 字典 | {"session": "abc123"} |
| file | ❌ | 上传文件 | files 格式对象 |
| **kwargs | ❌ | 其他请求参数 | json={}, data={}, params={} |

  • **kwargs 的灵活性: 动态接收请求参数 (data/json/params)

    GET 请求 - 传递 params

    run_main(..., params={"page": 1, "size": 10})

    POST 请求 - 表单提交

    run_main(..., data={"username": "test", "password": "123"})

    POST 请求 - JSON 提交

    run_main(..., json={"user": {"name": "test"}})

  1. 日志收集部分

    logs.info(f"接口名称:{name}") # 【输出】接口名称:用户登录
    logs.info(f"接口请求地址:{url}") # 【输出】接口请求地址:http://127.0.0.1:8787/...
    logs.info(f"请求方法:{method}") # 【输出】请求方法:POST
    logs.info(f"测试用例名称:{case_name}") # 【输出】测试用例名称:TC001_正确登录
    logs.info(f"请求头:{header}") # 【输出】请求头:{"Content-Type": "..."}
    logs.info(f"Cookies:") # 【输出】Cookies:(后面会显示具体值)

作用: 在测试报告中记录完整的请求信息,方便问题排查。


复制代码
req_params = json.dumps(kwargs, ensure_ascii=False)

作用:

  • 将 kwargs 字典转为 JSON 字符串

  • ensure_ascii=False:支持中文不乱码

    if 'data' in kwargs.keys():
    logs.info(f'请求参数:{kwargs}')
    elif 'json' in kwargs.keys():
    logs.info(f'请求参数:{kwargs}')
    elif 'params' in kwargs.keys():
    logs.info(f'请求参数:{kwargs}')

  • 检查 kwargs 中包含哪种类型的请求参数

  • 使用 if-elif 结构,因为一次请求只会用一种方式传参

三种传参方式的区别:

|--------|------------------|-----------|-----------------------------------|----------------|
| 参数名 | 支持 HTTP 方法 | 数据位置 | Content-Type 常用类型 | 适用场景 |
| params | GET / POST / ... | URL 查询字符串 | 无需指定 | 接口查询、分页、筛选 |
| data | POST / PUT | 请求体(表单) | application/x-www-form-urlencoded | 传统表单提交、登录、简单参数 |
| json | POST / PUT | 请求体(JSON) | application/json | 接口自动化、前后端分离接口 |

  1. 发送请求部分

|-----------------|------|-----------------------------|
| 传递的参数 | 来源 | 说明 |
| method=method | 方法参数 | HTTP 方法(POST/GET 等) |
| url=url | 方法参数 | 请求地址 |
| headers=header | 方法参数 | 请求头(注意变量名:header → headers) |
| cookies=cookies | 方法参数 | Cookie 信息 |
| files=file | 方法参数 | 上传文件(注意变量名:file → files) |
| verify=False | 硬编码 | 忽略 HTTPS 证书验证 |
| **kwargs | 可变参数 | 解包传递 data/json/params 等 |

**kwargs 的解包传递

复制代码
# 假设调用时传入
run_main(..., data={"user_name": "test", "passwd": "123"})

# kwargs 变成
kwargs = {"data": {"user_name": "test", "passwd": "123"}}

# **kwargs 解包后相当于
send_request(..., data={"user_name": "test", "passwd": "123"})

8.2. send_request 方法

基于 requests****库封装的接口请求通用方法 ,主要用于自动化测试(结合pytest)中发送 HTTP 请求、自动处理 Cookie、记录日志、异常捕获,是接口自动化测试的核心工具类方法。

整体功能概述

  1. 发送任意类型的 HTTP 请求(GET/POST/PUT/DELETE 等)
  2. 自动提取响应中的 Cookie 并保存,下次请求可复用
  3. 记录请求日志(Cookie、响应信息)
  4. 捕获各类请求异常,打印错误日志并终止测试用例
  5. 持久化存储 Cookie 到 YAML 文件

8.2.1. 代码详解

复制代码
def send_request(self, **kwargs):
  • 定义 :类的成员方法,self代表类实例本身
  • 参数**kwargs 可变关键字参数,核心作用 :接收 HTTP 请求的所有参数(url/method/headers/data/json等),让方法支持所有类型的 HTTP 请求

复制代码
cookie = {}
session = requests.Session()
result = None
  1. cookie = {}:空字典,用于封装最终要传递的 Cookie 请求头
  2. session = requests.Session():创建requests会话对象
    • 核心优势:会话会自动管理 Cookie(保持登录状态),比直接用requests.get()更稳定
  1. result = None:初始化响应结果变量,避免未赋值就返回的报错

复制代码
try:
    result = session.request(**kwargs)
  • try:异常捕获代码块,包裹核心请求逻辑
  • session.request(**kwargs)发送 HTTP 请求
    • 动态解包kwargs参数,等价于直接写session.request(method="GET", url="xxx")
    • 返回值:接口响应对象(包含状态码、响应体、Cookie、响应头)

复制代码
set_cookie = requests.utils.dict_from_cookiejar(result.cookies)
  • 功能:将响应中的 CookieJar 格式转为 Python 字典
  • result.cookies:响应自带的 Cookie,格式是RequestsCookieJar(无法直接使用)
  • dict_from_cookiejarrequests工具方法,专门转换 Cookie 格式

复制代码
if set_cookie:
    cookie['Cookie'] = set_cookie
  • 判断:如果响应中存在 Cookie(非空)
  • 封装:将 Cookie 字典存入cookie字典的Cookie键中
  • 目的:拼接成HTTP 请求头标准格式,下次请求可直接携带

复制代码
self.read.write_yaml_data(set_cookie)
logs.info(f"cookie:{cookie}")
  1. self.read.write_yaml_data(set_cookie)
    • 调用类中封装的 YAML 工具方法,将 Cookie 持久化保存到 YAML 文件
    • 作用:跨用例、跨脚本复用 Cookie(保持登录态)
  1. logs.info():打印 INFO 级别的日志,记录 Cookie 内容,方便调试

复制代码
logs.info(f'接口实际返回信息:{result}')
  • 打印接口响应对象日志,包含:状态码、响应头、响应体等,用于排查接口问题

复制代码
except requests.exceptions.ConnectionError:
logs.error(f'接口连接服务器异常!')
pytest.fail('接口请求异常,可能是request的连接数过多,或者请求速度过快导致程序报错')
  • 异常类型:连接异常(服务器无响应、网络不通、域名错误、连接超时)
  • 操作:打印 ERROR 日志 + 用pytest.fail()强制终止测试用例,并给出明确报错原因

复制代码
except requests.exceptions.HTTPError:
logs.error(f"http异常")
pytest.fail("http请求异常")
  • 异常类型:HTTP 协议异常(如 4xx 客户端错误、5xx 服务端错误触发的异常)
  • 作用:专门捕获 HTTP 状态码不合法的问题

复制代码
except requests.exceptions.RequestException as e:
logs.error(e)
pytest.fail('请求异常,请检查系统或数据是否正常')
  • 异常类型requests通用异常基类(兜底捕获)
  • 作用:捕获所有未被前面分支处理的请求异常(超时、参数错误、重定向异常等)
  • as e:接收异常详情,打印具体错误信息

复制代码
return result
  • 最终返回接口响应对象
  • 调用方可以通过返回值获取:result.text(响应文本)、result.json()(响应 JSON)、result.status_code(状态码)
相关推荐
好家伙VCC2 小时前
**发散创新:用 Rust实现数据编织(DataWrangling)的高效流式处理架构**在现
java·开发语言·python·架构·rust
编程大师哥2 小时前
Python 爬虫
python
用户0190047832672 小时前
Python中:可迭代对象、迭代器、生成器、生成器表达式、列表推导式
python
2401_876907522 小时前
《Python深度学习》
开发语言·python·深度学习
BatyTao2 小时前
Python从零起步6-文件及操作
python
学习指针路上的小学渣2 小时前
requests笔记
后端·python
_深海凉_2 小时前
LeetCode热题100-反转链表
python·leetcode·链表
筋斗云计算3 小时前
SONiC-mgmt系列3:编写测试用例代码
测试用例·sonic·sonic-mgmt
gc_22993 小时前
学习python使用Ultralytics的YOLO26进行姿势估计的基本用法
python·ultralytics·yolo26·姿势估计