pytest默认捕获stdout和logging输出,需加-s参数显示print、--log-cli-level=info显示日志,用request.fixture动态命名logger可定位日志行号,caplog fixture比直接getlogger更可靠。

pytest里print没输出,logging也不见踪影?
默认情况下,pytest会捕获所有stdout和logging输出,测试通过就直接丢弃——不是你的logging.info()没执行,是它被吞了。必须显式启用日志捕获并配置级别,否则连WARNING都看不到。
- 加
-s参数可释放print,但对logging无效 - 必须用
--log-cli-level=INFO(或更高)才能在控制台看到日志 - 若用
pytest.ini配置,写log_cli_level = INFO,别漏掉log_cli = true - 注意:
DEBUG级日志默认不显示,除非你明确设为DEBUG
如何让每条日志自动带上测试函数名和行号?
硬编码logger = logging.getLogger(__name__)在测试文件里不管用——pytest会把测试函数动态导入到临时命名空间,__name__变成pytest或conftest,失去上下文。得靠pytest的request fixture动态注入。
- 在测试函数参数中加
request,用request.node.name获取当前测试名 - 用
logging.getLogger(f"test.{request.node.name}")创建独立logger - 配合格式器
%(name)s:%(lineno)d,就能定位到具体哪行日志 - 避免全局
basicConfig,它会被pytest覆盖;改用logging.basicConfig(level=logging.INFO, format="%(name)s:%(lineno)d %(message)s")并在conftest.py的pytest_configure钩子里调用
测试失败时怎么自动打出完整日志?
pytest只在失败时展示断言错误和traceback,默认不翻出之前捕获的日志——这意味着你可能错过关键中间状态。得靠--log-cli-level配合--tb=short以外的选项,再加一点钩子。
- 运行时加
--log-cli-level=DEBUG --tb=short,失败时会把整个捕获日志追加在traceback后面 - 更稳的做法:在
conftest.py里写pytest_runtest_makereport钩子,检测report.when == "call" and report.failed,然后手动logging.getLogger().handlers[0].stream.write(...)刷出缓存日志 - 注意:如果用了
caplogfixture,它的text属性只含本次测试的日志,适合断言日志内容,但不自动输出到终端
为什么用caplog比直接logging.getLogger()更可靠?
caplog是pytest内置fixture,它不依赖全局logger配置,也不受basicConfig干扰,专为测试可观测性设计。直接调logging.getLogger()容易撞上根logger的level限制、handler缺失或被其他测试污染。
-
caplog.set_level(logging.DEBUG)只影响当前测试,不影响其他用例 -
assert "expected" in caplog.text比assert "expected" in some_logger_buffer稳定得多 - 如果要验证日志是否没发生,用
assert caplog.records == [],比检查空字符串更准确 - 注意:
caplog默认只捕获rootlogger,若你用logging.getLogger("my.module"),得提前caplog.handler.level = logging.DEBUG并确保该logger有handler
日志层级、handler绑定、fixture作用域——这三个地方出问题,日志就悄无声息地消失。别假设“写了log就一定看得见”。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











