Gibt es einen einfachen Mechanismus zum Überschreiben von Django-Einstellungen für einen Komponententest? Ich habe einen Manager für eines meiner Modelle, der eine bestimmte Anzahl der neuesten Objekte zurückgibt. Die Anzahl der zurückgegebenen Objekte wird durch eine NUM_LATEST-Einstellung definiert.
Dies kann dazu führen, dass meine Tests fehlschlagen, wenn jemand die Einstellung ändert. Wie kann ich die Einstellungen überschreiben setUp()
und anschließend wiederherstellen tearDown()
? Wenn das nicht möglich ist, gibt es eine Möglichkeit, die Methode zu patchen oder die Einstellungen zu verspotten?
EDIT: Hier ist mein Manager-Code:
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]
Der Manager settings.NEWS_LATEST_MAX
schneidet das Abfrageset. Das getattr()
wird einfach verwendet, um eine Standardeinstellung anzugeben, falls die Einstellung nicht vorhanden ist.
quelle
Antworten:
BEARBEITEN: Diese Antwort gilt, wenn Sie die Einstellungen für eine kleine Anzahl spezifischer Tests ändern möchten .
Seit Django 1.4 gibt es Möglichkeiten, Einstellungen während Tests zu überschreiben: https://docs.djangoproject.com/de/dev/topics/testing/tools/#overriding-settings
TestCase verfügt über einen Kontextmanager für self.settings und einen @ override_settings-Dekorator, der entweder auf eine Testmethode oder eine gesamte TestCase-Unterklasse angewendet werden kann.
Diese Funktionen gab es in Django 1.3 noch nicht.
Wenn Sie die Einstellungen für alle Ihre Tests ändern möchten , müssen Sie eine separate Einstellungsdatei für den Test erstellen, in der Einstellungen aus Ihrer Haupteinstellungsdatei geladen und überschrieben werden können. In den anderen Antworten gibt es mehrere gute Ansätze dafür; Ich habe erfolgreiche Variationen sowohl der Ansätze von hspander als auch von dmitrii gesehen .
quelle
self.settings().wrapped.MEDIA_ROOT
, aber das ist ziemlich schrecklich.@modify_settings(MIDDLEWARE_CLASSES=...
(Danke für diese Antwort)Sie können mit der
UnitTest
Unterklasse alles tun, was Sie möchten, einschließlich des Festlegens und Lesens von Instanzeigenschaften:Da die Django-Testfälle jedoch mit einem Thread ausgeführt werden, bin ich gespannt, was den NUM_LATEST-Wert sonst noch ändern könnte. Wenn dieses "etwas anderes" von Ihrer Testroutine ausgelöst wird, bin ich mir nicht sicher, ob durch das Patchen von Affen der Test gespeichert wird, ohne die Richtigkeit der Tests selbst zu beeinträchtigen.
quelle
settings.TEMPLATE_LOADERS
... Das ist also zumindest nicht allgemein, die Einstellungen oder Django werden nicht neu geladen oder irgendetwas mit diesem Trick.Obwohl das Überschreiben der Konfiguration der Einstellungen zur Laufzeit hilfreich sein kann, sollten Sie meiner Meinung nach eine separate Datei zum Testen erstellen. Dies spart viel Konfiguration für Tests und würde sicherstellen, dass Sie niemals etwas Irreversibles tun (wie das Bereinigen der Staging-Datenbank).
Angenommen, Ihre Testdatei befindet sich in 'my_project / test_settings.py', fügen Sie hinzu
in Ihrer manage.py. Dadurch wird sichergestellt, dass Sie beim
python manage.py test
Ausführen nur test_settings verwenden. Wenn Sie einen anderen Testclient wie pytest verwenden, können Sie diesen genauso einfach zu pytest.ini hinzufügenquelle
Sie können die
--settings
Option beim Ausführen von Tests übergebenquelle
Update : Die folgende Lösung wird nur für Django 1.3.x und früher benötigt. Für> 1.4 siehe die Antwort von slinkp .
Wenn Sie in Ihren Tests häufig Einstellungen ändern und Python ≥2,5 verwenden, ist dies auch praktisch:
Dann können Sie tun:
quelle
yield
Anweisung hinzugefügt , wobei der letzte Teil der Funktion imfinally
Block enthalten ist, sodass die Einstellungen immer zurückgesetzt werden.@override_settings
ist großartig, wenn Sie nicht viele Unterschiede zwischen Ihren Produktions- und Testumgebungskonfigurationen haben.In anderen Fällen sollten Sie nur andere Einstellungsdateien haben. In diesem Fall sieht Ihr Projekt folgendermaßen aus:
Sie müssen also die meisten Einstellungen in
base.py
und dann in anderen Dateien haben, um alles von dort zu importieren und einige Optionen zu überschreiben. Sotest.py
sieht Ihre Datei aus:Und dann müssen Sie entweder die
--settings
Option wie in der Antwort von @MicroPyramid angeben oder dieDJANGO_SETTINGS_MODULE
Umgebungsvariable angeben , und dann können Sie Ihre Tests ausführen:quelle
Dies wurde beim Versuch gefunden, einige Doctests zu korrigieren ... Der Vollständigkeit halber möchte ich erwähnen, dass Sie dies tun sollten, bevor Sie etwas anderes importieren, wenn Sie die Einstellungen bei der Verwendung von Doctests ändern möchten ...
quelle
Für Pytest- Benutzer.
Das größte Problem ist:
override_settings
funktioniert nicht mit pytest.TestCase
unterordnen, funktioniert es, aber dann können Sie keine Pytest-Geräte verwenden.Die Lösung besteht darin, das hier
settings
dokumentierte Gerät zu verwenden .Beispiel
Und falls Sie mehrere Felder aktualisieren müssen
quelle
Ich benutze Pytest.
Ich habe es folgendermaßen geschafft:
quelle
Sie können die Einstellungen im Test folgendermaßen überschreiben:
Und wenn Sie dieselben Einstellungen in einer anderen Datei benötigen, können Sie diese direkt importieren
test_settings
.quelle
Sie können die Einstellung auch für eine einzelne Testfunktion überschreiben.
oder Sie können die Einstellung für jede Funktion in der Klasse überschreiben.
quelle
Wenn Sie mehrere Testdateien in einem Unterverzeichnis (Python-Paket) abgelegt haben, können Sie die Einstellungen für alle diese Dateien basierend auf der Bedingung des Vorhandenseins einer Testzeichenfolge in sys.argv überschreiben
__init__.py:
Nicht der beste Ansatz. Verwendet es, um den Sellerie-Broker von Redis in Memory zu ändern.
quelle
Ich habe eine neue Datei settings_test.py erstellt, die alles aus der Datei settings.py importiert und zu Testzwecken alle Änderungen ändert. In meinem Fall wollte ich beim Testen einen anderen Cloud-Speicher-Bucket verwenden.
settings_test.py:
manage.py:
quelle