Existe-t-il un mécanisme simple pour remplacer les paramètres Django pour un test unitaire? J'ai un gestionnaire sur l'un de mes modèles qui renvoie un nombre spécifique des derniers objets. Le nombre d'objets qu'il renvoie est défini par un paramètre NUM_LATEST.
Cela a le potentiel de faire échouer mes tests si quelqu'un change le paramètre. Comment puis-je remplacer les paramètres setUp()
et les restaurer ultérieurement tearDown()
? Si ce n'est pas possible, y a-t-il un moyen pour monkey patcher la méthode ou me moquer des paramètres?
EDIT: Voici mon code de gestionnaire:
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]
Le gestionnaire utilise settings.NEWS_LATEST_MAX
pour découper l'ensemble de requêtes. Le getattr()
est simplement utilisé pour fournir une valeur par défaut si le paramètre n'existe pas.
Réponses:
MODIFIER: Cette réponse s'applique si vous souhaitez modifier les paramètres d'un petit nombre de tests spécifiques .
Depuis Django 1.4, il existe des moyens de remplacer les paramètres lors des tests: https://docs.djangoproject.com/en/dev/topics/testing/tools/#overriding-settings
TestCase aura un gestionnaire de contexte self.settings, et il y aura également un décorateur @override_settings qui peut être appliqué à une méthode de test ou à une sous-classe TestCase entière.
Ces fonctionnalités n'existaient pas encore dans Django 1.3.
Si vous souhaitez modifier les paramètres de tous vos tests, vous souhaiterez créer un fichier de paramètres distinct pour le test, qui peut charger et remplacer les paramètres de votre fichier de paramètres principal. Il existe plusieurs bonnes approches à ce sujet dans les autres réponses; J'ai vu des variations réussies sur les approches de hspander et de dmitrii .
la source
self.settings().wrapped.MEDIA_ROOT
, mais c'est assez terrible.@modify_settings(MIDDLEWARE_CLASSES=...
Vous pouvez faire tout ce que vous voulez pour la
UnitTest
sous - classe, y compris la définition et la lecture des propriétés d'occurrence:Étant donné que les cas de test django fonctionnent avec un seul thread, je suis curieux de savoir quoi d'autre pourrait modifier la valeur NUM_LATEST? Si ce "quelque chose d'autre" est déclenché par votre routine de test, alors je ne suis pas sûr qu'une quantité de patching de singe sauvera le test sans invalider la véracité des tests eux-mêmes.
la source
settings.TEMPLATE_LOADERS
... Donc ce n'est pas de manière générale du moins, les paramètres ou Django n'est pas rechargé ou quoi que ce soit avec cette astuce.Bien que la configuration des paramètres de remplacement lors de l'exécution puisse aider, à mon avis, vous devriez créer un fichier séparé pour les tests. Cela économise beaucoup de configuration pour les tests et cela garantirait que vous ne finissiez jamais par faire quelque chose d'irréversible (comme le nettoyage de la base de données de préparation).
Supposons que votre fichier de test existe dans "mon_projet / test_settings.py", ajoutez
dans votre manage.py. Cela garantira que lorsque vous exécutez,
python manage.py test
vous utilisez uniquement test_settings. Si vous utilisez un autre client de test comme pytest, vous pouvez aussi facilement l'ajouter à pytest.inila source
Vous pouvez passer l'
--settings
option lors de l'exécution des testsla source
Mise à jour : la solution ci-dessous n'est nécessaire que sur Django 1.3.x et versions antérieures. Pour> 1.4, voir la réponse de slinkp .
Si vous modifiez fréquemment les paramètres dans vos tests et utilisez Python ≥2.5, cela est également pratique:
Ensuite, vous pouvez faire:
la source
yield
instruction, avec la dernière partie de la fonction contenue dans lefinally
bloc, afin que les paramètres soient toujours annulés.@override_settings
est idéal si vous n'avez pas beaucoup de différences entre vos configurations d'environnement de production et de test.Dans les autres cas, vous feriez mieux d'avoir simplement différents fichiers de paramètres. Dans ce cas, votre projet ressemblera à ceci:
Vous devez donc avoir la plupart de vos paramètres dans
base.py
, puis dans d'autres fichiers, vous devez tout importer à partir de là et remplacer certaines options. Voici à quoi ressemblera votretest.py
fichier:Et puis, vous devez soit spécifier l'
--settings
option comme dans la réponse @MicroPyramid, soit spécifierDJANGO_SETTINGS_MODULE
la variable d'environnement, puis vous pouvez exécuter vos tests:la source
J'ai trouvé ceci en essayant de corriger certains doctests ... Par souci d'exhaustivité, je tiens à mentionner que si vous allez modifier les paramètres lors de l'utilisation de doctests, vous devez le faire avant d'importer quoi que ce soit d'autre ...
la source
Pour les utilisateurs de pytest .
Le plus gros problème est:
override_settings
ne fonctionne pas avec pytest.TestCase
fera fonctionner, mais vous ne pourrez pas utiliser les appareils pytest.La solution est d'utiliser le
settings
luminaire documenté ici .Exemple
Et au cas où vous auriez besoin de mettre à jour plusieurs champs
la source
Vous pouvez annuler le réglage même pour une seule fonction de test.
ou vous pouvez remplacer le paramètre de chaque fonction de la classe.
la source
J'utilise pytest.
J'ai réussi à résoudre ce problème de la manière suivante:
la source
Vous pouvez remplacer les paramètres dans le test de cette manière:
Et si vous avez besoin de ces mêmes paramètres dans un autre fichier, vous pouvez simplement les importer directement
test_settings
.la source
Si vous avez plusieurs fichiers de test placés dans un sous-répertoire (package python), vous pouvez remplacer les paramètres de tous ces fichiers en fonction de la condition de présence de la chaîne 'test' dans sys.argv
__init__.py:
Pas la meilleure approche. Utilisé pour changer le courtier Celery de Redis en Memory.
la source
J'ai créé un nouveau fichier settings_test.py qui importerait tout du fichier settings.py et modifierait tout ce qui est différent à des fins de test. Dans mon cas, je voulais utiliser un autre compartiment de stockage dans le cloud lors des tests.
settings_test.py:
manage.py:
la source