pytest 如何在扩展的插件中修改日志格式
- pytest 日志格式配置
- 如何在插件或者代码运行时修改日志格式
pytest 日志格式配置
Pytest 支持通过配置的方式修改日志格式,查看 pytest 帮助命令即可查看支持的配置参数。 其中与日志相关的配置有以下几项:
pytest --help
usage: pytest [options] [file_or_dir] [file_or_dir] [...]
logging:
--log-level=LEVEL level of messages to catch/display.
Not set by default, so it depends on the root/parent log handler's effective level, where it is "WARNING" by default.
--log-format=LOG_FORMAT
log format as used by the logging module.
--log-date-format=LOG_DATE_FORMAT
log date format as used by the logging module.
--log-cli-level=LOG_CLI_LEVEL
cli logging level.
--log-cli-format=LOG_CLI_FORMAT
log format as used by the logging module.
--log-cli-date-format=LOG_CLI_DATE_FORMAT
log date format as used by the logging module.
--log-file=LOG_FILE path to a file when logging will be written to.
--log-file-level=LOG_FILE_LEVEL
log file logging level.
--log-file-format=LOG_FILE_FORMAT
log format as used by the logging module.
--log-file-date-format=LOG_FILE_DATE_FORMAT
log date format as used by the logging module.
--log-auto-indent=LOG_AUTO_INDENT
Auto-indent multiline messages passed to the logging module. Accepts true|on, false|off or an integer.
[pytest] ini-options in the first pytest.ini|tox.ini|setup.cfg file found:
log_level (string): default value for --log-level
log_format (string): default value for --log-format
log_date_format (string):
default value for --log-date-format
log_cli (bool): enable log display during test run (also known as "live logging").
log_cli_level (string):
default value for --log-cli-level
log_cli_format (string):
default value for --log-cli-format
log_cli_date_format (string):
default value for --log-cli-date-format
log_file (string): default value for --log-file
log_file_level (string):
default value for --log-file-level
log_file_format (string):
default value for --log-file-format
log_file_date_format (string):
default value for --log-file-date-format
log_auto_indent (string):
default value for --log-auto-indent
pytest 支持在命令行中指定日志参数格式,例pytest --log-format="%(asctime)s %(levelname)s [%(filename)s:%(lineno)s] %(message)s" --log-date-format="%Y-%m-%d %H:%M:%S"
也支持pytest.ini
文件配置
[pytest]
log_cli = True
log_cli_level = DEBUG
log_date_format = %Y-%m-%d %H:%M:%S
log_format = %(asctime)s %(levelname)s [%(filename)s:%(lineno)s] %(message)s
如何在插件或者代码运行时修改日志格式
我碰到的一种场景是,我们自己开发了一个集成了实际业务场景的pytest插件pytest-XXX,这个对接了几十个测试项目,现在想要修改测试报告中的日志格式。 如果按照官方的配置进行修改的话,那么需要修改N多项目,并且无法保证没有修改遗漏,并且以后新增的项目也需要增加这个配置。
那么如何在插件中修改pytest的日志格式呢?
走读pytest源码 https://docs.pytest.org/en/7.1.x/_modules/_pytest/logging.html 发现 pytest 的loggging模块中,声明了通过hook的方式注册了一个日志插件 logging-plugin
,而这个日志插件正是pytest打印日志的插件
@hookimpl(trylast=True)
def pytest_configure(config: Config) -> None:
config.pluginmanager.register(LoggingPlugin(config), "logging-plugin")
class LoggingPlugin:
"""Attaches to the logging module and captures log messages for each test."""
def __init__(self, config: Config) -> None:
# Report logging.
self.formatter = self._create_formatter(
get_option_ini(config, "log_format"),
get_option_ini(config, "log_date_format"),
get_option_ini(config, "log_auto_indent"),
)
...
self.log_level = get_log_level_for_setting(config, "log_level")
self.caplog_handler = LogCaptureHandler()
self.caplog_handler.setFormatter(self.formatter)
self.report_handler = LogCaptureHandler()
self.report_handler.setFormatter(self.formatter)
...
self.log_cli_handler = _LiveLoggingNullHandler()
...
知道了原理之后,那么我们就可以在加载我们插件(pytest-XXX)的地方,动态修改pytest注册的logging插件中的日志输出格式配置。
# 配置文件
@pytest.hookimpl(trylast=True)
def pytest_configure(config):
mgr = config.pluginmanager
logging_plugin = mgr.get_plugin("logging-plugin")
log_formatter = logging_plugin._create_formatter(
"%(asctime)s %(levelname)s [%(filename)s:%(lineno)s] %(message)s",
"%Y-%m-%d %H:%M:%S",
False,
)
logging_plugin.log_cli_handler.setFormatter(log_formatter)
logging_plugin.caplog_handler.setFormatter(log_formatter)
logging_plugin.report_handler.setFormatter(log_formatter)
这样,无论前面配置生成的logging handler 格式如何,最终的日志格式都会被修改为我们预期的格式。