You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pytest如何捕获指定测试用例生成的日志并在测试结束后获取存储

pytest指定测试用例日志捕获与获取方案

以下是三种主流实现方式,可根据你的日志输出场景选择:

方法1:使用capsys/capfd fixture捕获stdout/stderr输出的日志

  • 适用场景:日志直接打印到标准输出/错误流的场景
  • 操作方式:在测试用例参数中引入capsys或capfd fixture,测试运行结束后调用readouterr()方法获取输出内容
    示例代码:
def test_target_case(capsys):
    # 测试逻辑执行,过程中产生日志打印
    run_your_test_logic()
    # 测试执行完成后捕获所有输出
    captured = capsys.readouterr()
    # stdout输出存在captured.out,stderr输出存在captured.err
    case_log = captured.out
    # 自定义存储逻辑
    with open("target_case.log", "w", encoding="utf-8") as f:
        f.write(case_log)

capfd和capsys的区别是前者可捕获文件描述符级别的输出,适配更多第三方日志库的打印场景

方法2:使用caplog fixture捕获logging模块输出的日志

  • 适用场景:日志通过Python标准库logging模块输出的场景,是最常用的日志捕获方案
  • 操作方式:在测试用例参数中引入caplog fixture,直接访问其属性获取所有日志记录
    示例代码:
import logging
import pytest

@pytest.mark.your_target_mark
def test_target_case(caplog):
    # 可设置捕获的最低日志级别,也可指定只捕获特定模块的日志
    caplog.set_level(logging.INFO, logger="your_business_module")
    # 测试逻辑执行,过程中通过logging输出日志
    run_your_test_logic()
    # 获取结构化日志记录(每条为logging.LogRecord对象)
    all_log_records = caplog.records
    # 获取已格式化的纯文本日志内容
    log_text = caplog.text
    # 自定义存储逻辑
    with open("target_case.log", "w", encoding="utf-8") as f:
        f.write(log_text)

方法3:自定义pytest hook实现指定用例日志自动持久化

  • 适用场景:需要批量捕获指定标记用例的日志、统一管理日志存储路径与格式的场景
  • 操作方式:在conftest.py中实现pytest运行钩子,测试用例前后动态添加/移除专属日志处理器
    示例代码:
import logging
from pathlib import Path
import pytest

@pytest.hookimpl(tryfirst=True)
def pytest_runtest_setup(item):
    # 只给打了capture_log标记的指定用例添加日志处理器
    if not item.get_closest_marker("capture_log"):
        return
    # 生成用例专属日志路径
    case_name = item.name
    log_path = Path("./test_logs") / f"{case_name}.log"
    log_path.parent.mkdir(exist_ok=True)
    # 自定义日志格式与处理器
    handler = logging.FileHandler(log_path, encoding="utf-8")
    formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
    handler.setFormatter(formatter)
    # 挂载处理器到根日志器
    logging.getLogger().addHandler(handler)
    # 把处理器存在用例对象上,后续清理用
    item.case_log_handler = handler

@pytest.hookimpl(trylast=True)
def pytest_runtest_teardown(item):
    # 测试用例结束后移除处理器,避免日志重复输出
    if hasattr(item, "case_log_handler"):
        logging.getLogger().removeHandler(item.case_log_handler)
        item.case_log_handler.close()

测试运行结束后,所有带@pytest.mark.capture_log标记的指定用例日志都会自动存储在./test_logs目录下,以用例名命名

内容的提问来源于stack exchange,提问作者username

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 06:57:04