Сообщить об ошибке.

Функция pytest.raises() модуля pytest в Python

Проверка ожидаемых исключений в pytest

Иногда, при тестировании кода необходимо убедится, что заложенные в коде приложения ожидаемые исключения появляются именно в ожидаемых ситуациях. Фреймворк pytest дает такую возможность по средствам использования контекстного менеджера pytest.raises(Exc, match=None).

  • Аргумент Exc: объект исключения Exception или кортеж объектов Exception;
  • Аргумент match: если указано, то это строка, содержащая регулярное выражение или объект регулярного выражения, который проверяется на соответствие строковому представлению исключения с помощью re.search(). Может содержать специальные символы, шаблон может быть сначала экранирован с помощью re.escape().

    Аргумент match используется только тогда, когда pytest.raises() используется в качестве диспетчера контекста. При использовании pytest.raises() в качестве функции можно использовать: pytest.warns(Exc, func, match="passed on").match("my pattern")

Например:

import pytest

def test_zero_division():
    with pytest.raises(ZeroDivisionError):
        1 / 0

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

def test_recursion_depth():
    with pytest.raises(RuntimeError) as excinfo:

        def f():
            f()

        f()
    assert "maximum recursion" in str(excinfo.value)

Переменная excinfo - это ни что иное как экземпляр класса ExceptionInfo, которым обертывается вызванное исключение. Наиболее интересными его атрибутами являются ExceptionInfo.type, ExceptionInfo.value и ExceptionInfo.traceback.

Чтобы проверить, что строковому представлению исключения (аналогично методу TestCase.assertRaisesRegexp модуля unittest) соответствует регулярное выражение, то менеджеру контекста можно передать параметр match:

import pytest

def myfunc():
    raise ValueError("Exception 123 raised")

def test_match():
    with pytest.raises(ValueError, match=r".* 123 .*"):
        myfunc()

Регулярное выражение аргумента match сопоставляется с функцией re.search, так что в приведенном выше примере match='123' также сработает.

Есть и альтернативный вариант использования pytest.raises(), когда передается функция, которая которая должна выполняться с заданными *args и **kwargs и проверять, что вызвано указанное исключение:

pytest.raises(ExpectedException, func, *args, **kwargs)

В случае падения теста, pytest выведет полезную информацию, например, о том, что исключение не вызвано (no exception) или вызвано неверное исключение (wrong exception).

Обратите внимание, что декоратор @pytest.mark.xfail() также принимает аргумент raises, который особым образом проверяет само падение теста, а не просто возникновение какого-то исключения:

@pytest.mark.xfail(raises=IndexError)
def test_f():
    f()

Использование функции pytest.raises() скорее всего пригодится, когда тестируются исключения, генерируемые собственным кодом, а применение декоратора @pytest.mark.xfail() для тестовой функции, лучше подойдет для документирования незафиксированных (когда тест описывает то, что "должно бы" происходить) или зависимых от чего-либо падений кода.