Wie drucke ich in pytest auf die Konsole?

174

Ich versuche, TDD (testgetriebene Entwicklung) mit zu verwenden pytest. pytestwerde nicht printzur Konsole, wenn ich benutze print.

Ich benutze es pytest my_tests.py, um es auszuführen.

Das documentationscheint zu sagen, dass es standardmäßig funktionieren sollte: http://pytest.org/latest/capture.html

Aber:

import myapplication as tum

class TestBlogger:

    @classmethod
    def setup_class(self):
        self.user = "alice"
        self.b = tum.Blogger(self.user)
        print "This should be printed, but it won't be!"

    def test_inherit(self):
        assert issubclass(tum.Blogger, tum.Site)
        links = self.b.get_links(posts)
        print len(links)   # This won't print either.

Auf meiner Standardausgabekonsole wird nichts gedruckt (nur der normale Fortschritt und wie viele Tests bestanden / fehlgeschlagen sind).

Und das Skript, das ich teste, enthält print:

class Blogger(Site):
    get_links(self, posts):
        print len(posts)   # It won't get printed in the test.

Im unittestModul wird standardmäßig alles gedruckt, genau das, was ich brauche. Ich möchte jedoch pytestaus anderen Gründen verwenden.

Weiß jemand, wie die Druckanweisungen angezeigt werden?

BBedit
quelle
1
Möglicherweise wird stdout überschrieben. Was passiert, wenn Sie verwenden sys.stdout.write("Test")? Wie wäre es sys.__stdout__.write("Test")? Letzterer sollte immer in das systemdefinierte Standardout schreiben, das die Konsole sein sollte. Wenn die beiden Befehle unterschiedliche Aktionen ausführen, wird stdout geändert. Wenn sie dasselbe tun, ist das Problem etwas anderes.
TheSoundDefense

Antworten:

205

Erfasst standardmäßig py.testdas Ergebnis des Standardausgangs, damit es steuern kann, wie es ausgedruckt wird. Wenn dies nicht der Fall wäre, würde es viel Text ausspucken, ohne den Kontext, in dem dieser Test diesen Text gedruckt hat.

Wenn ein Test jedoch fehlschlägt, enthält er einen Abschnitt im resultierenden Bericht, der zeigt, was in diesem bestimmten Test als Standard gedruckt wurde.

Beispielsweise,

def test_good():
    for i in range(1000):
        print(i)

def test_bad():
    print('this should fail!')
    assert False

Ergebnisse in der folgenden Ausgabe:

>>> py.test tmp.py
============================= test session starts ==============================
platform darwin -- Python 2.7.6 -- py-1.4.20 -- pytest-2.5.2
plugins: cache, cov, pep8, xdist
collected 2 items

tmp.py .F

=================================== FAILURES ===================================
___________________________________ test_bad ___________________________________

    def test_bad():
        print('this should fail!')
>       assert False
E       assert False

tmp.py:7: AssertionError
------------------------------- Captured stdout --------------------------------
this should fail!
====================== 1 failed, 1 passed in 0.04 seconds ======================

Beachten Sie den Captured stdoutAbschnitt.

Wenn Sie printAnweisungen sehen möchten, während sie ausgeführt werden, können Sie das -sFlag an übergeben py.test. Beachten Sie jedoch, dass dies manchmal schwierig zu analysieren ist.

>>> py.test tmp.py -s
============================= test session starts ==============================
platform darwin -- Python 2.7.6 -- py-1.4.20 -- pytest-2.5.2
plugins: cache, cov, pep8, xdist
collected 2 items

tmp.py 0
1
2
3
... and so on ...
997
998
999
.this should fail!
F

=================================== FAILURES ===================================
___________________________________ test_bad ___________________________________

    def test_bad():
        print('this should fail!')
>       assert False
E       assert False

tmp.py:7: AssertionError
====================== 1 failed, 1 passed in 0.02 seconds ======================
Tbekolay
quelle
2
Sehr praktisch. Gut gemacht!
cmc
1
hmm ... protokolliert meine Druckanweisungen immer noch nicht
Tim Boland
67

Mit der -sOption wird die Ausgabe aller Funktionen gedruckt, die möglicherweise zu viel sind.

Wenn Sie eine bestimmte Ausgabe benötigen, bietet die von Ihnen erwähnte Dokumentseite einige Vorschläge:

  1. Fügen Sie assert False, "dumb assert to make PyTest print my stuff"am Ende Ihrer Funktion ein, und Sie sehen Ihre Ausgabe aufgrund eines fehlgeschlagenen Tests.

  2. Sie haben ein spezielles Objekt von PyTest an Sie übergeben, und Sie können die Ausgabe in eine Datei schreiben, um sie später zu überprüfen

    def test_good1(capsys):
        for i in range(5):
            print i
        out, err = capsys.readouterr()
        open("err.txt", "w").write(err)
        open("out.txt", "w").write(out)

    Sie können die Dateien outund errin einer separaten Registerkarte öffnen und vom Editor automatisch für Sie aktualisieren lassen oder einen einfachen py.test; cat out.txtShell-Befehl ausführen, um Ihren Test auszuführen.

Das ist eine ziemlich hackige Art, Dinge zu tun, aber vielleicht ist es das, was Sie brauchen: TDD bedeutet schließlich, dass Sie sich mit Dingen anlegen und sie sauber und leise lassen, wenn sie fertig sind :-).

