Перейти к основному содержимому

Функции, которые вызывают исключения

Функция Python, получившая неверные входные данные, должна сообщить об этом, вызвав исключение: при успехе она возвращает результат, при неудаче вызывает ошибку — например, ValueError, — которая объясняет, что пошло не так.

Тест для такой функции должен проверять оба пути: при верных входных данных возвращается правильное значение и ничего не вызывается, а при неверных входных данных исключение действительно вызывается — функция, которая молча принимает неверные данные, тоже содержит ошибку.

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


Хороший путь

Для верных входных данных ничего дополнительного писать не нужно. Вызовите функцию, затем сравните значение. Если вместо этого вызов вызовет исключение, оно само завершит тест, и отчёт это покажет — заранее проверять это не нужно.

Верные входные данные, без исключения

safe_divide(10, 2) должна вернуть 5 и не должна вызывать исключение. Сначала идёт вызов; неожиданное исключение завершило бы тест прямо здесь. Только после этого сравнивается значение.

Prompt
Напиши тестовый файл на Python с функцией safe_divide, которая вызывает ValueError при делении на ноль, а в остальных случаях возвращает частное. Напиши тест для хорошего пути: safe_divide(10, 2) должна вернуть 5 — сначала вызов, затем проверка значения через assert; неожиданное исключение само по себе провалит тест. Покажи вывод pytest -v.
Вывод: полная программа на Python
Valid input, no exception

Плохой путь

Вторая половина контракта: неверные входные данные должны вызывать исключение. Вызов помещается в блок with pytest.raises(ValueError) — если функция вместо исключения возвращает число, тест проваливается.

Важно указать класс исключения: блок принимает только ValueError, поэтому другая, неожиданная ошибка всё равно провалит тест.

Неверные входные данные должны вызывать исключение

Деление на ноль должно завершаться ошибкой. pytest.raises(ValueError) оборачивает вызов safe_divide(10, 0). Функция, как и обещано, вызывает исключение, поэтому тест проходит.

Prompt
Напиши тест на Python для плохого пути функции safe_divide: вызов с делителем 0 должен вызывать ValueError. Помести вызов в блок with pytest.raises(ValueError). Покажи вывод pytest -v.
Вывод: полная программа на Python
Bad input must raise

Таблица с want_error

Оба пути помещаются в один параметризованный тест: дайте каждому случаю флаг want_error, который говорит, ожидается ли исключение. Значение want для такого случая равно None, потому что у случая, вызывающего исключение, нет значения для сравнения.

Тест сначала смотрит на want_error. Ожидаемая ошибка проверяется с помощью pytest.raises, и на этом всё; в остальных случаях значение сравнивается как обычно.

Хорошие и плохие случаи в одной таблице

Четыре случая: три обычных деления и одно деление на ноль с want_error=True. Один параметризованный тест покрывает весь контракт функции, и все четыре случая проходят.

Prompt
Напиши параметризованный тест на Python для safe_divide, в котором у каждого случая есть id, два входных значения, ожидаемое значение и флаг want_error. Для случая с ошибкой используй pytest.raises(ValueError), для остальных сравнивай значение. Добавь три обычных случая и одно деление на ноль. Покажи вывод pytest -v.
Вывод: полная программа на Python
Good and bad cases in one table