tutorial template examples bootstrap django settings testing django-managers

template - Cómo probar la unidad con diferentes configuraciones en Django?



templates django python (8)

¿Hay algún mecanismo simple para anular la configuración de Django para una prueba unitaria? Tengo un administrador en uno de mis modelos que devuelve un número específico de los últimos objetos. La cantidad de objetos que devuelve se define mediante una configuración NUM_LATEST.

Esto tiene el potencial de hacer que mis pruebas fallen si alguien cambiara la configuración. ¿Cómo puedo anular las configuraciones en setUp() y luego restaurarlas en tearDown() ? Si eso no es posible, ¿hay alguna forma de que yo pueda parchear el método o simular la configuración?

EDITAR: Aquí está mi código de administrador:

class LatestManager(models.Manager): """ Returns a specific number of the most recent public Articles as defined by the NEWS_LATEST_MAX setting. """ def get_query_set(self): num_latest = getattr(settings, ''NEWS_NUM_LATEST'', 10) return super(LatestManager, self).get_query_set().filter(is_public=True)[:num_latest]

El administrador usa settings.NEWS_LATEST_MAX para cortar el conjunto de consulta. El getattr() se usa simplemente para proporcionar un valor predeterminado si la configuración no existe.


A pesar de que la configuración general de configuración en el tiempo de ejecución puede ayudar, en mi opinión, debe crear un archivo separado para la prueba. Esto ahorra mucha configuración para las pruebas y esto garantizaría que nunca termine haciendo algo irreversible (como limpiar la base de datos de etapas).

Supongamos que su archivo de prueba existe en ''my_project / test_settings.py'', agregue

settings = ''my_project.test_settings'' if ''test'' in sys.argv else ''my_project.settings''

en su manage.py Esto garantizará que cuando ejecute la python manage.py test manage.py solo use test_settings. Si está utilizando algún otro cliente de prueba como Pytest, podría agregarlo tan fácilmente a pytest.ini


EDITAR: esta respuesta se aplica si desea cambiar la configuración de un pequeño número de pruebas específicas .

Desde Django 1.4, hay formas de anular la configuración durante las pruebas: https://docs.djangoproject.com/en/dev/topics/testing/tools/#overriding-settings

TestCase tendrá un administrador de contexto selfsettings, y también habrá un decorador @override_settings que se puede aplicar a un método de prueba o a toda una subclase de TestCase.

Estas características aún no existían en Django 1.3.

Si desea cambiar la configuración de todas sus pruebas, querrá crear un archivo de configuración separado para la prueba, que puede cargar y anular la configuración de su archivo de configuración principal. Hay varios buenos enfoques para esto en las otras respuestas; He visto variaciones exitosas en los hspander''s dmitrii''s y dmitrii''s .


Encontré esto mientras trataba de arreglar algunos doctests ... Para completar, quiero mencionar que si va a modificar la configuración cuando usa doctests, debe hacerlo antes de importar cualquier otra cosa ...

>>> from django.conf import settings >>> settings.SOME_SETTING = 20 >>> # Your other imports >>> from django.core.paginator import Paginator >>> # etc


Estoy usando Pytest.

Pude resolver esto de la siguiente manera:

import django import app.setting import modules.that.use.setting # do some stuff with default setting setting.VALUE = "some value" django.setup() import importlib importlib.reload(app.settings) importlib.reload(modules.that.use.setting) # do some stuff with settings new value


Puede hacer lo que quiera con la subclase UnitTest , incluidas las propiedades de configuración y lectura de instancia:

from django.conf import settings class MyTest(unittest.TestCase): def setUp(self): self.old_setting = settings.NUM_LATEST settings.NUM_LATEST = 5 # value tested against in the TestCase def tearDown(self): settings.NUM_LATEST = self.old_setting

Como los casos de prueba de django se ejecutan en un único subproceso, sin embargo, tengo curiosidad acerca de qué más puede estar modificando el valor NUM_LATEST. Si su rutina de prueba desencadena esa "otra cosa", entonces no estoy seguro de que la cantidad de parches de mono guarde la prueba sin invalidar la veracidad de las pruebas.


Puede pasar la opción --settings cuando ejecuta pruebas

python manage.py test --settings=mysite.settings_local


@override_settings es excelente si no tiene muchas diferencias entre las configuraciones de entorno de producción y prueba.

En otro caso, será mejor que tengas diferentes archivos de configuración. En este caso, su proyecto se verá así:

your_project your_app ... settings __init__.py base.py dev.py test.py production.py manage.py

Por lo tanto, necesita tener la mayoría de sus configuraciones en base.py y luego en otros archivos, necesita importar todo desde allí y anular algunas opciones. Así es como se test.py tu archivo test.py :

from .base import * DEBUG = False DATABASES = { ''default'': { ''ENGINE'': ''django.db.backends.sqlite3'', ''NAME'': ''app_db_test'' } } PASSWORD_HASHERS = ( ''django.contrib.auth.hashers.MD5PasswordHasher'', ) LOGGING = {}

Y luego debes especificar la opción --settings como en @MicroPyramid answer, o especificar la variable de entorno DJANGO_SETTINGS_MODULE y luego puedes ejecutar tus pruebas:

export DJANGO_SETTINGS_MODULE=settings.test python manage.py test


Actualización : la solución a continuación solo es necesaria en Django 1.3.xy versiones anteriores. Para> 1.4 ver la respuesta de slinkp .

Si cambia la configuración con frecuencia en sus pruebas y usa Python ≥2.5, esto también es útil:

from contextlib import contextmanager class SettingDoesNotExist: pass @contextmanager def patch_settings(**kwargs): from django.conf import settings old_settings = [] for key, new_value in kwargs.items(): old_value = getattr(settings, key, SettingDoesNotExist) old_settings.append((key, old_value)) setattr(settings, key, new_value) yield for key, old_value in old_settings: if old_value is SettingDoesNotExist: delattr(settings, key) else: setattr(settings, key, old_value)

Entonces puedes hacer:

with patch_settings(MY_SETTING=''my value'', OTHER_SETTING=''other value''): do_my_tests()