caplog默认只捕获WARNING及以上级别日志,需调用caplog.set_level("INFO")等显式设置级别;断言应优先使用caplog.records中LogRecord字段,避免依赖易变的caplog.text。

直接用 caplog 就能捕获日志,但默认只捕获 WARNING 及以上级别——这是绝大多数人第一次写断言就失败的根本原因。
为什么 caplog 里找不到你 expect 的 INFO 日志?
pytest 默认将 root logger 级别设为 WARNING,而 caplog 仅捕获当前 logger 级别允许输出的日志。即使你的代码调用了 logger.info("xxx"),它也会被过滤掉。
- 在测试函数开头加
caplog.set_level("INFO"),或更宽泛地设为"DEBUG" - 若测试涉及多个 logger(比如模块级 logger),需显式指定名称:
caplog.set_level("INFO", logger="my_module") - 不推荐改全局 root logger 级别,可能干扰其他测试
如何精准断言某条日志是否出现?
caplog.records 是一个 LogRecord 列表,每条记录含 levelname、message、name 等属性;caplog.text 是拼接后的字符串,适合模糊匹配但不可靠。
- 查日志级别和消息内容:
assert "user not found" in [r.message for r in caplog.records if r.levelno == logging.WARNING] - 查是否恰好有一条 ERROR:
assert len([r for r in caplog.records if r.levelno == logging.ERROR]) == 1 - 避免用
assert "ERROR" in caplog.text——它可能匹配到日志消息里的单词 "error",而非真正的 ERROR 级别
caplog 和 logging.basicConfig 冲突怎么办?
如果项目启动时调用了 logging.basicConfig()(比如在 __main__.py 或 conftest.py 中),它会创建一个默认 handler 并锁定 root logger 的 level,导致 caplog.set_level() 失效。
立即学习“Python免费学习笔记(深入)”;
- 在 conftest.py 的
pytest_configure钩子中重置 root logger:logging.getLogger().setLevel(logging.NOTSET) - 或在测试前手动移除已有 handler:
logging.getLogger().handlers.clear() - 更稳妥的做法:所有模块 logger 都显式声明(
logger = logging.getLogger(__name__)),不依赖 root logger
真正麻烦的不是怎么捕获,而是日志传播链——比如你 mock 了某个函数,但它内部又调用了另一个模块的 logger,那个 logger 可能没被 caplog 覆盖到。这时候得看 caplog.get_records("call") 或直接 inspect caplog.handler.records。


















