Вимкнути міграцію під час запуску одиничних тестів у Django 1.7


110

Django 1.7 ввів міграцію баз даних .

Під час виконання одиничних тестів у Django 1.7 він змушує мігрувати , що займає тривалий час. Тому я хотів би пропустити міграцію джанго та створити базу даних у остаточному стані.

Я знаю, що ігнорування міграцій може бути поганою практикою, оскільки ця частина коду не буде перевірена. Але це не так: я виконую повну міграцію на тестовому сервері CI (jenkins). Я хочу лише пропустити міграцію в своїх місцевих тестах, де швидкість має значення.


Деякий контекст:

До Django 1.6 під час використання South я використовував налаштування SOUTH_TESTS_MIGRATE :

За замовчуванням команда syncdb Саута також застосовуватиме міграції, якщо вона виконується в неінтерактивному режимі, що включає під час запуску тестів - вона буде виконувати кожну міграцію щоразу, коли ви запускаєте тести.

Якщо ви хочете, щоб тестовий бігун використовував syncdb замість міграції - наприклад, якщо ваші міграції тривають занадто довго, щоб застосувати - просто встановіть SOUTH_TESTS_MIGRATE = Неправильно в налаштуваннях.py.

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

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

Параметр --keepdb може використовуватися для збереження тестової бази даних між тестовими запусками. Це має перевагу пропускати як створювати, так і руйнувати дії, що значно скорочує час на виконання тестів, особливо у великих тестових наборах. Якщо тестової бази даних не існує, вона буде створена під час першого запуску та збережена для кожного наступного запуску. Будь-які неприкладені міграції також будуть застосовані до тестової бази даних перед запуском тестового набору.

Тож це питання обмежується Django 1.7.


Я заперечую, що під час UT ви дійсно не виконуєте міграції таким чином, щоб тестувати їх, оскільки їх БД, з якого ви починаєте, не існує. Тестування міграцій насправді відбувається лише тоді, коли ви переносите існуючу БД. Цей бізнес з міграцією 1,7 є першою справжньою суєтою під сідлом, яке я мав з Джанго, але це справді великий подразник. Південь принаймні отримав правильний сценарій тестування для міграцій.
boatcoder

django-test-without-migrationsПакет був дуже зручно для мене, ви можете захотіти змінити прийнятий відповідь на stackoverflow.com/a/28993456/200224
Енді

Я вважаю за краще уникати додавання нових залежностей, якщо це можливо.
Девід Аркос

Відповіді:


79

Подивіться на це рішення , яке опублікував Bernie Sumption для списку розсилки розробників Django:

Якщо макеміграції ще не запущені, команда "migrate" розглядає додаток як неміграційне та створює таблиці безпосередньо з моделей так, як це робило syncdb в 1.6. Я визначив новий модуль налаштувань лише для тестових одиниць під назвою "settings_test.py", який імпортує * з головного модуля налаштувань і додає цей рядок:

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

Тоді я запускаю тести так:

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

Ці дурні мігрують, думаючи, що додаток не переселено, і тому кожен раз, коли створюється тестова база даних, вона відображає поточну структуру models.py.

У Django 1.9 цю ситуацію дещо покращують , і ви можете встановити значення None:

MIGRATION_MODULES = {"myapp": Немає}


9
Зауважте, що myapp.migrations_not_used_in_testsмодуль не повинен існувати.
bmihelac

4
На додаток до коментаря @bmihelac, зробленого з приводу того, що модуль не існує, рядок модуля повинен містити підрядку "міграції". Для чого дивіться: github.com/django/django/blob/stable/1.7.x/django/db/migrations /…
nealtodd

7
Суть функції для побудови MIGRATION_MODULES динамічно в налаштуваннях_test.py: gist.github.com/nealtodd/2869341f38f5b1eeb86d
nealtodd

1
TY. Через це я зміг скоротити свої тести з 13 секунд до 4 секунд. Крім того, більше швидкості можна отримати, використовуючи sqlite для тестування. Для мене використання постгресів для тестів займає 5,5 секунд, але sqlite займає 4 секунди.
Геттстер

21
З коментарів до суті @ nealtodd ось посилання на рішення, яке дозволяє уникнути деяких підводних каменів і є надто простим: 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'
Zhe Li

1
Дякую вам за це, це єдине, що я виявив, що насправді працює.
puffels

Це більше не працює в Django 1.9 при запуску тестів у паралельному режимі. Використовуючи звичайне непаралельне тестування, воно продовжує працювати нормально, але перехід на паралельний режим призводить до помилок, які таблиці не знаходять.
LS55321

@LeeSemel в паралельному режимі ви, мабуть, хочете використовувати рішення від rlmv
Гійом Вінсент

@guillaumevincent У мене така ж проблема при використанні django-test-без міграцій у паралельному режимі
LS55321


3

Оновлення : Неважливо, цю зміну було скасовано до виходу 1.10 фіналу. Сподіваємось, він повернеться у майбутній версії.


Зауважте, що з Django 1.10 це можна контролювати за допомогою тестової бази даних.

МІГРАТ

За замовчуванням: 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. будь ласка, подивіться центр екскурсій та довідки . Зазвичай рекомендується не лише надати однорядкові відповіді, але й пояснити, чому (на вашу думку) ваша відповідь правильна.
Бурки

1

На джанго 1.9 і вище відповідь Гійом Вінсент більше не працює, тож ось нове рішення:

Я використовую цей фрагмент у моєму файлі налаштувань після визначення INSTALLED_APPS

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

Він повторює всі встановлені додатки і позначає кожен, що не має модуля міграції. Додаткову інформацію див. У документах про джанго .

За допомогою цього фрагмента можна запустити тести, встановивши змінну середовища TESTS_WITHOUT_MIGRATIONS, наприклад:

TESTS_WITHOUT_MIGRATIONS=1 ./manage.py test

1

Я просто з'ясував, як відключити міграцію після джанго 1.10, можливо, це може комусь допомогти. Ось посилання на git

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

    def __getitem__(self, item):
        return None

DATABASES = DisableMigrations()

MIGRATION_MODULES = DisableMigrations()

Міграція для джанго 1.10 має дві частини, дивіться на load_disk та диктофон

Частина load_disk для кочівель моделі програми , які будуть додані в INSTALL_APP і частини recorderдля з'єднання з базою даних для версії до 1.9 , ми треба встановлювати MIGRATION_MODULES={'do.not.migrate':'notmigrations'}при запуску тесту Тепер нам не потрібно встановити його немає подібні MIGRATION_MODULES={'do.not.migrate':None} Так що, якщо ми не хочемо зробити міграцію для будь-якої програми , просто продовжте дікт і поверніться Noneдо getitemфункції, і зробіть те ж саме DATABASES, це правильна річ, яку вам потрібно зробити

PS: Для команди вам потрібно вказати --setting=module.path.settings_test_snippetпісляtest PPS. Якщо ви працюєте pycharm, не встановлюйте --settings параметри на Run/Debug configurations, просто додайте шлях settings_test_snippet.pyу налаштуваннях Custom. Це просто добре !!

насолоджуватися

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.