12

Как протестировать, что функция Python вызывает исключение?

18

Как написать модульный тест, который завершится неудачей только в том случае, если функция не выбрасывает ожидаемое исключение?

5 ответ(ов)

5

Код из моего предыдущего ответа можно упростить до следующего:

def test_afunction_throws_exception(self):
    self.assertRaises(ExpectedException, afunction)

Если функция принимает аргументы, просто передайте их в assertRaises следующим образом:

def test_afunction_throws_exception(self):
    self.assertRaises(ExpectedException, afunction, arg1, arg2)
0

Ваш код должен следовать следующему шаблону (это стиль теста из модуля 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 только проверяет, было ли вызвано какое-либо исключение.

0

В вашем коде вы пытаетесь протестировать функцию 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

Таким образом, тест пройдет успешно, и результат будет именно тем, что вы ожидали!

Если у вас возникли еще вопросы или требуется дополнительная помощь, не стесняйтесь задавать их!

0

Если вы не нашли подробного объяснения о том, как проверить, возникает ли конкретное исключение из списка допустимых с использованием менеджера контекста, или о других деталях исключения, я добавлю свою версию (проверено на 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])
0

Если вы используете 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 мы проверяем, что это исключение возникает, и совпадает с ожидаемым сообщением.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь