Deshabilite las migraciones al ejecutar pruebas unitarias en Django 1.7


110

Django 1.7 introdujo migraciones de bases de datos .

Al ejecutar las pruebas unitarias en Django 1.7, obliga a migración , que lleva mucho tiempo. Entonces me gustaría omitir las migraciones de Django y crear la base de datos en el estado final.

Sé que ignorar las migraciones puede ser una mala práctica, ya que esa parte del código no se probaría. Pero ese no es el caso: estoy ejecutando las migraciones completas en el servidor de prueba de CI (jenkins). Solo quiero omitir las migraciones en mis pruebas locales, donde la velocidad importa.


Algo de contexto:

Hasta Django 1.6 , cuando usaba South, usaba SOUTH_TESTS_MIGRATE configuración :

De forma predeterminada, el comando syncdb de South también aplicará migraciones si se ejecuta en modo no interactivo, lo que incluye cuando está ejecutando pruebas; ejecutará todas las migraciones cada vez que ejecute sus pruebas.

Si desea que el ejecutor de prueba use syncdb en lugar de migrar, por ejemplo, si sus migraciones están tardando demasiado en aplicarse, simplemente configure SOUTH_TESTS_MIGRATE = False en settings.py.

Sin embargo, syncdb ya no existe, ahora está migrando .

Y a partir de Django 1.8 Voy a usar el --keepdb parámetro:

La opción --keepdb se puede utilizar para preservar la base de datos de prueba entre ejecuciones de prueba. Esto tiene la ventaja de omitir las acciones de creación y destrucción, lo que reduce en gran medida el tiempo para ejecutar las pruebas, especialmente las que se encuentran en un conjunto de pruebas grande. Si la base de datos de prueba no existe, se creará en la primera ejecución y luego se conservará para cada ejecución posterior. Cualquier migración no aplicada también se aplicará a la base de datos de prueba antes de ejecutar el conjunto de pruebas.

Entonces esta pregunta se limita a Django 1.7.


Yo diría que durante UT, realmente no está ejecutando las migraciones de una manera que las pruebe, ya que la base de datos con la que comienza no existe. La prueba de las migraciones realmente solo ocurre cuando está migrando una base de datos existente. Este negocio de migraciones 1.7 es el primer problema real que he tenido con Django, pero es un gran irritante. South al menos consiguió el escenario de prueba adecuado para las migraciones.
boatcoder

El django-test-without-migrationspaquete ha sido realmente útil para mí, es posible que desee cambiar la respuesta aceptada a stackoverflow.com/a/28993456/200224
Andy

Prefiero evitar agregar nuevas dependencias, si es posible.
David Arcos

Respuestas:


79

Mire esta solución , publicada por Bernie Sumption en la lista de correo de desarrolladores de Django:

Si aún no se ha ejecutado makemigrations, el comando "migrate" trata una aplicación como no migrada y crea tablas directamente a partir de los modelos tal como lo hizo syncdb en 1.6. Definí un nuevo módulo de configuración solo para pruebas unitarias llamado "settings_test.py", que importa * desde el módulo de configuración principal y agrega esta línea:

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

Luego ejecuto pruebas como esta:

DJANGO_SETTINGS_MODULE = "myapp.settings_test" prueba python manage.py

Estos tontos migran a pensar que la aplicación no ha migrado, por lo que cada vez que se crea una base de datos de prueba, refleja la estructura actual de models.py.

En Django 1.9, esta situación ha mejorado un poco y puede establecer el valor en None:

MIGRATION_MODULES = {"myapp": Ninguno}


9
Tenga en cuenta que el myapp.migrations_not_used_in_testsmódulo no debería existir.
bmihelac

4
Además del comentario que @bmihelac hizo sobre el módulo que no existe, la cadena del módulo debe contener la subcadena 'migraciones'. Para saber por qué, consulte: github.com/django/django/blob/stable/1.7.x/django/db/migrations /…
nealtodd

