Есть ли способ для pytest, чтобы проверить, была ли сделана запись в журнале на уровне ошибки или выше? - PullRequest
3 голосов
/ 15 января 2020

Python 3.8.0, pytest 5.3.2, ведение журнала 0.5.1.2.

Мой код имеет ввод l oop, и для предотвращения полного сбоя программы я улавливаю все исключения, которые получают бросить, зарегистрировать их как критические, сбросить состояние программы и продолжать работу. Это означает, что тест, который вызывает такое исключение, не будет полностью провален, пока результат будет тем, что ожидается. Это может произойти, если ошибка была побочным эффектом тестового кода, но не влияла на основные тестируемые логи c. Я все еще хотел бы знать, что тест выявляет ошибку, вызывающую ошибку, однако.

Большинство выполненных мною поисков показывают результаты о том, как отображать логи в pytest, что я и делаю но я не могу выяснить, есть ли способ представить журналы в тесте, чтобы я мог провалить любой тест с журналом на уровне ошибок или критических.

Редактировать: это минимальное Пример неудачной попытки:

test.py:

import subject
import logging
import pytest

@pytest.fixture(autouse=True)
def no_log_errors(caplog):
    yield  # Run in teardown
    print(caplog.records)
    # caplog.set_level(logging.INFO)
    errors = [record for record in caplog.records if record.levelno >= logging.ERROR]
    assert not errors

def test_main():
    subject.main()
    # assert False

subject.py:

import logging
logger = logging.Logger('s')
def main():
    logger.critical("log critical")

Запуск python3 -m pytest test.py проходит без ошибок. Раскомментирование оператора assert завершает тест без ошибок и печатает [] в стандартный вывод и log critical в стандартный вывод.

Редактировать 2:

Я обнаружил, почему это не удается. Из документации по caplog:

Атрибут caplog.records содержит записи только текущего этапа, поэтому на этапе настройки он содержит только журналы настройки, то же самое с фазами вызовов и разрыва

Тем не менее, то, что я должен был найти в первый раз:

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

@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(
                "warning messages encountered during testing: {}".format(messages)
            )

Однако это все равно не имеет значения, и print(caplog.get_records("call")) по-прежнему возвращает []

Ответы [ 2 ]

4 голосов
/ 15 января 2020

Вы можете создать что-то подобное, используя приспособление caplog

. Вот пример кода из документации, который делает некоторые утверждения на основе уровней:

def test_baz(caplog):
    func_under_test()
    for record in caplog.records:
        assert record.levelname != "CRITICAL"
    assert "wally" not in caplog.text

, поскольку record s являются стандартными типами записей журналирования, вы можете использовать все, что вам нужно там

вот один способ, которым вы могли бы сделать это ~ более автоматически с помощью приспособления autouse :

@pytest.fixture(autouse=True)
def no_logs_gte_error(caplog):
    yield
    errors = [record for record in caplog.get_records('call') if record.levelno >= logging.ERROR]
    assert not errors

(отказ от ответственности: я - главный разработчик Pytest)

1 голос
/ 15 января 2020

Вы можете использовать модуль unittest.mock (даже если используете pytest) и monkey-patch любой функции / метода, которые вы используете для регистрации. Затем в вашем тесте вы можете получить некоторое утверждение, которое не будет выполнено, если, скажем, будет вызван logging.error.

Это было бы краткосрочным решением. Но может также случиться так, что ваш дизайн получит выгоду от большего разделения, так что вы можете легко протестировать ваше приложение без ревностного try ... except блока, улавливающего / подавляющего практически все.

...