dmitry_romanov
quelle
Ich habe Version 1 mit Pytest 3.8.1 ausprobiert. Leider wird nur der Testfunktionsblock gedruckt, aber nicht die Ausgabe von Druckanweisungen :( Weitere Tricks dafür?
UV
@UV - Anstatt die print()Funktion zu verwenden, sollten Sie die Variable oder Nachricht, die Sie drucken möchten , nach dem Komma in die assert-Anweisung einfügen . ZB assert False, what_are_youwird der Wert von what_are_youim Pytest-Bericht "ausgedruckt".
Mart Van de Ven
43

Kurze Antwort

Verwenden Sie die -sOption:

pytest -s

Detaillierte Antwort

Aus den Dokumenten :

Während der Testausführung werden alle an stdout und stderr gesendeten Ausgaben erfasst. Wenn ein Test oder eine Setup-Methode fehlschlägt, wird die entsprechende erfasste Ausgabe normalerweise zusammen mit dem Fehler-Traceback angezeigt.

pytesthat die Möglichkeit , --capture=methodin der methodpro-Testverfahren ist die Erfassung und könnte einer der folgenden sein: fd, sysoder no. pytesthat auch die Option, für -sdie es sich um eine Verknüpfung handelt --capture=no, und mit dieser Option können Sie Ihre Druckanweisungen in der Konsole anzeigen.

pytest --capture=no     # show print statements in console
pytest -s               # equivalent to previous command

Festlegen von Erfassungsmethoden oder Deaktivieren der Erfassung

Es gibt zwei Möglichkeiten, die pytestErfassung durchzuführen:

  1. Erfassung auf Dateideskriptor-Ebene (FD) (Standard): Alle Schreibvorgänge in die Dateideskriptoren 1 und 2 des Betriebssystems werden erfasst.

  2. Erfassung auf Sys-Ebene : Es werden nur Schreibvorgänge in Python-Dateien sys.stdout und sys.stderr erfasst. Es wird keine Erfassung von Schreibvorgängen an Dateideskriptoren durchgeführt.

pytest -s            # disable all capturing
pytest --capture=sys # replace sys.stdout/stderr with in-mem files
pytest --capture=fd  # also point filedescriptors 1 and 2 to temp file
lmiguelvargasf
quelle
17

Ich musste wichtige Warnungen über übersprungene Tests genau dann ausdrucken, wenn PyTestbuchstäblich alles stummgeschaltet war .

Ich wollte keinen Test zum Senden eines Signals nicht bestehen, also habe ich einen Hack wie folgt durchgeführt:

def test_2_YellAboutBrokenAndMutedTests():
    import atexit
    def report():
        print C_patch.tidy_text("""
In silent mode PyTest breaks low level stream structure I work with, so
I cannot test if my functionality work fine. I skipped corresponding tests.
Run `py.test -s` to make sure everything is tested.""")
    if sys.stdout != sys.__stdout__:
        atexit.register(report)

Das atexitModul ermöglicht es mir, Dinge zu drucken, nachdem PyTest die Ausgabestreams freigegeben wurden. Die Ausgabe sieht wie folgt aus:

============================= test session starts ==============================
platform linux2 -- Python 2.7.3, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
rootdir: /media/Storage/henaro/smyth/Alchemist2-git/sources/C_patch, inifile: 
collected 15 items 

test_C_patch.py .....ssss....s.

===================== 10 passed, 5 skipped in 0.15 seconds =====================
In silent mode PyTest breaks low level stream structure I work with, so
I cannot test if my functionality work fine. I skipped corresponding tests.
Run `py.test -s` to make sure everything is tested.
~/.../sources/C_patch$

Die Nachricht wird gedruckt, auch wenn sie PyTestsich im unbeaufsichtigten Modus befindet, und wird nicht gedruckt, wenn Sie Inhalte ausführen py.test -s, sodass bereits alles gut getestet wurde.

dmitry_romanov
quelle
1
Perfekt für die Ausgabe von benutzerdefinierten Testmetriken.
16.
5

Nach der pytest docs , pytest --capture=syssollte funktionieren. Wenn Sie den Standard in einem Test erfassen möchten, lesen Sie das Capsys-Gerät.

Karthik Gomadam Rajagopal
quelle
Es ist Arbeit für mich, wenn Druckvariable im Terminal benötigt wird ...
Sukma Saputra
2

Ich bin ursprünglich hierher gekommen, um herauszufinden, wie man PyTestin der VSCode-Konsole druckt, während der Unit-Test von dort aus ausgeführt / debuggt wird. Dies kann mit der folgenden launch.jsonKonfiguration erfolgen. Gegeben .venvder Ordner der virtuellen Umgebung.

    "version": "0.2.0",
    "configurations": [
        {
            "name": "PyTest",
            "type": "python",
            "request": "launch",
            "stopOnEntry": false,
            "pythonPath": "${config:python.pythonPath}",
            "module": "pytest",
            "args": [
                "-sv"
            ],
            "cwd": "${workspaceRoot}",
            "env": {},
            "envFile": "${workspaceRoot}/.venv",
            "debugOptions": [
                "WaitOnAbnormalExit",
                "WaitOnNormalExit",
                "RedirectOutput"
            ]
        }
    ]
}
dummyDev
quelle