7
Resumen de una función para construir MIGRATION_MODULES dinámicamente en settings_test.py: gist.github.com/nealtodd/2869341f38f5b1eeb86d
nealtodd

1
TY. Pude reducir mis pruebas unitarias de 13 segundos a 4 segundos debido a esto. Además, se pueden encontrar más ganancias de velocidad utilizando sqlite para las pruebas. Para mí, usar postgres para las pruebas está tomando 5.5 segundos, pero sqlite está tomando 4 segundos.
Gattster

21
De los comentarios de la esencia de @ nealtodd, aquí hay un enlace a una solución que evita algunos de los escollos y es súper simple: gist.github.com/NotSqrt/5f3c76cd15e40ef62d09
djsutho

72

Aquí está el final de mi archivo de configuración:

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()

basado en este fragmento

Inhabilité las migraciones solo cuando las pruebas se están ejecutando


1
¡Agradable! También agregaría un __setitem__(self, *_)método porque tuvimos problemas con las aplicaciones que configuran su propia migración como settings.MIGRATION_MODULES['chroniker'] = 'db_migrations'
Zhe Li

1
Muchas gracias por esto, es lo único que encontré que realmente funciona.
fluffels

Esto ya no funciona en Django 1.9 cuando se ejecutan pruebas en modo paralelo. Con las pruebas no paralelas normales, sigue funcionando bien, pero cambiar al modo paralelo da como resultado errores que no se encuentran en las tablas.
LS55321

@LeeSemel en modo paralelo probablemente desee utilizar la solución de rlmv
Guillaume Vincent

@guillaumevincent tengo el mismo problema cuando uso django-test-without-migrations en modo paralelo
LS55321


3

Actualización : no importa, este cambio se revirtió antes de que se lanzara la versión 1.10 final. Ojalá vuelva en una versión futura.


Tenga en cuenta que a partir de Django 1.10 esto se puede controlar mediante una configuración de base de datos de prueba.

EMIGRAR

Defecto: True

Si se establece en False, Django no usará migraciones para crear la base de datos de prueba.



1

Para django 1.9 y versiones posteriores, la respuesta de Guillaume Vincent ya no funciona, así que aquí hay una nueva solución:

Estoy usando este fragmento en mi archivo de configuración, después de la definición del INSTALLED_APPS

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

Repite todas las aplicaciones instaladas y las marca como sin módulo de migración. Consulte los documentos de django para obtener más información .

Con este fragmento, puede ejecutar sus pruebas, configurando la variable de entorno TESTS_WITHOUT_MIGRATIONS, por ejemplo:

TESTS_WITHOUT_MIGRATIONS=1 ./manage.py test

1

Acabo de descubrir cómo deshabilitar las migraciones después de django 1.10, puede ser que pueda ayudar a alguien. Aquí hay un enlace en git

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

    def __getitem__(self, item):
        return None

DATABASES = DisableMigrations()

MIGRATION_MODULES = DisableMigrations()

Las migraciones para django 1.10 tienen dos partes, consulte load_disk y recorder

La parte de load_disklas migraciones modelo de aplicación que se añade a INSTALL_APP Y la parte de recorderlas conexiones de base de datos para la versión antes de 1.9 Tenemos que establecemos MIGRATION_MODULES={'do.not.migrate':'notmigrations'}cuando se está ejecutando la prueba Ahora necesitamos propusimos que nadie como MIGRATION_MODULES={'do.not.migrate':None} lo tanto, si no queremos que las migraciones de maquillaje para cualquier aplicación , simplemente extienda un dictado y regrese Nonepara getitemfunción, y haga lo mismo en DATABASES, eso es lo correcto que debe hacer

PD: Para el comando, debe especificar --setting=module.path.settings_test_snippetdespués de test PPS. Si está trabajando con pycharm, no configure las --settings opciones en Run/Debug configurations, simplemente agregue la ruta de settings_test_snippet.pyen Configuración personalizada. ¡¡Eso estará bien !!

disfrutar

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.