Ich schreibe Tests für eine Funktion wie die nächste:
def foo():
print 'hello world!'
Wenn ich diese Funktion testen möchte, sieht der Code folgendermaßen aus:
import sys
from foomodule import foo
def test_foo():
foo()
output = sys.stdout.getline().strip() # because stdout is an StringIO instance
assert output == 'hello world!'
Wenn ich jedoch Nosetests mit dem Parameter -s ausführe, stürzt der Test ab. Wie kann ich die Ausgabe mit unittest oder Nasenmodul abfangen?
python
unit-testing
nosetests
python-nose
Pedro Valencia
quelle
quelle
with mock.patch('sys.stdout', new_callable=StringIO.StringIO):
pypi.python.org/pypi/mockAntworten:
Ich benutze diesen Kontextmanager , um die Ausgabe zu erfassen. Es verwendet letztendlich die gleiche Technik wie einige der anderen Antworten, indem es vorübergehend ersetzt wird
sys.stdout
. Ich bevorzuge den Kontextmanager, weil er die gesamte Buchhaltung in einer einzigen Funktion zusammenfasst, sodass ich keinen Try-finally-Code neu schreiben muss und keine Setup- und Teardown-Funktionen nur dafür schreiben muss.Verwenden Sie es so:
Da der ursprüngliche Ausgabezustand beim Verlassen des
with
Blocks wiederhergestellt wird , können wir außerdem einen zweiten Erfassungsblock in derselben Funktion wie den ersten einrichten, was mit Setup- und Teardown-Funktionen nicht möglich ist und beim Schreiben von try-finally wortreich wird blockiert manuell. Diese Fähigkeit erwies sich als nützlich, wenn das Ziel eines Tests darin bestand, die Ergebnisse zweier Funktionen relativ zueinander und nicht mit einem vorberechneten Wert zu vergleichen.quelle
TypeError: unicode argument expected, got 'str'
(der an print übergebene Typ (str / unicode) ist irrelevant).from io import BytesIO as StringIO
und in Python 3 nurfrom io import StringIO
. Schien das Problem in meinen Tests zu beheben, denke ich.strip()
dieunicode
Rückkehr von aufStringIO.getvalue()
?sys
. Mit Ihrer Importanweisung erstellen Sie eine lokale Variable mit dem Namenstderr
, die eine Kopie des Werts in erhalten hatsys.stderr
. Änderungen an einem werden nicht im anderen wiedergegeben.Wenn Sie dies wirklich tun möchten, können Sie sys.stdout für die Dauer des Tests neu zuweisen.
Wenn ich diesen Code schreiben würde, würde ich
out
derfoo
Funktion lieber einen optionalen Parameter übergeben .Dann ist der Test viel einfacher:
quelle
StringIO
muss die Klasse jetzt aus demio
Modul importiert werden.from io import StringIO
funktioniert in Python 2.6+.from io import StringIO
in Python 2 verwenden, erhalten SieTypeError: unicode argument expected, got 'str'
beim Drucken eine.with redirect_stdout(out):
saved_stdout = sys.stdout
, Sie haben immer einen magischen Hinweis daraufsys.__stdout__
, z. B. brauchen Sie nursys.stdout = sys.__stdout__
in Ihrer Bereinigung.Seit Version 2.7 müssen Sie keine Neuzuweisung mehr vornehmen
sys.stdout
. Dies wird über dasbuffer
Flag bereitgestellt . Darüber hinaus ist dies das Standardverhalten von Nosetest.Hier ist ein Beispiel, das im nicht gepufferten Kontext fehlschlägt:
Sie können einstellen , Puffer durch
unit2
Befehlszeilenparameter-b
,--buffer
oder inunittest.main
Optionen. Das Gegenteil wird durchnosetest
Flagge erreicht--nocapture
.quelle
--nocapture
; Insbesondere wenn dieses Flag gesetzt ist, wird der gepufferte Modus deaktiviert. Sie haben also die Möglichkeit, entweder die Ausgabe auf dem Terminal zu sehen oder zu testen, ob die Ausgabe wie erwartet ist.Viele dieser Antworten sind für mich fehlgeschlagen, weil Sie dies
from StringIO import StringIO
in Python 3 nicht können . Hier ist ein minimaler Arbeitsausschnitt, der auf dem Kommentar von @ naxa und dem Python-Kochbuch basiert.quelle
In Python 3.5 können Sie
contextlib.redirect_stdout()
und verwendenStringIO()
. Hier ist die Änderung an Ihrem Codequelle
redirect_stdout()
undredirect_stderr()
geben ihr Eingabeargument zurück. Also,with contextlib.redirect_stdout(StringIO()) as temp_stdout:
gibt Ihnen alles in einer Zeile. Getestet mit 3.7.1.Ich lerne gerade erst Python und habe mit einem ähnlichen Problem wie oben mit Unit-Tests für Methoden mit Ausgabe zu kämpfen. Mein bestehender Unit-Test für das oben genannte foo-Modul sieht folgendermaßen aus:
quelle
sys.stdout.getvalue().strip()
und nicht betrügen im Vergleich zu\n
:)from io import StringIO
Das Schreiben von Tests zeigt uns oft, wie wir unseren Code besser schreiben können. Ähnlich wie bei Shane möchte ich noch eine andere Sichtweise vorschlagen. Möchten Sie wirklich behaupten, dass Ihr Programm eine bestimmte Zeichenfolge ausgegeben hat oder nur eine bestimmte Zeichenfolge für die Ausgabe erstellt hat? Dies wird einfacher zu testen, da wir wahrscheinlich davon ausgehen können, dass die Python-
print
Anweisung ihre Aufgabe korrekt erfüllt.Dann ist Ihr Test sehr einfach:
Wenn Sie wirklich die tatsächliche Ausgabe Ihres Programms testen müssen, können Sie dies natürlich ignorieren. :) :)
quelle
foo()
es wahrscheinlich kein Problem , wenn Sie nichts anderes tun, als die print-Anweisung aufzurufen .Basierend auf Rob Kennedys Antwort habe ich eine klassenbasierte Version des Kontextmanagers geschrieben, um die Ausgabe zu puffern.
Verwendung ist wie:
Hier ist die Implementierung:
quelle
Oder erwägen Sie die Verwendung
pytest
, es verfügt über eine integrierte Unterstützung für die Bestätigung von stdout und stderr. Siehe Dokumentequelle
Sowohl n611x007 als auch Noumenon schlugen bereits die Verwendung vor
unittest.mock
, aber diese Antwort passt Acumenus an, um zu zeigen, wie Sieunittest.TestCase
Methoden zur Interaktion mit einem verspotteten einfach umschließen könnenstdout
.quelle
Aufbauend auf all den fantastischen Antworten in diesem Thread habe ich es so gelöst. Ich wollte es so gut wie möglich auf Lager halten. Ich ergänzte den Unit - Test - Mechanismus
setUp()
zu Erfassungsys.stdout
undsys.stderr
fügte neuer assert APIs den erfassten Wert mit einem erwarteten Wert zu prüfen und dann wiederherstellensys.stdout
undsys.stderr
auftearDown(). I did this to keep a similar unit test API as the built-in
UnittestAPI while still being able to unit test values printed to
sys.stdoutor
sys.stderr`.Wenn der Komponententest ausgeführt wird, lautet die Ausgabe:
quelle