版本与验证范围:本文依据 2026-10-02 核验留存的官方 stable 文档快照;缓存页面没有明确标注精确的 pytest 发布版本。文中的 pytest 3.3、3.4 属于历史行为变更说明,不代表本文要求使用这些旧版本;实验性 API 的限制按原文保留。配置片段保留原文的 TOML 与 INI 两种写法,使用前需按目标 pytest 版本核对配置文件格式。本站未运行或实测文中的命令与示例,代码和示例输出均逐字保留自原文,不代表本站运行结果。
pytest 会自动捕获 WARNING 及以上级别的日志消息,并在每个失败测试的报告中,用独立的区域显示这些日志,方式与捕获的 stdout 和 stderr 相同。
不带任何选项运行:
pytest
失败测试会显示为:
----------------------- Captured stdlog call ----------------------
test_reporting.py 26 WARNING text going to logger
----------------------- Captured stdout call ----------------------
text going to stdout
----------------------- Captured stderr call ----------------------
text going to stderr
==================== 2 failed in 0.02 seconds =====================
默认情况下,每条捕获的日志消息都会显示模块、行号、日志级别和消息内容。
如果需要,可以通过传入相应的格式选项,将日志格式和日期格式设置为 logging 模块支持的任意格式:
pytest --log-format="%(asctime)s %(levelname)s %(message)s" \
--log-date-format="%Y-%m-%d %H:%M:%S"
失败测试会显示为:
----------------------- Captured stdlog call ----------------------
2010-04-10 14:48:44 WARNING text going to logger
----------------------- Captured stdout call ----------------------
text going to stdout
----------------------- Captured stderr call ----------------------
text going to stderr
==================== 2 failed in 0.02 seconds =====================
这些选项也可以通过配置文件进行自定义:
TOML 配置示例(原文)
[pytest]
log_format = "%(asctime)s %(levelname)s %(message)s"
log_date_format = "%Y-%m-%d %H:%M:%S"
INI 配置示例(原文)
[pytest]
log_format = %(asctime)s %(levelname)s %(message)s
log_date_format = %Y-%m-%d %H:%M:%S
可以通过 --log-disable={logger_name} 禁用指定的日志记录器。这个参数可以传入多次:
pytest --log-disable=main --log-disable=testing
此外,还可以使用以下选项,完全关闭失败测试报告中对已捕获内容的展示,包括 stdout、stderr 和日志:
pytest --show-capture=no
caplog 测试夹具
在测试内部,可以更改所捕获日志消息的日志级别。caplog fixture(测试夹具)提供了这一能力:
def test_foo(caplog):
caplog.set_level(logging.INFO)
默认情况下,设置的是根日志记录器的级别。为方便使用,也可以设置任意日志记录器的日志级别:
def test_foo(caplog):
caplog.set_level(logging.CRITICAL, logger="root.baz")
这样设置的日志级别会在测试结束时自动恢复。
也可以使用上下文管理器,在 with 代码块内临时更改日志级别:
def test_bar(caplog):
with caplog.at_level(logging.INFO):
pass
同样,默认情况下受影响的是根日志记录器的级别;也可以改为更改任意其他日志记录器的级别:
def test_bar(caplog):
with caplog.at_level(logging.CRITICAL, logger="root.baz"):
pass
最后,测试运行期间发送给日志记录器的所有日志,都可以通过这个 fixture 访问,既包括 logging.LogRecord 实例,也包括最终的日志文本。如果需要对消息内容进行断言,这会很有用:
def test_baz(caplog):
func_under_test()
for record in caplog.records:
assert record.levelname != "CRITICAL"
assert "wally" not in caplog.text
日志记录的所有可用属性,请参阅 logging.LogRecord 类。
如果只需要确认某些消息确实以指定的日志记录器名称、严重程度和消息内容被记录,也可以使用 record_tuples:
def test_foo(caplog):
logging.getLogger().info("boo %s", "arg")
assert caplog.record_tuples == [("root", logging.INFO, "boo arg")]
可以调用 caplog.clear(),清空测试中已经捕获的日志记录:
def test_something_with_clearing_records(caplog):
some_method_that_creates_log_records()
caplog.clear()
your_test_method()
assert ["Foo"] == [rec.message for rec in caplog.records]
caplog.records 属性只包含当前阶段的记录。因此,在 setup 阶段中,它只包含 setup 日志;call 和 teardown 阶段也是如此。
要访问其他阶段的日志,请使用 caplog.get_records(when) 方法。例如,如果要确保使用某个 fixture 的测试不会记录任何警告,可以在 teardown 期间,检查 setup 和 call 阶段的日志记录:
@pytest.fixture
def window(caplog):
window = create_window()
yield window
for when in ("setup", "call"):
messages = [
x.message for x in caplog.get_records(when) if x.levelno == logging.WARNING
]
if messages:
pytest.fail(f"warning messages encountered during testing: {messages}")
完整的 API 见 pytest.LogCaptureFixture。
警告
caplog fixture 会向根日志记录器添加一个处理器,以便捕获日志。如果在测试期间修改根日志记录器,例如使用 logging.config.dictConfig,这个处理器可能会被移除,导致无法捕获任何日志。为避免这种情况,应确保对根日志记录器的任何配置,都只在现有处理器的基础上添加处理器。
实时日志
将配置选项 log_cli 设置为 true 后,pytest 会在日志记录产生时,直接将其输出到控制台。
可以通过传入 --log-cli-level 指定日志级别,级别等于或高于该值的日志记录会打印到控制台。这个设置接受 logging 文档中列出的日志级别名称或数值。
此外,还可以指定 --log-cli-format 和 --log-cli-date-format。这两个选项分别对应 --log-format 和 --log-date-format,未提供时会默认使用后两者的值,但它们只作用于控制台日志处理器。
所有 CLI 日志选项也都可以在配置文件中设置。选项名称如下:
如果需要将整个测试套件的日志调用记录到文件,可以传入 --log-file=/path/to/log/file。默认情况下,这个日志文件以写入模式打开,这意味着每次测试会话都会覆盖它。如果希望改为以追加模式打开文件,可以传入 --log-file-mode=a。请注意,无论日志文件的位置是通过 CLI 传入,还是在配置文件中声明,其中的相对路径始终相对于当前工作目录进行解析。
也可以通过传入 --log-file-level 指定日志文件的日志级别。这个设置接受 logging 文档中列出的日志级别名称或数值。
此外,还可以指定 --log-file-format 和 --log-file-date-format。这两个选项分别与 --log-format 和 --log-date-format 相同,但作用于日志文件的日志处理器。
所有日志文件选项也都可以在配置文件中设置。选项名称如下:
可以调用 set_log_path() 动态自定义 log_file 路径。这项功能被视为实验性功能。请注意,set_log_path() 会遵循 log_file_mode 选项。
自定义颜色
启用彩色终端输出后,日志级别会以不同颜色显示。通过 add_color_level(),可以修改默认颜色,也可以为自定义日志级别设置颜色。例如:
@pytest.hookimpl(trylast=True)
def pytest_configure(config):
logging_plugin = config.pluginmanager.get_plugin("logging-plugin")
# Change color on existing log level
logging_plugin.log_cli_handler.formatter.add_color_level(logging.INFO, "cyan")
# Add color to a custom log level (a custom log level `SPAM` is already set up)
logging_plugin.log_cli_handler.formatter.add_color_level(logging.SPAM, "blue")
警告
这项功能及其 API 被视为实验性功能,可能在不同版本之间发生变化,且不会预先发出弃用通知。
版本说明
这项功能引入时,是作为 pytest-catchlog 插件的直接替代品,两者相互冲突。对 pytest-capturelog 的向后兼容 API 在引入这项功能时已被移除。因此,如果出于这一原因仍需要 pytest-catchlog,可以在配置文件中添加以下内容,禁用内置功能:
TOML 配置示例(原文)
[pytest]
addopts = ["-p", "no:logging"]
INI 配置示例(原文)
[pytest]
addopts = -p no:logging
pytest 3.4 中的不兼容变更
这项功能是在 3.3 中引入的。根据社区反馈,3.4 中进行了若干不兼容变更:
-
除非通过配置选项
log_level或命令行选项--log-level明确要求,否则不再更改日志级别。这样,用户可以自行配置日志记录器对象。设置log_level会指定全局捕获的日志级别。因此,如果某个测试需要比该级别更低的日志,请使用caplog.set_level();否则,这个测试就容易失败。 -
实时日志现在默认禁用,可以通过将配置选项
log_cli设置为true来启用。启用后,输出详细程度会提高,以便看到每个测试的日志。
如果想部分恢复 3.3 版本的日志行为,可以在配置文件中添加以下选项:
TOML 配置示例(原文)
[pytest]
log_cli = true
log_level = "NOTSET"
INI 配置示例(原文)
[pytest]
log_cli = true
log_level = NOTSET
有关促成这些变更的讨论,更多细节见 #3013。
原文版权与许可:Copyright © 2015, holger krekel and pytest-dev team。原页提供的 License(许可证) 入口予以保留。本页为中文译文;具体许可条款以项目原始许可证为准。












暂无评论内容