Как протестировать, что функция Python вызывает исключение?
Как написать модульный тест, который завершится неудачей только в том случае, если функция не выбрасывает ожидаемое исключение?
5 ответ(ов)
Код из моего предыдущего ответа можно упростить до следующего:
def test_afunction_throws_exception(self):
self.assertRaises(ExpectedException, afunction)
Если функция принимает аргументы, просто передайте их в assertRaises
следующим образом:
def test_afunction_throws_exception(self):
self.assertRaises(ExpectedException, afunction, arg1, arg2)
Ваш код должен следовать следующему шаблону (это стиль теста из модуля unittest):
def test_afunction_throws_exception(self):
try:
afunction()
except ExpectedException:
pass
except Exception:
self.fail('было вызвано неожиданное исключение')
else:
self.fail('ExpectedException не было вызвано')
На Python < 2.7 такая конструкция полезна для проверки конкретных значений в ожидаемом исключении. Функция assertRaises
из модуля unittest только проверяет, было ли вызвано какое-либо исключение.
В вашем коде вы пытаетесь протестировать функцию square_value
, которая вызывает TypeError
, если на вход подается некорректный тип данных. Однако, в текущем виде теста вы получаете ошибку, потому что TypeError
вызывается сразу при выполнении функции, а не в контексте проверки.
Вместо этого, вы должны использовать lambda
, чтобы отложить выполнение функции до момента, когда assertRaises
сможет обработать исключение. Таким образом, ваш тест должен выглядеть следующим образом:
self.assertRaises(TypeError, lambda: df.square_value(self.false_int))
Теперь ваш тест будет правильно работать и не выдавать ошибку, потому что TypeError
будет вызван именно как ожидаемое исключение внутри assertRaises
. После внесенных изменений, при запуске теста вы получите следующее:
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
Таким образом, тест пройдет успешно, и результат будет именно тем, что вы ожидали!
Если у вас возникли еще вопросы или требуется дополнительная помощь, не стесняйтесь задавать их!
Если вы не нашли подробного объяснения о том, как проверить, возникает ли конкретное исключение из списка допустимых с использованием менеджера контекста, или о других деталях исключения, я добавлю свою версию (проверено на Python 3.8).
Если я просто хочу проверить, что функция вызывает, например, исключение TypeError
, я напишу:
with self.assertRaises(TypeError):
function_raising_some_exception(parameters)
Если я хочу проверить, что функция вызывает либо TypeError
, либо IndexError
, то напишу:
with self.assertRaises((TypeError, IndexError)):
function_raising_some_exception(parameters)
А если мне нужны дополнительные детали о возбужденном исключении, я могу поймать его в контексте следующим образом:
# Здесь я ловлю любое исключение
with self.assertRaises(Exception) as e:
function_raising_some_exception(parameters)
# Здесь я проверяю фактический тип исключения (но также могу
# проверить и другие свойства этого конкретного исключения,
# например, его сообщение или значения, сохраненные в исключении)
self.assertTrue(type(e.exception) in [TypeError, MatrixIsSingular])
Если вы используете Python 3, чтобы проверить возникновение исключения с сообщением об ошибке, вы можете воспользоваться контекстным менеджером assertRaises
и передать сообщение в качестве аргумента msg
. Вот пример того, как это сделать:
import unittest
def ваша_функция():
raise RuntimeError('сообщение вашей ошибки')
class ВашТестКейс(unittest.TestCase):
def test(self):
with self.assertRaises(RuntimeError, msg='сообщение вашей ошибки'):
ваша_функция()
if __name__ == '__main__':
unittest.main()
В этом примере метод your_function
вызывает исключение RuntimeError
с заданным сообщением. В тесте test
с помощью assertRaises
мы проверяем, что это исключение возникает, и совпадает с ожидаемым сообщением.
Как правильно проверить, что исключение возникает в pytest?
Вручную вызов (бросание) исключения в Python
Поймать и вывести полный трейсбек исключения в Python без остановки/выхода из программы
Как напечатать исключение в Python?
Как проверить, существует ли переменная?