Как проверить, что функция Python генерирует исключение?
Как написать тест, который не проходит, только если функция не выдает
ожидаемое исключение?
Краткий ответ:
Используйте метод self.assertRaises
в качестве менеджера контекста:
def test_1_cannot_add_int_and_str(self):
with self.assertRaises(TypeError):
1 + '1'
Демонстрация
Метод наилучшей практики довольно легко продемонстрировать в оболочке Python.
Библиотека unittest
В Python 2.7 или 3:
import unittest
В Python 2.6 вы можете установить бэкпорт библиотеки unittest
2.7, которая называется unittest2 , и просто псевдоним, такой как unittest
:
import unittest2 as unittest
Пример тестов
Теперь вставьте в вашу оболочку Python следующий тест безопасности типов Python:
class MyTestCase(unittest.TestCase):
def test_1_cannot_add_int_and_str(self):
with self.assertRaises(TypeError):
1 + '1'
def test_2_cannot_add_int_and_str(self):
import operator
self.assertRaises(TypeError, operator.add, 1, '1')
Test one использует assertRaises
в качестве диспетчера контекста, который гарантирует, что ошибка будет правильно обнаружена и устранена во время записи.
Мы могли бы также написать без диспетчера контекста, см. Тест два Первым аргументом будет тип ошибки, который вы ожидаете вызвать, второй аргумент, функция, которую вы тестируете, а остальные аргументы и аргументы ключевых слов будут переданы этой функции.
Я думаю, что гораздо проще, удобочитаемее и легче обслуживать, чем просто использовать менеджер контекста.
Запуск тестов
Для запуска тестов:
unittest.main(exit=False)
В Python 2.6 вам, вероятно, потребуется следующее :
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromTestCase(MyTestCase))
И ваш терминал должен вывести следующее:
..
----------------------------------------------------------------------
Ran 2 tests in 0.007s
OK
<unittest2.runner.TextTestResult run=2 errors=0 failures=0>
И мы видим, что, как мы и ожидаем, попытка добавить 1
и '1'
приведет к TypeError
.
Для более подробного вывода, попробуйте это:
unittest.TextTestRunner(verbosity=2).run(unittest.TestLoader().loadTestsFromTestCase(MyTestCase))