Как работает метод `assertRaises()` в `unittest`?

Метод assertRaises() в unittest используется для проверки того, что код вызывает определенное исключение. Он принимает тип исключения, вызываемый объект (функцию, метод или другой вызываемый объект) и аргументы, которые будут переданы этому вызываемому объекту. Если исключение указанного типа не возникает при вызове объекта, тест завершится неудачей. По сути, это контекстный менеджер, который ожидает выброса определенного исключения.

Метод assertRaises() в модуле unittest языка Python используется для проверки того, что при выполнении определенного кода выбрасывается ожидаемое исключение. Это важный инструмент для написания надежных и устойчивых тестов, гарантирующих, что ваш код правильно обрабатывает исключительные ситуации.

Принцип работы:

  1. Вызов с контекстным менеджером: Наиболее распространенный способ использования assertRaises() — в качестве контекстного менеджера (with statement). В этом случае код, который, как ожидается, должен вызвать исключение, помещается в блок with. Если исключение ожидаемого типа не выбрасывается, тест завершается неудачей. Если исключение ожидаемого типа выбрасывается, тест считается пройденным.
  2. Вызов с вызываемым объектом и аргументами: Альтернативно, assertRaises() можно вызвать, передав вызываемый объект (функцию, метод и т.д.) и аргументы, которые должны быть переданы этому вызываемому объекту. В этом случае assertRaises() вызывает вызываемый объект с предоставленными аргументами и проверяет, выбрасывается ли ожидаемое исключение.

Синтаксис (контекстный менеджер):

with self.assertRaises(expected_exception):
    # Код, который, как ожидается, должен вызвать исключение
    ...

Синтаксис (вызываемый объект и аргументы):

self.assertRaises(expected_exception, callable_obj, *args, **kwargs)

Параметры:

  • expected_exception: Класс исключения, которое, как ожидается, должно быть выброшено (например, ValueError, TypeError, IndexError).
  • callable_obj: Вызываемый объект (функция, метод и т.д.), который должен быть выполнен. (Только при вызове без контекстного менеджера).
  • *args: Позиционные аргументы, которые должны быть переданы callable_obj. (Только при вызове без контекстного менеджера).
  • **kwargs: Именованные аргументы (ключевые слова), которые должны быть переданы callable_obj. (Только при вызове без контекстного менеджера).
  • msg (необязательный): Пользовательское сообщение об ошибке, которое будет отображено в случае, если исключение не будет выброшено (доступно в обеих формах вызова).

Пример:

import unittest

def divide(x, y):
    if y == 0:
        raise ValueError("Cannot divide by zero")
    return x / y

class TestDivide(unittest.TestCase):
    def test_divide_by_zero(self):
        with self.assertRaises(ValueError) as context:
            divide(10, 0)
        self.assertEqual(str(context.exception), "Cannot divide by zero")

    def test_valid_division(self):
        self.assertEqual(divide(10, 2), 5)

    def test_divide_by_zero_alternative(self):
        self.assertRaises(ValueError, divide, 10, 0)


if __name__ == '__main__':
    unittest.main()

В этом примере test_divide_by_zero проверяет, что функция divide() выбрасывает исключение ValueError при попытке деления на ноль. Контекстный менеджер также позволяет получить доступ к выброшенному исключению (через context.exception) для дальнейшей проверки (например, проверки сообщения об ошибке). Альтернативный способ вызова демонстрируется в test_divide_by_zero_alternative.

Важно: assertRaises() проверяет, что выбрасывается именно указанное исключение. Если будет выброшено исключение другого типа, тест также завершится неудачей. Также важно, чтобы код, вызывающий исключение, находился внутри блока with или был явно вызван через callable_obj. В противном случае тест может пройти успешно (если исключение не будет выброшено), даже если это не то, что предполагалось.

0