В процессе тестирования часто возникает необходимость проверить, что определенный код генерирует ожидаемое исключение. В pytest это можно сделать с помощью контекстного менеджера pytest.raises
.
Допустим, вы хотите убедиться, что деление на ноль в Python вызывает ZeroDivisionError
. Вы можете использовать pytest.raises
для этого:
import pytest
def test_divide_by_zero():
with pytest.raises(ZeroDivisionError):
result = 1 / 0
Если в блоке with
не возникнет исключение ZeroDivisionError
, тест будет считаться не пройденным.
Иногда необходимо удостовериться, что исключение генерирует конкретное сообщение. Это можно сделать, передав аргумент match
:
def test_divide_by_zero_message():
with pytest.raises(ZeroDivisionError, match="division by zero"):
result = 1 / 0
Если исключение возникло, но его сообщение не соответствует заданному регулярному выражению, тест тоже будет считаться не пройденным.
Иногда после перехвата исключения вы можете захотеть провести дополнительные проверки. pytest.raises
возвращает объект исключения, который можно дополнительно анализировать:
def test_divide_by_zero_analysis():
with pytest.raises(ZeroDivisionError) as exc_info:
result = 1 / 0
assert "zero" in str(exc_info.value)
В некоторых ситуациях вы можете захотеть удостовериться, что исключение не возникает в блоке кода. В pytest нет прямого способа сделать это, но вам может помочь стандартная конструкция:
def test_no_exception():
try:
result = 1 / 1 # Этот код не должен вызывать исключение
except Exception as e:
pytest.fail(f"Unexpected exception raised: {e}")
В данном примере, если возникнет исключение, тест будет считаться не пройденным благодаря вызову pytest.fail()
.
Вы можете использовать кортеж для перечисления нескольких исключений, которые могут возникнуть:
def test_multiple_exceptions():
with pytest.raises((TypeError, ValueError)):
result = int("not_a_number")
В этом примере тест пройдет, если возникнет либо TypeError
, либо ValueError
.
Вы можете сочетать параметризацию тестов с ожиданием исключений для создания набора тестовых случаев:
import pytest
@pytest.mark.parametrize("input, exception_type", [
("not_a_number", ValueError),
(None, TypeError)
])
def test_parametrized_exceptions(input, exception_type):
with pytest.raises(exception_type):
result = int(input)
Такой подход позволяет удобно тестировать различные сценарии ошибок в одном тестовом методе.
При использовании pytest.raises
важно помещать в блок with
только ту часть кода, где действительно ожидается исключение. Это помогает избежать ложных срабатываний, когда исключение возникает не там, где ожидалось.
# Неправильно
with pytest.raises(ValueError):
some_setup_function()
result = int("not_a_number")
# Правильно
some_setup_function()
with pytest.raises(ValueError):
result = int("not_a_number")
Обработка исключений является ключевой частью многих тестовых сценариев, особенно когда вы хотите убедиться, что ваш код корректно реагирует на ошибки или аномальные ситуации. pytest предоставляет простой и интуитивно понятный механизм для тестирования и анализа исключений, что делает ваш код тестов более ясным и надежным.
Содержание: