Отключить миграции при запуске модульных тестов в Django 1.7

110

Django 1.7 представил миграцию баз данных .

При запуске модульных тестов в Django 1.7 он вызывает миграцию , которая занимает много времени. Поэтому я хотел бы пропустить миграции django и создать базу данных в конечном состоянии.

Я знаю, что игнорирование миграций может быть плохой практикой, поскольку эта часть кода не будет проверяться. Но это не так: я выполняю полные миграции на тестовом сервере CI (jenkins). Я только хочу пропустить миграции в моих локальных тестах, где важна скорость.


Некоторый контекст:

До Django 1.6 при использовании South я использовал настройку SOUTH_TESTS_MIGRATE :

По умолчанию команда South syncdb также применяет миграции, если она выполняется в неинтерактивном режиме, в том числе, когда вы выполняете тесты - она ​​будет запускать каждую миграцию каждый раз, когда вы запускаете свои тесты.

Если вы хотите, чтобы средство выполнения тестов использовало syncdb вместо миграции - например, если ваши миграции слишком долго применяются - просто установите SOUTH_TESTS_MIGRATE = False в settings.py.

Однако syncdb больше не существует, теперь он переносится .

А из Django 1.8 я буду использовать параметр --keepdb :

Параметр --keepdb можно использовать для сохранения тестовой базы данных между тестовыми запусками. Это дает то преимущество, что пропускаются действия create и destroy, что значительно сокращает время выполнения тестов, особенно в большом наборе тестов. Если тестовая база данных не существует, она будет создана при первом запуске, а затем сохранена для каждого последующего запуска. Любые непримененные миграции также будут применены к тестовой базе данных перед запуском набора тестов.

Итак, этот вопрос ограничен Django 1.7.

Дэвид Аркос
источник
Я бы сказал, что во время UT вы действительно не запускаете миграции таким образом, чтобы их тестировать, поскольку их БД, с которой вы начинаете, не существует. Тестирование миграции действительно происходит только тогда, когда вы переносите существующую БД. Эта миграция 1.7 - первая настоящая проблема, которую я получил с Django, но это действительно большой раздражитель. Юг, по крайней мере, получил правильный сценарий тестирования для миграции.
boatcoder
django-test-without-migrationsПакет был очень удобно для меня, вы можете захотеть изменить принятый ответ на stackoverflow.com/a/28993456/200224
Энди
Я предпочитаю по возможности избегать добавления новых зависимостей.
Дэвид Аркос

Ответы:

79

Взгляните на этот обходной путь , опубликованный Берни Самптионом в списке рассылки разработчиков Django:

Если makemigrations еще не запущен, команда «migrate» рассматривает приложение как не мигрированное и создает таблицы непосредственно из моделей, как это делал syncdb в 1.6. Я определил новый модуль настроек только для модульных тестов под названием «settings_test.py», который импортирует * из основного модуля настроек и добавляет эту строку:

MIGRATION_MODULES = {"myapp": "myapp.migrations_not_used_in_tests"}

Затем я запускаю такие тесты:

DJANGO_SETTINGS_MODULE = "myapp.settings_test" тест python manage.py

Эти дураки думают, что приложение не мигрировали, и поэтому каждый раз, когда создается тестовая база данных, она отражает текущую структуру models.py.

В Django 1.9 эта ситуация несколько улучшена , и вы можете установить значение None:

MIGRATION_MODULES = {"myapp": Нет}

Альбертгассет
источник
9
Обратите внимание, что myapp.migrations_not_used_in_testsмодуль не должен существовать.
bmihelac
4
В дополнение к комментарию @bmihelac о том, что модуль не существует, строка модуля должна содержать подстроку 'migrations'. Почему см .: github.com/django/django/blob/stable/1.7.x/django/db/migrations /…
nealtodd
7
Суть функции для динамического построения
MIGRATION_MODULES
1
TY. Благодаря этому я смог сократить свои модульные тесты с 13 до 4 секунд. Кроме того, больший прирост скорости можно получить, используя sqlite для тестирования. Для меня использование postgres для тестов занимает 5,5 секунды, но sqlite занимает 4 секунды.
Gattster
21
Из комментариев @ nealtodd gist вот ссылка на решение, которое позволяет избежать некоторых ловушек и очень простое: gist.github.com/NotSqrt/5f3c76cd15e40ef62d09
djsutho
72

Вот конец моего файла настроек:

class DisableMigrations(object):

    def __contains__(self, item):
        return True

    def __getitem__(self, item):
        return None


