import pytest
def test_exception():
with pytest.raises(ValueError):
raise ValueError("Неверное значение")
def test_specific_exception_message():
with pytest.raises(ValueError, match=".*Неверное.*"):
raise ValueError("Неверное значение")
`pytest.raises` принимает тип исключения и, опционально, строку для сравнения с сообщением исключения через параметр `match`. Убедитесь, что код, который должен вызвать исключение, находится внутри блока `with`.
Для проверки исключений в pytest
существует несколько основных подходов. Наиболее распространенные и рекомендуемые:
pytest.raises
как контекстный менеджер:
Это наиболее идиоматичный и читаемый способ. Используйте pytest.raises
как контекстный менеджер (with pytest.raises(...)
). Код, который должен вызывать исключение, помещается внутрь блока with
. pytest
автоматически проверит, что было выброшено ожидаемое исключение. Если исключение не выбрасывается или выбрасывается исключение другого типа, тест завершится неудачей.
import pytest
def my_function(x):
if x < 0:
raise ValueError("x must be non-negative")
return x * 2
def test_my_function_raises_valueerror():
with pytest.raises(ValueError):
my_function(-1)
def test_my_function_works_correctly():
assert my_function(2) == 4
В этом примере проверяется, что my_function(-1)
выбрасывает исключение ValueError
.
Вы можете получить доступ к объекту исключения:
def test_my_function_raises_valueerror_with_message():
with pytest.raises(ValueError) as excinfo:
my_function(-1)
assert "x must be non-negative" in str(excinfo.value)
excinfo
содержит информацию об исключении, например, его тип, значение и traceback.
pytest.raises
как функция-обертка:
Реже используемый способ, но все еще валидный. pytest.raises
может использоваться как функция-обертка для вызова функции, которая, как ожидается, выбросит исключение. Этот способ полезен, когда необходимо, например, в цикле протестировать вызовы функций с различными аргументами, которые должны вызывать исключения.
def test_my_function_raises_valueerror_functional():
with pytest.raises(ValueError):
pytest.raises(ValueError, my_function, -1) # Устаревший способ
# более предпочтительный способ (аналогично контекстному менеджеру):
with pytest.raises(ValueError):
my_function(-1)
Важно отметить, что в последнем примере использование pytest.raises(ValueError, my_function, -1)
немного устарело и рекомендуется использовать контекстный менеджер для большей читаемости и ясности.
match
параметр для проверки сообщения исключения (Python 3.10+):
Начиная с Python 3.10, в pytest.raises
добавлен параметр match
, позволяющий проверять, соответствует ли сообщение исключения заданному регулярному выражению. Это упрощает проверку конкретных деталей исключения.
import pytest
def test_my_function_raises_valueerror_with_message_regex():
with pytest.raises(ValueError, match="x must be non-negative"):
my_function(-1)
def test_my_function_raises_valueerror_with_message_regex_partial():
with pytest.raises(ValueError, match="non-negative"): # проверяется частичное совпадение
my_function(-1)
try...except
(Не рекомендуется):
Хотя можно использовать блоки try...except
для перехвата исключений, это не рекомендуется для написания тестов в pytest
. Этот подход менее явный и может приводить к пропуску ошибок, если исключение выбрасывается в неожиданном месте или если тип исключения не совпадает. Использование pytest.raises
делает намерение более ясным и обеспечивает лучшую обработку ошибок.
# Не рекомендуется!
def test_my_function_raises_valueerror_bad():
try:
my_function(-1)
except ValueError:
pass
else:
assert False, "ValueError was not raised"
В целом, использование pytest.raises
как контекстного менеджера является предпочтительным способом проверки исключений в pytest
. Он обеспечивает четкость, читаемость и надежность при написании тестов.