Использование assertRaises() с NoneType объектами в Python

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Чтобы проверить возникновение исключений при работе с объектом None, вызываемую функцию, генерирующую исключение, следует поместить внутрь блока assertRaises. Образец кода приведён ниже:

Python
Скопировать код
import unittest

class TestNoneOperation(unittest.TestCase):
    def test_none_method_call_raises(self):
        with self.assertRaises(AttributeError):
            none_var = None
            none_var.invalid_method()  # У None нет методов, подобно моим свободным воскресеньям ;)

unittest.main()

В данном примере мы убеждаемся, что при попытке вызвать несуществующий метод у объекта None возникает исключение AttributeError.

Кинга Идем в IT: пошаговый план для смены профессии

Корректный вызов assertRaises

Метод assertRaises() принимает аргументы по отдельности: тип исключения, вызываемую функцию и аргументы для этой функции. Если функция будет вызвана до передачи в assertRaises, тест перехватит исключение, не относящееся к тестируемым сценариям. Рассмотрим примеры:

Python
Скопировать код
# Это аналогично попытке бросить мяч в чужую корзину
self.assertRaises(ExceptionType, some_function(None))  # Неправильно! Попытка вызвать функцию приведёт к TypeError

# Мы точно знаем, куда бросаем мяч
self.assertRaises(ExceptionType, some_function, None)  # Правильно! Вызываемая функция и её аргументы передаются раздельно

Если исключение TypeError вызывается аргументами функции, используйте лямбда-выражение для отложенного вызова:

Python
Скопировать код
self.assertRaises(ExceptionType, lambda: some_function(None))  # Лямбда-функция отложит вызов аргумента

Проверка деталей исключения

Использование assertRaises() в качестве контекстного менеджера позволяет проверять тип и содержание исключения:

Python
Скопировать код
with self.assertRaises(SomeException) as cm:
    code_that_raises()  # Считаем, что здесь "ящик Пандоры" с ошибками

self.assertEqual('Ожидаемое сообщение', str(cm.exception))  # Проверяем, что это именно то исключение, которое мы ожидали

Этот подход оказывается особенно полезным для отлова ошибки "NoneType object is not subscriptable" (обычно случается при попытке обращения к объекту None, как к последовательности).

Стратегии для старых версий Python

  • Python 2.7 и выше: Используйте assertRaises() в качестве контекстного менеджера.
  • Python 2.6 и ниже: Используйте модуль unittest2, который расширяет возможности вашего тестового фреймворка, в том числе добавляет использование assertRaises() в качестве контекстного менеджера.

Продвинутые способы работы

В более сложных случаях, связанных с assertRaises(), может пригодиться функция operator.itemgetter, позволяющая избегать ошибки TypeError при имитировании индексирования объектов, которые не поддерживают индексацию:

Python
Скопировать код
import operator
self.assertRaises(TypeError, operator.itemgetter(0), None)  # Itemgetter играет роль охотника за None

Визуализация

Можно представить assertRaises() как сетку безопасности (🥅), предназначенную для отлова мяча (🏀) определённого типа:

Python
Скопировать код
with self.assertRaises(ExpectedException):
    throw_ball()  # Ожидаем, что сетка поймает баскетбольный мяч.

Когда в сценарий вступает NoneType, можно сказать, что мяч словно исчез в воздухе (💨):

Markdown
Скопировать код
with self.assertRaises(ExpectedException):
    throw_ball()  # Мяч не был брошен. Где же мяч?

В этой аналогии судья – это оператор утверждения, проверяющий, пойман ли именно тот мяч, который ожидался:

Markdown
Скопировать код
🥅 Сетка безопасности: "Я ловлю только 🏀!"
💨 Нет мяча: "Подождите, здесь и впрямь ничего нет!"
👨‍⚖️ Судья: "Ошибка! Ожидали 🏀, а поймали 💨."

Принцип: сетка безопасности (🥅) неэффективна, если в игре только воздух (💨); ей нужен конкретный мяч (🏀), то есть объект, генерирующий исключение.

Настройка вашего assertRaises

Контекст имеет значение

Применение assertRaises() как контекстного менеджера помогает поддерживать надежность тестов и обеспечивает их стабильное выполнение даже при обновлении версий Python, позволяя точно определить, что именно породило исключение.

Подробнее об этом расскажет наш спикер на видео
skypro youtube speaker

Предупреждение ложноположительных результатов

Неправильная работа с assertRaises() может привести к ложноположительным результатам тестов. Убедитесь, что вызов исключения осуществлён намеренно, и он не связан с другими проблемами, не относящимися к тесту.

Использование слоёв совместимости для Python 2

Для версий Python 2.6 и более ранних модуль unittest2 предоставляет бесплатные обновления возможностей стандартного тестового пакета.

Полезные материалы

  1. unittest — Фреймворк модульного тестирования — Документация Python 3.12.2официальная документация Python по assertRaises.
  2. Начало работы с тестированием на Python – Real Python — подробные руководства по первым шагам в модульном тестировании на Python.
  3. Примеры использования unittest.assertRaises в Python — практические примеры использования unittest.assertRaises.
  4. Как правильно формулировать утверждения в тестах — документация pytest — глубокий анализ того, как сделать тестирование максимально эффективным и удобным для поддержки.
  5. Тестирование в Python 3: Введение в unittest – Mouse Vs Python — вводная статья по модульному тестированию для новичков.
  6. Встроенные константы — Документация Python 3.12.2 — информация о NoneType и его роли в Python.
Проверь как ты усвоил материалы статьи
Пройди тест и узнай насколько ты лучше других читателей
Какой тип исключения генерируется при попытке вызвать несуществующий метод у объекта None?
1 / 5