caplog默认只捕获WARNING及以上级别日志(WARNING、ERROR、CRITICAL);需显式调用caplog.set_level("INFO")等才能捕获INFO或DEBUG日志,且仅作用于当前测试函数。

caplog能捕获哪些日志级别?
caplog 默认只捕获 WARNING 及以上级别的日志(即 WARNING、ERROR、CRITICAL),不会自动捕获 INFO 或 DEBUG。这不是 bug,而是 pytest 的默认日志级别配置所致。
- 测试中调用
logger.info("hello")后,caplog.records为空,是正常现象 - 若需捕获
INFO,必须显式设置日志级别:在测试函数参数中加caplog并调用caplog.set_level("INFO") -
caplog.set_level()作用于当前测试函数内所有 logger(包括 root logger 和命名 logger) - 级别名不区分大小写,但推荐用全大写字符串,如
"DEBUG"
注意: caplog.set_level("INFO") 不会改变全局 logger 配置,仅影响本次测试中 caplog 的捕获行为。
如何断言某条日志的 levelno 或levelname?
日志记录对象(caplog.records[0])是 logging.LogRecord 实例,可直接访问其属性:
-
record.levelno是整数(DEBUG=10,INFO=20,WARNING=30…) -
record.levelname是字符串("INFO","ERROR") - 推荐用
levelname断言,语义清晰且不易出错
def test_login_failure(caplog):
caplog.set_level("WARNING")
authenticate(username="bad", password="wrong") # 触发 warning 日志
assert len(caplog.records) == 1
assert caplog.records[0].levelname == "WARNING"
assert "invalid credentials" in caplog.text
-
caplog.text是所有日志的拼接字符串(含换行),适合做子串匹配 -
caplog.messages是纯消息列表(不含级别/时间),但无法区分同消息不同级别 - 避免仅依赖
caplog.text断言级别——它不包含级别标识,只含格式化后的内容
为什么 caplog.records 为空,但 logging.getLogger().warning() 明明执行了?
常见原因有三个:
caplogfixture 未被测试函数声明为参数 → pytest 不会注入它,caplog是未定义变量忘记调用
caplog.set_level(),而日志级别低于默认捕获阈值(比如只写了INFO却没设级)日志被其他 handler 拦截(例如项目初始化时调用了
logging.basicConfig()且 level 设得过高,或添加了 NullHandler)确保测试函数签名包含
def test_xxx(caplog):在触发日志前调用
caplog.set_level("INFO")(或对应所需级别)-
检查项目启动代码是否覆盖了 root logger 的 level,必要时在测试前重置:
logging.getLogger().setLevel(logging.DEBUG)
Secure Python Code Sandbox下载安全 Python 代码沙箱:在隔离的沙箱中执行任意 Python 代码,预装 requests、NumPy、pandas 库。返回 stdout、stderr。
多个 logger 场景下 caplog 还管用吗?
caplog 默认捕获 root logger 及其所有子 logger 的日志,只要它们没被单独配置 handler 或禁用传播(propagate=False)。
如果业务代码用
logging.getLogger("myapp.api"),它仍会被caplog捕获但如果该 logger 设置了
propagate=False且没配 handler,日志就“消失”了,caplog.records自然为空多个 logger 共享同一
caplogfixture,无需额外 setup检查 logger 是否设置了
propagate=False(尤其在模块级 logger 初始化时)不要为测试中的 logger 单独 addHandler,否则会绕过
caplog若必须隔离 logger 行为,可用
caplog.at_level("DEBUG", logger="myapp.api")上下文管理器,比全局set_level更精准
实际调试时,最常被忽略的是 propagate 和 caplog 参数缺失——这两点一错,日志就“看不见”。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










