Est-il possible d'écrire django unittests sans mettre en place une db? Je veux tester la logique métier qui ne nécessite pas de la db. Et alors qu'il est rapide pour l'installation de la base de données, je n'ai pas vraiment besoin dans certaines situations.
Réponses
Trop de publicités?Vous pouvez sous-classe DjangoTestSuiteRunner et remplacer setup_databases et teardown_databases méthodes de passer.
Créer un nouveau fichier de paramètres et de définir TEST_RUNNER à la nouvelle classe que vous venez de créer. Ensuite, lorsque vous exécutez votre test, indiquez votre nouveau fichier de paramètres-paramètres de l'indicateur.
Voici ce que j'ai fait:
Créer un custom test (test personnalisé maillot de coureur de similaire à ceci:
from django.test.simple import DjangoTestSuiteRunner
class NoDbTestRunner(DjangoTestSuiteRunner):
""" A test runner to test without database creation """
def setup_databases(self, **kwargs):
""" Override the database creation defined in parent class """
pass
def teardown_databases(self, old_config, **kwargs):
""" Override the database teardown defined in parent class """
pass
Créer des paramètres personnalisés:
from mysite.settings import *
# Test runner with no database creation
TEST_RUNNER = 'mysite.scripts.testrunner.NoDbTestRunner'
Lorsque vous exécutez vos tests, de l'exécuter comme suit --paramètres de l'indicateur est défini pour votre nouveau fichier de paramètres:
python manage.py test myapp --settings='no_db_settings'
Généralement, les tests d'une application peuvent être classés en deux catégories
- Les tests unitaires, ces test de l'individu extraits de code dans l'insolation et ne nécessitent pas d'aller à la base de données
- L'intégration des cas de test qui vont effectivement à la base de données et de tester l'intégration de la logique.
Django prend en charge les deux tests unitaires et d'intégration.
Les tests unitaires, ne nécessite pas d'installation et le démontage de la base de données et nous nous devrait hériter de SimpleTestCase.
from django.test import SimpleTestCase
class ExampleUnitTest(SimpleTestCase):
def test_something_works(self):
self.assertTrue(True)
Pour l'intégration des cas de test hériter de cas de test à son tour hérite de TransactionTestCase et il va l'installation et le démontage de la base de données avant l'exécution de chaque test.
from django.test import TestCase
class ExampleIntegrationTest(TestCase):
def test_something_works(self):
#do something with database
self.assertTrue(True)
Cette stratégie permettra d'assurer que la base de données créée et détruite seulement pour les cas de test d'accès à la base de données et, par conséquent, des tests seront plus efficaces
D' django.test.simple
warnings.warn(
"The django.test.simple module and DjangoTestSuiteRunner are deprecated; "
"use django.test.runner.DiscoverRunner instead.",
RemovedInDjango18Warning)
Afin de remplacer DiscoverRunner
au lieu de DjangoTestSuiteRunner
.
from django.test.runner import DiscoverRunner
class NoDbTestRunner(DiscoverRunner):
""" A test runner to test without database creation/deletion """
def setup_databases(self, **kwargs):
pass
def teardown_databases(self, old_config, **kwargs):
pass
L'utilisation de ce genre :
python manage.py test app --testrunner=app.filename.NoDbTestRunner
J'ai choisi d'hériter d' django.test.runner.DiscoverRunner
et de faire quelques ajouts à l' run_tests
méthode.
Mon premier ajout vérifie si la configuration de la base de données est nécessaire et permet à la normale setup_databases
de la fonctionnalité coup de pied dans si une base de données est nécessaire. Ma deuxième plus permet à la normale teardown_databases
à exécuter si l' setup_databases
méthode a été autorisé à s'exécuter.
Mon code suppose que tous les cas de test qui hérite de django.test.TransactionTestCase
(et donc de django.test.TestCase
) nécessite une base de données de configuration. J'ai fait cette hypothèse parce que le Django docs disent:
Si vous avez besoin l'un de l'autre de plus en plus complexes et luxueux de Django fonctionnalités spécifiques comme ... les Essais ou l'utilisation de l'ORM ... alors vous devriez utiliser TransactionTestCase ou de cas de test à la place.
https://docs.djangoproject.com/en/1.6/topics/testing/tools/#django.test.SimpleTestCase
mysite/scripts/settings.py
from django.test import TransactionTestCase
from django.test.runner import DiscoverRunner
class MyDiscoverRunner(DiscoverRunner):
def run_tests(self, test_labels, extra_tests=None, **kwargs):
"""
Run the unit tests for all the test labels in the provided list.
Test labels should be dotted Python paths to test modules, test
classes, or test methods.
A list of 'extra' tests may also be provided; these tests
will be added to the test suite.
If any of the tests in the test suite inherit from
``django.test.TransactionTestCase``, databases will be setup.
Otherwise, databases will not be set up.
Returns the number of tests that failed.
"""
self.setup_test_environment()
suite = self.build_suite(test_labels, extra_tests)
# ----------------- First Addition --------------
need_databases = any(isinstance(test_case, TransactionTestCase)
for test_case in suite)
old_config = None
if need_databases:
# --------------- End First Addition ------------
old_config = self.setup_databases()
result = self.run_suite(suite)
# ----------------- Second Addition -------------
if need_databases:
# --------------- End Second Addition -----------
self.teardown_databases(old_config)
self.teardown_test_environment()
return self.suite_result(suite, result)
Enfin, j'ai ajouté la ligne suivante à mon projet settings.py fichier.
mysite/settings.py
TEST_RUNNER = 'mysite.scripts.settings.MyDiscoverRunner'
Maintenant, lors de l'exécution de seulement de non-db-dépendante des tests, mon test suite exécute un ordre de grandeur plus rapide! :)
@Cesar est droit. Après la chute accidentelle ./manage.py test --settings=no_db_settings
, sans spécifier un nom d'application, développement de base de données a été anéantie.
Pour des conditions de sécurité accrue, utilisez le même NoDbTestRunner
, mais en liaison avec les suivantes, mysite/no_db_settings.py
:
from mysite.settings import *
# Test runner with no database creation
TEST_RUNNER = 'mysite.scripts.testrunner.NoDbTestRunner'
# Use an alternative database as a safeguard against accidents
DATABASES['default']['NAME'] = '_test_mysite_db'
Vous devez créer une base de données appelée _test_mysite_db
à l'aide d'un outil de base de données. Ensuite, exécutez la commande suivante pour créer les tables correspondantes:
./manage.py syncdb --settings=mysite.no_db_settings
Si vous utilisez Sud, exécutez la commande suivante:
./manage.py migrate --settings=mysite.no_db_settings
OK!
Vous pouvez maintenant exécuter des tests unitaires hyper rapide (et de sécurité) par:
./manage.py test myapp --settings=mysite.no_db_settings