Existe-t-il une possibilité d'écrire des unittests django sans configurer de base de données? Je veux tester la logique métier qui ne nécessite pas la configuration de la base de données. Et bien qu'il soit rapide de configurer une base de données, je n'en ai vraiment pas besoin dans certaines situations.
126
Réponses:
Vous pouvez sous-classer DjangoTestSuiteRunner et remplacer les méthodes setup_databases et teardown_databases à transmettre.
Créez un nouveau fichier de paramètres et définissez TEST_RUNNER sur la nouvelle classe que vous venez de créer. Ensuite, lorsque vous exécutez votre test, spécifiez votre nouveau fichier de paramètres avec l'indicateur --settings.
Voici ce que j'ai fait:
Créez un coureur de combinaison de test personnalisé similaire à celui-ci:
Créez des paramètres personnalisés:
Lorsque vous exécutez vos tests, exécutez-les comme suit avec l'indicateur --settings défini sur votre nouveau fichier de paramètres:
MISE À JOUR: avril / 2018
Depuis Django 1.8, le module a été déplacé vers .
django.test.simple.DjangoTestSuiteRunner
'django.test.runner.DiscoverRunner'
Pour plus d'informations, consultez la section officielle de la documentation sur les testeurs personnalisés.
la source
--testrunner
option.En règle générale, les tests d'une application peuvent être classés en deux catégories
Django prend en charge les tests unitaires et d'intégration.
Les tests unitaires ne nécessitent pas de configuration et de suppression de la base de données et nous devrions hériter de SimpleTestCase .
Pour les cas de test d'intégration, hériter de TestCase hérite à son tour de TransactionTestCase et il configurera et supprimera la base de données avant d'exécuter chaque test.
Cette stratégie garantira que la base de données sera créée et détruite uniquement pour les cas de test qui accèdent à la base de données et donc les tests seront plus efficaces
la source
De
django.test.simple
Alors remplacez
DiscoverRunner
au lieu deDjangoTestSuiteRunner
.Utilisez comme ça:
la source
J'ai choisi d'hériter
django.test.runner.DiscoverRunner
et de faire quelques ajouts à larun_tests
méthode.Mon premier ajout vérifie si la configuration d'une base de données est nécessaire et permet à la
setup_databases
fonctionnalité normale de démarrer si une base de données est nécessaire. Mon deuxième ajout permet à la normaleteardown_databases
de fonctionner si lesetup_databases
méthode était autorisée à s'exécuter.Mon code suppose que tout TestCase qui hérite de
django.test.TransactionTestCase
(et doncdjango.test.TestCase
) nécessite la configuration d'une base de données. J'ai fait cette hypothèse parce que la documentation Django dit:https://docs.djangoproject.com/en/1.6/topics/testing/tools/#django.test.SimpleTestCase
monsite / scripts / settings.py
Enfin, j'ai ajouté la ligne suivante au fichier settings.py de mon projet.
monsite / settings.py
Maintenant, lorsque j'exécute uniquement des tests non dépendants de la base de données, ma suite de tests exécute un ordre de grandeur plus rapide! :)
la source
Mise à jour: consultez également cette réponse pour l'utilisation d'un outil tiers
pytest
.@Cesar a raison. Après avoir accidentellement couru
./manage.py test --settings=no_db_settings
, sans spécifier de nom d'application, ma base de données de développement a été effacée.Pour une manière plus sûre, utilisez le même
NoDbTestRunner
, mais en conjonction avec ce qui suitmysite/no_db_settings.py
:Vous devez créer une base de données appelée à l'
_test_mysite_db
aide d'un outil de base de données externe. Exécutez ensuite la commande suivante pour créer les tables correspondantes:Si vous utilisez South, exécutez également la commande suivante:
D'ACCORD!
Vous pouvez désormais exécuter des tests unitaires extrêmement rapidement (et en toute sécurité) en:
la source
Au lieu de modifier vos paramètres pour rendre NoDbTestRunner "sûr", voici une version modifiée de NoDbTestRunner qui ferme la connexion à la base de données actuelle et supprime les informations de connexion des paramètres et de l'objet de connexion. Fonctionne pour moi, testez-le dans votre environnement avant de vous y fier :)
la source
__getitem__
plus. Utilisezconnections._connections.default
pour accéder à l'objet.Une autre solution serait que votre classe de test hérite simplement de la
unittest.TestCase
place de l'une des classes de test de Django. La documentation Django ( https://docs.djangoproject.com/en/2.0/topics/testing/overview/#writing-tests ) contient l'avertissement suivant à ce sujet:Cependant, si votre test n'utilise pas la base de données, cet avertissement ne doit pas vous concerner et vous pouvez profiter des avantages de ne pas avoir à exécuter chaque scénario de test dans une transaction.
la source
Les solutions ci-dessus conviennent également. Mais la solution suivante réduira également le temps de création de la base de données s'il y a plus de migrations. Pendant les tests unitaires, exécuter syncdb au lieu d'exécuter toutes les migrations sud sera beaucoup plus rapide.
la source
Mon hôte Web autorise uniquement la création et la suppression de bases de données à partir de leur interface graphique Web, donc j'obtenais une erreur "Une erreur lors de la création de la base de données de test: autorisation refusée" lors de la tentative d'exécution
python manage.py test
.J'espérais utiliser l'option --keepdb pour django-admin.py mais elle ne semble plus être prise en charge depuis Django 1.7.
Ce que j'ai fini par faire, c'est de modifier le code Django dans ... / django / db / backends / creation.py, en particulier les fonctions _create_test_db et _destroy_test_db.
Car
_create_test_db
j'ai commenté lacursor.execute("CREATE DATABASE ...
ligne et l' ai remplacée parpass
pour que letry
bloc ne soit pas vide.Car
_destroy_test_db
je viens de commentercursor.execute("DROP DATABASE
- je n'ai pas eu besoin de le remplacer par quoi que ce soit car il y avait déjà une autre commande dans le bloc (time.sleep(1)
).Après cela, mes tests se sont bien déroulés - même si j'ai configuré séparément une version test_ de ma base de données régulière.
Ce n'est pas une excellente solution bien sûr, car elle se cassera si Django est mis à niveau, mais j'avais une copie locale de Django en raison de l'utilisation de virtualenv, donc au moins j'ai le contrôle sur quand / si je mets à niveau vers une version plus récente.
la source
Autre solution non mentionnée: cela a été facile pour moi à mettre en œuvre car j'ai déjà plusieurs fichiers de paramètres (pour local / staging / production) qui héritent de base.py. Donc, contrairement à d'autres personnes, je n'ai pas eu à remplacer DATABASES ['default'], car DATABASES n'est pas défini dans base.py
SimpleTestCase a toujours essayé de se connecter à ma base de données de test et d'exécuter des migrations. Lorsque j'ai créé un fichier config / settings / test.py qui ne définissait DATABASES sur rien, mes tests unitaires se sont déroulés sans. Cela m'a permis d'utiliser des modèles qui avaient une clé étrangère et des champs de contrainte uniques. (La recherche inversée de clé étrangère, qui nécessite une recherche de base de données, échoue.)
(Django 2.0.6)
Extraits de code PS
la source
Lorsque vous utilisez le testeur de nez (django-nose), vous pouvez faire quelque chose comme ceci:
my_project/lib/nodb_test_runner.py
:Dans votre,
settings.py
vous pouvez spécifier le testeur ici, c'est-à-direTEST_RUNNER = 'lib.nodb_test_runner.NoDbTestRunner' . # Was 'django_nose.NoseTestSuiteRunner'
OU
Je le voulais uniquement pour exécuter des tests spécifiques, alors je le lance comme suit:
la source