我应该如何登录我的 pytest 插件?

Nir*_*Izr 5 python testing logging pytest

我正在构建一个 pytest 插件,目前我通过在插件文件的顶部添加类似于以下两行的内容来登录:

logging.basicConfig()
log = logging.getLogger(PLUGIN_NAME)
Run Code Online (Sandbox Code Playgroud)

但是,这似乎没有考虑 pytest 配置(通过命令行选项或 ini 文件),例如日志文件路径、记录器格式等。

我可以手动将它们复制到我的basicConfig电话中,但我认为 pytest 和第三方插件之间有更好的工具用于日志记录,不是吗?

我在 pytest 的文档和代码中发现了相当多的日志记录参考,但所有这些都在讨论捕获测试日志。我对记录pytest 插件本身很感兴趣。

hoe*_*ing 4

  1. 正如您已经发现的,已被弃用,并且一旦重构所有用法,py就会从依赖项中删除;如果可能的话,不要使用任何其他模块。pytestpypy.logpy

  2. pytest没有任何用于在测试之外进行日志记录的配置或通用功能。LoggingPluginin_pytest.logging用于“实时”打印日志(一旦它们在测试中发出;请参阅我的其他答案以获取示例)。其余的_pytest.logging内容用于捕获测试中的日志记录。

因此,只需以与任何其他程序相同的方式配置插件中的日志记录:创建一个名为您的插件的记录器,附加处理程序,然后就可以开始了。一个示例插件:

import logging
import pytest


class SpamPlugin:

    name = 'spam-plugin'

    def __init__(self, config):
        # turn debug prints on only if "-vv" or more passed
        level = logging.DEBUG if config.option.verbose > 1 else logging.INFO
        logging.basicConfig(level=level)
        self.logger = logging.getLogger(self.name)

    def pytest_sessionstart(self, session):
        self.logger.debug('session started')

    def pytest_sessionfinish(self, session, exitstatus):
        self.logger.debug('session finished')


@pytest.mark.trylast
def pytest_configure(config):
    config.pluginmanager.register(SpamPlugin(config), SpamPlugin.name)
Run Code Online (Sandbox Code Playgroud)

测试输出:

import logging
import pytest


class SpamPlugin:

    name = 'spam-plugin'

    def __init__(self, config):
        # turn debug prints on only if "-vv" or more passed
        level = logging.DEBUG if config.option.verbose > 1 else logging.INFO
        logging.basicConfig(level=level)
        self.logger = logging.getLogger(self.name)

    def pytest_sessionstart(self, session):
        self.logger.debug('session started')

    def pytest_sessionfinish(self, session, exitstatus):
        self.logger.debug('session finished')


@pytest.mark.trylast
def pytest_configure(config):
    config.pluginmanager.register(SpamPlugin(config), SpamPlugin.name)
Run Code Online (Sandbox Code Playgroud)

当然,如果您愿意,您可以重用为实时日志定义的格式,尽管这需要更多的工作,因为您必须自己配置根记录器:

import logging
import pytest
from _pytest.config import create_terminal_writer
from _pytest.logging import ColoredLevelFormatter, get_actual_log_level, get_option_ini


class SpamPlugin:

    name = 'spam-plugin'

    def __init__(self, config):
        level = get_actual_log_level(config, 'log_cli_level')
        fmt = get_option_ini(config, 'log_cli_format')
        datefmt = get_option_ini(config, 'log_cli_date_format')
        formatter = ColoredLevelFormatter(create_terminal_writer(config), fmt, datefmt=datefmt)
        handler = logging.StreamHandler()
        handler.setLevel(level)
        handler.setFormatter(formatter)
        logging.getLogger().setLevel(level)
        logging.getLogger().addHandler(handler)
        self.logger = logging.getLogger(self.name)

    def pytest_sessionstart(self, session):
        self.logger.debug('session started')

    def pytest_sessionfinish(self, session, exitstatus):
        print()
        self.logger.debug('session finished')


@pytest.mark.trylast
def pytest_configure(config):
    config.pluginmanager.register(SpamPlugin(config), SpamPlugin.name)
Run Code Online (Sandbox Code Playgroud)

测试输出。尽管此处不可见,但日志级别的颜色将与实时日志中的颜色相同,因为ColoredLevelFormatter

$ pytest -vv
DEBUG:spam-plugin:session started
=================================== test session starts ====================================
platform darwin -- Python 3.6.4, pytest-3.7.1, py-1.5.3, pluggy-0.7.1 -- /Users/hoefling/.virtualenvs/stackoverflow/bin/python3.6
cachedir: .pytest_cache
rootdir: /Users/hoefling/projects/private/stackoverflow/so-51737378, inifile: pytest.ini
collected 2 items

test_spam.py::test_foo PASSED                                                         [ 50%]
test_spam.py::test_bar PASSED                                                         [100%]
DEBUG:spam-plugin:session finished


================================= 2 passed in 0.01 seconds =================================
Run Code Online (Sandbox Code Playgroud)