Как можно тестировать обработку собственных исключений?

Для тестирования обработки собственных исключений можно использовать:
  • pytest.raises(): Проверяет, что код внутри блока with вызывает ожидаемое исключение.
  • try...except блоки в тестах: Позволяют перехватывать исключения и проверять их атрибуты (сообщение, тип и т.д.).
  • assert: Для проверки, что сообщение исключения соответствует ожидаемому значению.
Важно проверять не только факт выброса исключения, но и его тип, сообщение (если оно имеет значение), а также то, что программа корректно обрабатывает это исключение, например, выполняет необходимые действия по логированию или уведомлению.

Тестирование обработки собственных исключений в Python - важная часть обеспечения надежности и предсказуемости кода. Вот несколько подходов, которые можно использовать:

  • assertRaises контекстный менеджер: Это наиболее распространенный и рекомендуемый способ. Он позволяет ожидать, что определенный блок кода вызовет конкретное исключение.
    
    import unittest
    
    class MyCustomError(Exception):
        pass
    
    def my_function(x):
        if x < 0:
            raise MyCustomError("Значение должно быть положительным")
        return x * 2
    
    class TestMyFunction(unittest.TestCase):
        def test_my_function_raises_error(self):
            with self.assertRaises(MyCustomError) as context:
                my_function(-1)
    
            self.assertEqual(str(context.exception), "Значение должно быть положительным") # Проверка сообщения об ошибке
        
        def test_my_function_works(self):
            self.assertEqual(my_function(5), 10)
    
    if __name__ == '__main__':
        unittest.main()
          

    В этом примере:

    • MyCustomError - наше пользовательское исключение.
    • assertRaises(MyCustomError) - контекстный менеджер, который проверяет, что внутри блока with будет выброшено исключение MyCustomError.
    • context.exception позволяет получить доступ к экземпляру исключения, чтобы проверить его атрибуты, например, сообщение.
  • assertRaisesRegex: Похож на assertRaises, но позволяет проверять, что сообщение об ошибке соответствует определенному регулярному выражению.
    
    import unittest
    import re
    
    class MyCustomError(Exception):
        pass
    
    def my_function(x):
        if x < 0:
            raise MyCustomError(f"Неверное значение: {x}")
        return x * 2
    
    class TestMyFunction(unittest.TestCase):
        def test_my_function_raises_error_with_regex(self):
            with self.assertRaisesRegex(MyCustomError, r"Неверное значение: -1"):
                my_function(-1)
          

    Здесь проверяется, что сообщение об ошибке содержит строку "Неверное значение: -1".

  • try...except в тестах (менее предпочтительно): Можно использовать блоки try...except внутри тестовой функции, но этот подход менее читабелен и может быть сложнее в поддержке.
    
    import unittest
    
    class MyCustomError(Exception):
        pass
    
    def my_function(x):
        if x < 0:
            raise MyCustomError("Значение должно быть положительным")
        return x * 2
    
    class TestMyFunction(unittest.TestCase):
        def test_my_function_raises_error_try_except(self):
            try:
                my_function(-1)
                self.fail("MyCustomError не был вызван")  # Если исключение не было вызвано, тест должен провалиться
            except MyCustomError as e:
                self.assertEqual(str(e), "Значение должно быть положительным")
          

    Этот подход менее предпочтителен, так как делает тест более многословным и сложным для понимания.

Дополнительные советы:

  • Тестируйте различные сценарии: Убедитесь, что исключение вызывается в разных ситуациях, в которых оно должно возникать.
  • Проверяйте сообщения об ошибках: Сообщение об ошибке должно быть информативным и помогать в отладке. Включайте в тесты проверки сообщений об ошибках.
  • Используйте моки (Mocking): Если код, вызывающий исключение, зависит от внешних ресурсов, используйте моки, чтобы изолировать код и сделать тесты более надежными и быстрыми.
  • Избегайте "глотания" исключений в тестах: Убедитесь, что вы действительно проверяете, что исключение вызывается, а не случайно обрабатываете его без проверки.
  • Помните про покрытие кода: Инструменты анализа покрытия кода помогут вам убедиться, что все возможные пути выполнения кода, включая обработку исключений, протестированы.
0