TESTS_IN_PROGRESS = False
if 'test' in sys.argv[1:] or 'jenkins' in sys.argv[1:]:
    logging.disable(logging.CRITICAL)
    PASSWORD_HASHERS = (
        'django.contrib.auth.hashers.MD5PasswordHasher',
    )
    DEBUG = False
    TEMPLATE_DEBUG = False
    TESTS_IN_PROGRESS = True
    MIGRATION_MODULES = DisableMigrations()

на основе этого фрагмента

Я отключил миграции только при запуске тестов

Гийом Винсент
источник
1
Ницца! Я хотел бы добавить __setitem__(self, *_)метод, а потому что у нас были проблемы с приложениями , которые устанавливают свои собственные миграции как settings.MIGRATION_MODULES['chroniker'] = 'db_migrations'
Чжэ Ли
1
Большое вам спасибо за это, это единственное, что я обнаружил, что действительно работает.
fluffels
Это больше не работает в Django 1.9 при запуске тестов в параллельном режиме. При обычном непараллельном тестировании он продолжает работать нормально, но переход в параллельный режим приводит к ошибкам, что таблицы не обнаруживаются.
LS55321
@LeeSemel в параллельном режиме, возможно, вы захотите использовать решение от rlmv
Гийом Винсент
@guillaumevincent у меня та же проблема при использовании django-test-without-migrations в параллельном режиме
LS55321
3

Обновление : неважно, это изменение было отменено до выхода финальной версии 1.10. Надеюсь, он вернется в будущей версии.


Обратите внимание, что начиная с Django 1.10 этим можно управлять с помощью настройки тестовой базы данных.

MIGRATE

По умолчанию: True

Если установлено значение False, Django не будет использовать миграции для создания тестовой базы данных.

Кевин Кристофер Генри
источник
2

https://gist.github.com/apollovy/22826f493ad2d06d9a9a22464730ce0b

MIGRATION_MODULES = {
    app[app.rfind('.') + 1:]: 'my_app.migrations_not_used_in_tests'
    for app in INSTALLED_APPS
}
Аполлов
источник
Добро пожаловать в stackoverflow. ознакомьтесь с обзором и справочным центром . Обычно рекомендуется не только давать однострочные ответы, но и объяснять, почему (как вы думаете) ваш ответ правильный.
Burki
1

Для django 1.9 и выше ответ Гийома Винсента больше не работает, поэтому вот новое решение:

Я использую этот фрагмент в своем файле настроек после определения INSTALLED_APPS

if os.environ.get('TESTS_WITHOUT_MIGRATIONS', False):
    MIGRATION_MODULES = {
        app.split('.')[-1]: None for app in INSTALLED_APPS
    }

Он перебирает все установленные приложения и помечает каждое как не имеющее модуля миграции. Дополнительную информацию смотрите в документации по django .

Используя этот фрагмент, вы можете запускать свои тесты, задав переменную среды TESTS_WITHOUT_MIGRATIONS, например:

TESTS_WITHOUT_MIGRATIONS=1 ./manage.py test
devsnd
источник
1

Я просто выяснил, как отключить миграции после django 1.10, может быть, это кому-то поможет. Вот ссылка на git

class DisableMigrations(dict):
    def __contains__(self, item):
        return True

    def __getitem__(self, item):
        return None

DATABASES = DisableMigrations()

MIGRATION_MODULES = DisableMigrations()

Миграция для django 1.10 состоит из двух частей, пожалуйста, посмотрите load_disk и рекордер

Часть load_diskдля модели миграции приложения, которая будет добавлена ​​в INSTALL_APP И часть recorderдля подключения к базе данных. Для версии до 1.9 нам нужно установить, MIGRATION_MODULES={'do.not.migrate':'notmigrations'}когда вы запускаете тест. Теперь нам нужно установить это None like MIGRATION_MODULES={'do.not.migrate':None} Итак, если мы не хотим делать миграции для любого приложения , просто расширите dict и вернитесь Noneдля getitemфункции, и сделайте то же самое в DATABASES, это то, что вам нужно сделать

PS: Для команды вам необходимо указать --setting=module.path.settings_test_snippetпосле test PPS. Если вы работаете с pycharm, не устанавливайте --settings параметры в Run/Debug configurations, просто добавьте путь settings_test_snippet.pyв разделе Пользовательские настройки. Это будет хорошо !!

наслаждаться

FavorMylikes
источник