Gibt es eine Möglichkeit, Django-Unittests zu schreiben, ohne eine Datenbank einzurichten? Ich möchte die Geschäftslogik testen, für deren Einrichtung die Datenbank nicht erforderlich ist. Und obwohl es schnell ist, eine Datenbank einzurichten, brauche ich sie in manchen Situationen wirklich nicht.
126
Antworten:
Sie können DjangoTestSuiteRunner in Unterklassen unterteilen und die zu übergebenden Methoden setup_databases und teardown_databases überschreiben.
Erstellen Sie eine neue Einstellungsdatei und setzen Sie TEST_RUNNER auf die neue Klasse, die Sie gerade erstellt haben. Wenn Sie dann Ihren Test ausführen, geben Sie Ihre neue Einstellungsdatei mit dem Flag --settings an.
Folgendes habe ich getan:
Erstellen Sie einen benutzerdefinierten Testanzugläufer, der dem folgenden ähnelt:
Erstellen Sie benutzerdefinierte Einstellungen:
Wenn Sie Ihre Tests ausführen, führen Sie sie wie folgt aus, wobei das Flag --settings auf Ihre neue Einstellungsdatei gesetzt ist:
UPDATE: April / 2018
Da Django 1.8, das Modul wurde bewegt zu .
django.test.simple.DjangoTestSuiteRunner
'django.test.runner.DiscoverRunner'
Weitere Informationen finden Sie im offiziellen Dokumentabschnitt über benutzerdefinierte Testläufer.
quelle
--testrunner
Option angeben .Im Allgemeinen können Tests in einer Anwendung in zwei Kategorien eingeteilt werden
Django unterstützt sowohl Unit- als auch Integrationstests.
Unit-Tests erfordern kein Einrichten und Herunterfahren der Datenbank. Diese sollten wir von SimpleTestCase erben .
Bei der Integration erben Testfälle, die von TestCase geerbt werden, wiederum von TransactionTestCase und es wird die Datenbank eingerichtet und heruntergefahren, bevor jeder Test ausgeführt wird.
Diese Strategie stellt sicher, dass die Datenbank nur für die Testfälle erstellt und zerstört wird, die auf die Datenbank zugreifen, und daher die Tests effizienter sind
quelle
Von
django.test.simple
Also überschreiben
DiscoverRunner
stattDjangoTestSuiteRunner
.Verwenden Sie so:
quelle
Ich habe mich entschieden, von
django.test.runner.DiscoverRunner
derrun_tests
Methode zu erben und sie ein paar Mal zu ergänzen .Mein erster Zusatz prüft, ob das Einrichten einer Datenbank erforderlich ist, und ermöglicht die Aktivierung der normalen
setup_databases
Funktionalität, wenn eine Datenbank erforderlich ist. Mein zweiter Zusatz ermöglicht dasteardown_databases
Ausführen des Normalen , wenn diesetup_databases
Methode ausgeführt werden durfte.Mein Code geht davon aus, dass für jeden TestCase, der von
django.test.TransactionTestCase
(und damitdjango.test.TestCase
) erbt , eine Datenbank eingerichtet werden muss. Ich habe diese Annahme gemacht, weil die Django-Dokumente sagen:https://docs.djangoproject.com/de/1.6/topics/testing/tools/#django.test.SimpleTestCase
mysite / scripts / settings.py
Schließlich habe ich die folgende Zeile zur Datei settings.py meines Projekts hinzugefügt.
mysite / settings.py
Wenn ich jetzt nur nicht db-abhängige Tests ausführe, läuft meine Testsuite um eine Größenordnung schneller! :) :)
quelle
Aktualisiert: Siehe auch diese Antwort für die Verwendung eines Tools eines Drittanbieters
pytest
.@Cesar ist richtig. Nach versehentlichem Ausführen
./manage.py test --settings=no_db_settings
ohne Angabe eines App-Namens wurde meine Entwicklungsdatenbank gelöscht.Verwenden Sie zur sichereren Verwendung dasselbe
NoDbTestRunner
, jedoch in Verbindung mit den folgendenmysite/no_db_settings.py
:Sie müssen eine Datenbank erstellen, die
_test_mysite_db
mit einem externen Datenbank-Tool aufgerufen wird . Führen Sie dann den folgenden Befehl aus, um die entsprechenden Tabellen zu erstellen:Wenn Sie South verwenden, führen Sie auch den folgenden Befehl aus:
OK!
Sie können jetzt Unit-Tests blitzschnell (und sicher) durchführen, indem Sie:
quelle
Als Alternative zum Ändern Ihrer Einstellungen, um NoDbTestRunner "sicher" zu machen, finden Sie hier eine modifizierte Version von NoDbTestRunner, mit der die aktuelle Datenbankverbindung geschlossen und die Verbindungsinformationen aus den Einstellungen und dem Verbindungsobjekt entfernt werden. Funktioniert für mich, testen Sie es in Ihrer Umgebung, bevor Sie sich darauf verlassen :)
quelle
__getitem__
. Verwenden Sie diese Option,connections._connections.default
um auf das Objekt zuzugreifen.Eine andere Lösung wäre, Ihre Testklasse einfach
unittest.TestCase
von einer der Testklassen von Django erben zu lassen . Die Django-Dokumente ( https://docs.djangoproject.com/de/2.0/topics/testing/overview/#writing-tests ) enthalten die folgende Warnung:Wenn Ihr Test die Datenbank jedoch nicht verwendet, muss Sie diese Warnung nicht betreffen, und Sie können die Vorteile nutzen, wenn Sie nicht jeden Testfall in einer Transaktion ausführen müssen.
quelle
Die obigen Lösungen sind auch in Ordnung. Die folgende Lösung reduziert jedoch auch die Erstellungszeit der Datenbank, wenn mehr Migrationen vorhanden sind. Während des Komponententests wird die Ausführung von syncdb anstelle aller Südmigrationen viel schneller sein.
quelle
Mein Webhost erlaubt nur das Erstellen und Löschen von Datenbanken über die Web-GUI. Daher wurde beim Ausführen der Fehlermeldung "Fehler beim Erstellen der Testdatenbank: Berechtigung verweigert" angezeigt
python manage.py test
.Ich hatte gehofft, die Option --keepdb für django-admin.py verwenden zu können, aber sie scheint ab Django 1.7 nicht mehr unterstützt zu werden.
Am Ende habe ich den Django-Code in ... / django / db / backends / created.py geändert, insbesondere die Funktionen _create_test_db und _destroy_test_db.
Denn
_create_test_db
ich habe diecursor.execute("CREATE DATABASE ...
Zeile auskommentiert und durch ersetzt,pass
damit dertry
Block nicht leer ist.Denn
_destroy_test_db
ich habe es gerade auskommentiertcursor.execute("DROP DATABASE
- ich musste es nicht durch irgendetwas ersetzen, da es bereits einen anderen Befehl im block (time.sleep(1)
) gab.Danach liefen meine Tests einwandfrei - obwohl ich eine test_-Version meiner regulären Datenbank separat eingerichtet habe.
Dies ist natürlich keine großartige Lösung, da es bei einem Upgrade von Django nicht funktioniert, aber ich hatte aufgrund der Verwendung von virtualenv eine lokale Kopie von Django, sodass ich zumindest die Kontrolle darüber habe, wann / ob ich auf eine neuere Version aktualisiere.
quelle
Eine andere Lösung, die nicht erwähnt wurde: Dies war für mich einfach zu implementieren, da ich bereits mehrere Einstellungsdateien (für lokal / Staging / Produktion) habe, die von base.py erben. Im Gegensatz zu anderen Personen musste ich DATABASES ['default'] nicht überschreiben, da DATABASES nicht in base.py festgelegt ist
SimpleTestCase hat immer noch versucht, eine Verbindung zu meiner Testdatenbank herzustellen und Migrationen auszuführen. Wenn ich eine Datei config / settings / test.py erstellt habe, in der DATABASES nicht festgelegt wurde, wurden meine Komponententests ohne diese Datei ausgeführt. Es erlaubte mir, Modelle zu verwenden, die Fremdschlüssel und eindeutige Einschränkungsfelder hatten. (Die umgekehrte Suche nach Fremdschlüsseln, für die eine Datenbank-Suche erforderlich ist, schlägt fehl.)
(Django 2.0.6)
PS-Code-Schnipsel
quelle
Wenn Sie den Nasentestläufer (Django-Nase) verwenden, können Sie Folgendes tun:
my_project/lib/nodb_test_runner.py
::In Ihrem können
settings.py
Sie dort den Testläufer angeben, dhTEST_RUNNER = 'lib.nodb_test_runner.NoDbTestRunner' . # Was 'django_nose.NoseTestSuiteRunner'
ODER
Ich wollte es nur zum Ausführen bestimmter Tests, also führe ich es so aus:
quelle