Иногда нужно прогнать разные входные данные и проверить, что в одних случаях код работает, а в других — выбрасывает нужное исключение.
✖️ Делать отдельный тест под каждый кейс — не всегда разумно.
Для этого удобно комбинировать
pytest.mark.parametrize с contextlib.nullcontext:
from contextlib import nullcontext as does_not_raise
import pytest
from pytest import raises
@pytest.mark.parametrize(
["x", "y", "expectation"],
[
(3, 2, does_not_raise()),
(0, 1, does_not_raise()),
(1, 0, raises(ZeroDivisionError)),
(1, "0", raises(TypeError)),
],
)
def test_division(x, y, expectation):
with expectation:
x / y
Подход простой:
🔵 если исключения не ожидается — используется
nullcontext🔵 если ожидается —
pytest.raises(...)🔵 все сценарии живут в одном параметризованном тесте
Метод описан в документации PyTest и обсуждался на StackOverflow, но на практике о нём знают не все.
Хорошо подходит, когда:
🔵 проверки на исключения однотипные
🔵 не хочется раздувать тестовый набор
🔵 нужно аккуратно покрыть все ветки кода
nullcontext — не самая очевидная часть стандартной библиотеки, но алиас does_not_raise делает намерение теста понятным с первого взгляда.📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека питониста
#буст