在 pytest 中通过继承 requests.Session 并重写 request() 方法实现请求日志记录,配合 function-scoped fixture 提供带日志的独立 session 实例,使用 test_name 动态命名 logger 实现日志隔离,并缓存 response._raw_content 以确保异常时仍可输出响应体。

怎么在 pytest 里让 requests 请求自动打日志
直接封装 requests.Session,重写 request() 方法,在发请求前后记录 URL、方法、headers、body、状态码和响应体。别用全局 monkey patch,容易污染其他测试;也别只靠 logging.basicConfig() 开关,那压根不抓 request 内容。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 继承
requests.Session,在子类的request()中调用super().request(),再用logging.debug()记录入参和返回值 - 把日志级别设为
DEBUG,并在 pytest 启动时加--log-level=DEBUG,否则看不到 - 响应体太大时(比如下载文件或大 JSON),用
response.content[:1024]截断,避免日志爆炸 - 敏感字段如
Authorization、Cookie建议脱敏:用正则把Bearer [a-zA-Z0-9\-_]+\.?替换成Bearer ***
如何让每个 pytest 测试用例都自带带日志的 session 实例
用 pytest 的 fixture 最稳妥。定义一个 session_with_logging fixture,scope 设为 function,每次测试都拿干净实例,互不干扰。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- fixture 返回自定义 Session 子类实例,不要返回模块级单例
- 在 fixture 里配置默认 headers(如
Content-Type: application/json)和超时(timeout=(3, 10)),避免测试里重复写 - 如果需要 mock 某些请求,用
responses或pytest-responses,它们能兼容你封装的 Session —— 关键是 mock 要在 fixture setup 阶段注册,而不是测试函数里 - 别在 fixture 里做登录获取 token 这类副作用操作,那会让测试耦合;token 应该由单独的 fixture 提供,再注入到 session 中
为什么 response.json() 报错时日志里看不到原始响应内容
因为 response.json() 抛异常时,response 对象可能已被释放或 body 已读取过,再访问 response.text 会返回空或报 ValueError: I/O operation on closed file。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 在 Session 子类的
request()里,统一调用response.content(bytes)并缓存到response._raw_content属性,后续无论是否调用.json()都能回溯 - 捕获
JSONDecodeError后,用repr(response._raw_content[:200])打日志,比response.text更可靠 - 对非 2xx 响应,强制读一次
response.content并缓存,否则某些服务(如 Flask TestClient)会在响应离开上下文后清空 body
pytest 日志输出太杂乱,怎么按测试函数隔离请求日志
pytest 默认把所有日志混在一起输出,看不出哪条 log 属于哪个 test。得靠 logger name + pytest 的 test_name 上下文绑定。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 在 fixture 中创建 logger 时,用
logging.getLogger(f"api.{test_name}"),其中test_name从request.node.name获取 - 给 handler 加
Formatter,格式里包含%(name)s,这样每条日志开头就是api.test_login_success这种可识别前缀 - 避免用 root logger,否则第三方库(如 urllib3)的日志也会挤进来;明确指定 logger name 并禁用 propagate
- 如果用
pytest --log-file=xxx.log,记得在 formatter 里加换行和时间戳,不然多线程跑时日志会粘连


















