Ich verwende einen einfachen Unit-Test-basierten Testläufer, um meine Django-Anwendung zu testen.
Meine Anwendung selbst ist so konfiguriert, dass sie einen grundlegenden Logger in settings.py verwendet.
logging.basicConfig(level=logging.DEBUG)
Und in meinem Anwendungscode mit:
logger = logging.getLogger(__name__)
logger.setLevel(getattr(settings, 'LOG_LEVEL', logging.DEBUG))
Wenn Sie jedoch Unittests ausführen, möchte ich die Protokollierung deaktivieren, damit meine Ausgabe der Testergebnisse nicht überladen wird. Gibt es eine einfache Möglichkeit, die Protokollierung global zu deaktivieren, damit die anwendungsspezifischen Protokollierer beim Ausführen von Tests keine Daten an die Konsole schreiben?
python
django
unit-testing
logging
Shreddd
quelle
quelle
Antworten:
Deaktiviert alle Protokollierungsanrufe mit Ebenen, die weniger schwerwiegend als oder gleich sind
CRITICAL
. Die Protokollierung kann mit wieder aktiviert werdenquelle
logging.disable
(aus der akzeptierten Antwort) obentests.py
in Ihrer Anwendung, die die Protokollierung durchführt, platzieren.tearDown()
Methode:logging.disable(logging.NOTSET)
Bringt die Protokollierung wieder ordentlich an.tests
Moduls ist sehr nützlich.Da Sie sich in Django befinden, können Sie diese Zeilen zu Ihren settings.py hinzufügen:
Auf diese Weise müssen Sie diese Zeile nicht bei jedem
setUp()
Ihrer Tests hinzufügen .Auf diese Weise können Sie auch einige nützliche Änderungen für Ihre Testanforderungen vornehmen.
Es gibt eine andere "schönere" oder "sauberere" Möglichkeit, Ihren Tests Besonderheiten hinzuzufügen, und das macht Ihren eigenen Testläufer.
Erstellen Sie einfach eine Klasse wie diese:
Und jetzt fügen Sie Ihrer settings.py-Datei Folgendes hinzu:
Auf diese Weise können Sie eine wirklich praktische Änderung vornehmen, die der andere Ansatz nicht tut. Django testet lediglich die gewünschten Anwendungen. Sie können dies tun, indem Sie das
test_labels
Hinzufügen dieser Zeile zum Testläufer ändern :quelle
Die anderen Antworten verhindern das "Schreiben von Inhalten an die Konsole", indem die Protokollierungsinfrastruktur global so eingestellt wird, dass alles ignoriert wird. Das funktioniert, aber ich finde es zu stumpf. Mein Ansatz besteht darin, eine Konfigurationsänderung durchzuführen, die nur das tut, was erforderlich ist, um zu verhindern, dass Protokolle auf der Konsole veröffentlicht werden. Also füge ich meinem : einen benutzerdefinierten Protokollierungsfilter hinzu
settings.py
:Und ich konfiguriere die Django-Protokollierung so , dass sie den Filter verwendet:
Endergebnis: Wenn ich teste, geht nichts an die Konsole, aber alles andere bleibt gleich.
Warum das tun?
Ich entwerfe Code, der Protokollierungsanweisungen enthält, die nur unter bestimmten Umständen ausgelöst werden und die genau die Daten ausgeben sollen, die ich für die Diagnose benötige, wenn etwas schief geht. Daher teste ich , dass sie das tun, was sie tun sollen, und daher ist es für mich nicht sinnvoll, die Protokollierung vollständig zu deaktivieren. Ich möchte nicht feststellen, dass das, was ich für protokolliert hielt , nicht protokolliert wird , sobald die Software in Produktion ist.
Darüber hinaus erfassen einige Testläufer (z. B. Nose) während des Tests Protokolle und geben den relevanten Teil des Protokolls zusammen mit einem Testfehler aus. Dies ist hilfreich, um herauszufinden, warum ein Test fehlgeschlagen ist. Wenn die Protokollierung vollständig deaktiviert ist, kann nichts erfasst werden.
quelle
test_settings.py
Datei neben der meines Projektssettings.py
. Es ist so eingestellt, dass es geladen wirdsettings.py
und einige Änderungen wie "setTESTING_MODE
to" vornimmtTrue
. Meine Testläufer sind so organisiert, dasstest_settings
das Modul für die Django-Projekteinstellungen geladen wird. Es gibt viele Möglichkeiten, dies zu tun. Normalerweise setze ich die UmgebungsvariableDJANGO_SETTINGS_MODULE
aufproj.test_settings
.Ich mag Hasseks Idee eines benutzerdefinierten Testläufers. Es ist zu beachten, dass dies
DjangoTestSuiteRunner
nicht mehr der Standard-Testläufer in Django 1.6+ ist, sondern durch den ersetzt wurdeDiscoverRunner
. Für das Standardverhalten sollte der Testläufer eher wie folgt aussehen:quelle
helpers
, die nur Utils enthält, die von keiner anderen Stelle im Projekt importiert werden.Ich habe festgestellt, dass für Tests innerhalb
unittest
oder ähnlich eines Frameworks der effektivste Weg, um unerwünschte Anmeldungen in Komponententests sicher zu deaktivieren, darin besteht, diesetUp
/tearDown
-Methoden eines bestimmten Testfalls zu aktivieren / deaktivieren . Auf diese Weise kann ein Ziel speziell festgelegt werden, wo Protokolle deaktiviert werden sollen. Sie können dies auch explizit auf dem Logger der Klasse tun, die Sie testen.quelle
Ich verwende einen einfachen Methodendekorateur, um die Protokollierung nur in einer bestimmten Testmethode zu deaktivieren.
Und dann benutze ich es wie im folgenden Beispiel:
quelle
Es gibt eine hübsche und saubere Methode, um die Anmeldung von Tests mit der
unittest.mock.patch
Methode auszusetzen .foo.py :
tests.py :
Und
python3 -m unittest tests
erzeugt keine Protokollausgabe.quelle
Manchmal möchten Sie die Protokolle und manchmal nicht. Ich habe diesen Code in meinem
settings.py
Wenn Sie also Ihren Test mit den
--no-logs
Optionen ausführen , erhalten Sie nur diecritical
Protokolle:Es ist sehr hilfreich, wenn Sie die Tests für Ihren kontinuierlichen Integrationsfluss beschleunigen möchten.
quelle
Wenn Sie nicht möchten, dass es wiederholt in setUp () und tearDown () für unittest ein- und ausgeschaltet wird (sehen Sie den Grund dafür nicht), können Sie es einfach einmal pro Klasse tun:
quelle
In Fällen, in denen ich einen bestimmten Logger vorübergehend unterdrücken möchte, habe ich einen kleinen Kontextmanager geschrieben, den ich als nützlich empfunden habe:
Sie verwenden es dann wie folgt:
Dies hat den Vorteil, dass der Logger nach Abschluss wieder aktiviert (oder auf seinen vorherigen Zustand zurückgesetzt) wird
with
.quelle
Sie können dies im Verzeichnis der obersten Ebene für Unit-Tests-
__init__.py
Dateien ablegen. Dadurch wird die globale Protokollierung in der Unit-Test-Suite deaktiviert.quelle
In meinem Fall habe ich eine Einstellungsdatei,
settings/test.py
die speziell zu Testzwecken erstellt wurde. So sieht es aus:Ich habe eine Umgebungsvariable
DJANGO_SETTINGS_MODULE=settings.test
auf gesetzt/etc/environment
.quelle
Wenn Sie verschiedene Initialisierungsmodule für Test, Entwicklung und Produktion haben, können Sie alles deaktivieren oder im Initialisierer umleiten. Ich habe local.py, test.py und Production.py, die alle von common.y erben
common.py führt die gesamte Hauptkonfiguration einschließlich dieses Snippets aus:
Dann habe ich in test.py folgendes:
Dies ersetzt den Konsolenhandler durch einen FileHandler und bedeutet, dass weiterhin protokolliert wird, aber ich muss die Produktionscodebasis nicht berühren.
quelle
Wenn Sie verwenden
pytest
:Da pytest Protokollnachrichten erfasst und nur für fehlgeschlagene Tests anzeigt, möchten Sie normalerweise keine Protokollierung deaktivieren. Verwenden Sie stattdessen eine separate
settings.py
Datei für Tests (z. B.test_settings.py
) und fügen Sie sie hinzu:Dies weist Django an, die Konfiguration der Protokollierung insgesamt zu überspringen. Das
LOGGING
Einstellung wird ignoriert und kann aus den Einstellungen entfernt werden.Mit diesem Ansatz erhalten Sie keine Protokollierung für bestandene Tests und alle verfügbaren Protokolle für fehlgeschlagene Tests.
Die Tests werden mit der Protokollierung ausgeführt, die von eingerichtet wurde
pytest
. Es kann in denpytest
Einstellungen (ztox.ini
. B. ) nach Ihren Wünschen konfiguriert werden . Verwenden Sielog_level = DEBUG
(oder das entsprechende Befehlszeilenargument), um Protokollnachrichten auf Debug-Ebene einzuschließen .quelle