Как управлять лесозаготовками

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 =====================

По умолчанию каждое перехваченное сообщение журнала показывает модуль, номер строки, уровень журнала и сообщение.

При желании формат журнала и даты может быть задан любой, который поддерживает модуль протоколирования, путем передачи определенных параметров форматирования:

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 =====================

Эти параметры также могут быть настроены через файл pytest.ini:

[pytest]
log_format = %(asctime)s %(levelname)s %(message)s
log_date_format = %Y-%m-%d %H:%M:%S

Далее можно полностью отключить отчет о перехваченном содержимом (stdout, stderr и журналы) при неудачных тестах:

pytest --show-capture=no

крепление капсюля

Внутри тестов можно изменить уровень журнала для перехваченных сообщений журнала. Это поддерживается приспособлением caplog:

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

Наконец, все журналы, отправленные в регистратор во время выполнения теста, становятся доступными на приспособлении в виде экземпляров 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 он содержит только журналы установки, то же самое с этапами call и teardown.

Чтобы получить доступ к журналам других этапов, используйте метод caplog.get_records(when). Например, если вы хотите убедиться, что тесты, использующие определенное приспособление, никогда не выдают предупреждений, вы можете просмотреть записи для этапов 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.

Живые журналы

Установив параметр конфигурации log_cli в значение true, pytest будет выводить записи протоколирования по мере их появления непосредственно в консоль.

Вы можете указать уровень протоколирования, для которого записи журнала с равным или более высоким уровнем будут выводиться на консоль, передав --log-cli-level. Этот параметр принимает имена уровней протоколирования или числовые значения, как показано в logging’s documentation.

Кроме того, вы можете указать --log-cli-format и --log-cli-date-format, которые зеркально отражают и по умолчанию соответствуют --log-format и --log-date-format, если не указаны, но применяются только к обработчику логирования консоли.

Все опции журнала CLI также можно задать в конфигурационном INI-файле. Имена опций следующие:

  • log_cli_level

  • log_cli_format

  • log_cli_date_format

Если вам нужно записать в файл журнал вызовов всего набора тестов, вы можете передать --log-file=/path/to/log/file. Этот файл журнала открывается в режиме записи, что означает, что он будет перезаписываться при каждом сеансе запуска тестов. Обратите внимание, что относительные пути для расположения лог-файла, переданные в CLI или объявленные в конфигурационном файле, всегда определяются относительно текущего рабочего каталога.

Вы также можете указать уровень протоколирования для файла журнала, передав параметр --log-file-level. Этот параметр принимает имена уровней протоколирования или числовые значения, как показано в logging’s documentation.

Дополнительно можно указать --log-file-format и --log-file-date-format, которые равны --log-format и --log-date-format, но применяются к обработчику логирования файла журнала.

Все параметры файла журнала можно также установить в конфигурационном INI-файле. Имена опций следующие:

  • log_file

  • log_file_level

  • log_file_format

  • log_file_date_format

Вы можете вызвать set_log_path() для динамической настройки пути к log_file. Эта функциональность считается экспериментальной.

Настройка цветов

Уровни журнала окрашиваются, если включен цветной вывод терминала. Изменение цветов по умолчанию или наложение цвета на пользовательские уровни журнала поддерживается через add_color_level(). Пример:

@pytest.hookimpl
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, и они конфликтуют друг с другом. API обратной совместимости с pytest-capturelog был отменен, когда была введена эта функция, поэтому если по этой причине вам все еще нужен pytest-catchlog, вы можете отключить внутреннюю функцию, добавив ее в pytest.ini:

[pytest]
    addopts=-p no:logging

Несовместимые изменения в pytest 3.4

Эта функция была представлена в 3.3, и некоторые несовместимые изменения были внесены в 3.4 после отзывов сообщества:

  • Уровни журналов больше не изменяются, если они явно не запрошены конфигурацией log_level или опциями командной строки --log-level. Это позволяет пользователям самим настраивать объекты логгеров. Настройка log_level устанавливает уровень, который фиксируется глобально, поэтому если для конкретного теста требуется более низкий уровень, чем этот, используйте функциональность caplog.set_level(), иначе тест будет склонен к сбоям.

  • Live Logs теперь отключен по умолчанию и может быть включен установкой параметра конфигурации log_cli в значение true. При включении этого параметра увеличивается точность, так что протоколирование каждого теста становится видимым.

  • Live Logs теперь отправляются в sys.stdout и больше не требуют опции командной строки -s для работы.

Если вы хотите частично восстановить поведение протоколирования версии 3.3, вы можете добавить эту опцию в ваш файл ini:

[pytest]
log_cli=true
log_level=NOTSET

Более подробно об обсуждении, которое привело к этим изменениям, можно прочитать в issue #3013.

Вернуться на верх