О новом подключаемом расширении для pytest, позволяющем подменять различные сущности в зависимостях.
На днях, для проверки работы поддержки Django в новой версии uwsgiconf (подробнее об этом в одной из следующих статей) я написал некоторое количество тестов, которые в ходе исполнения задействовали сущности из самого Django. Понятное дело, без наличия этого каркаса тесты будут падать, а каждый раз для их прогона тащить Django на какой-нибудь Travis — только время тратить, поэтому нужно было имитировать наличие пакета, благо, что в данном случае имитация была целесообразна.

В комплекте pytest идёт фикстура monkeypatch, однако, к сожалению, она не решает задачу имитации наличия пакетов, а лишь позволяет подменить атрибуты уже имеющихся. Беглый поиск по существующим плагинам результатов отчего-то не дал, поэтому я создал фикстуру stub, позволяющую имитировать наличие пакета/модуля путём временной манипуляции sys.modules.

Решение сработало, я решил им поделиться — так появился плагин pytest-stub.
Ниже вы можете видеть пример использования фикстуры stub.

    
def test_django_related(stub):

stub.apply({
# Заменим 'call_command' функцией, сгенерированной налету.
'django.core.management.call_command': '[func]',

# А здесь заменим 'BaseCommand' классом, сгенерированным налету.
'django.core.management.base.BaseCommand': '[cls]',

# Подменим сразу несколько атрибутов модуля 'conf' своими объектами.
'django.conf': {
'settings': object(),
'some': True,
},
})

# Теперь следующие импорты сработают, даже если Django недоступен.
from django.core.management import call_command
from django.core.management.base import BaseCommand
from django.conf import settings, some

Из кода видно, что имеется возможность не только прописывать свои значения атрибутам модуля (можно заменить их, к примеру, на MagicMock ), но есть и средства для быстрого генерирования функций и классов. Сгенерированные функции принимают любые аргументы и возвращают None, а сгенерированные классы просто наследуются от object.

Ввиду того, что до окончания поддержки Python 2.7 остаётся лишь год с небольшим, а также того, что для работы со старой версией потребовалось бы совершить много дополнительных телодвижений, pytest-stub работает только с Python 3.

pytest-stub разрабатывается открыто. Желающие могут принять участие.


Удачной подмены.

Категории

Язык
Область
Проект
Аспект языка

На заметку
У нас есть представительство во ВКонтакте. Ссылка в самом низу страницы.