887 Stimmen

Wie kann ich die normale Druckausgabe sehen, die während eines Pytestlaufs erzeugt wird?

Manchmal möchte ich einfach nur ein paar Druckanweisungen in meinen Code einfügen und sehen, was ausgedruckt wird, wenn ich sie ausführe. Normalerweise "übe" ich das mit bestehenden pytest-Tests. Aber wenn ich diese ausführe, scheine ich nicht in der Lage zu sein, eine Standardausgabe zu sehen (zumindest aus PyCharm, meiner IDE).

Gibt es eine einfache Möglichkeit, die Standardausgabe während eines Pytestlaufs zu sehen?

1082voto

hpk42 Punkte 18945

En -s Schalter deaktiviert die Aufzeichnung pro Test (nur wenn ein Test fehlschlägt).

-s ist gleichbedeutend mit --capture=no .

404voto

Sunthar Punkte 2291

Pytest fängt das stdout von einzelnen Tests auf und zeigt es nur unter bestimmten Bedingungen an, zusammen mit der Zusammenfassung der Tests, die es standardmäßig ausgibt.

Zusätzliche zusammenfassende Informationen kann mit der Option '-r' angezeigt werden:

pytest -rP

zeigt die erfasste Ausgabe der bestandenen Tests.

pytest -rx

zeigt die aufgezeichnete Ausgabe von fehlgeschlagenen Tests (Standardverhalten).

Die Formatierung der Ausgabe ist mit -r hübscher als mit -s.

74voto

Summerfun Punkte 757

Verwenden Sie bei der Durchführung des Tests die -s Option. Alle Druckanweisungen in exampletest.py wird auf der Konsole ausgegeben, wenn der Test ausgeführt wird.

py.test exampletest.py -s

63voto

Cecil Curry Punkte 8830

In einem hochgestufter Kommentar zum akzeptierte Antwort , Joe fragt:

Gibt es eine Möglichkeit, in die Konsole zu drucken UND die Ausgabe erfassen, damit sie im Junit-Bericht erscheint?

Unter UNIX wird dies üblicherweise als Abschlag . Idealerweise wäre der Standard von py.test eher das Testen als das Erfassen. Nicht ideal ist, dass weder py.test noch ein bestehendes py.test-Plugin eines Drittanbieters (... die ich kenne, jedenfalls ) unterstützt Abschläge - obwohl Python trivialerweise Abschläge unterstützt sofort einsatzbereit .

Monkey-Parcheando py.test zu tun alles nicht unterstützt wird, ist nicht trivial. Warum? Weil:

  • Die meisten py.test-Funktionen sind hinter einer privaten _pytest Paket no die zur externen Einfuhr bestimmt sind. Der Versuch, dies zu tun, ohne zu wissen, was man tut, führt in der Regel dazu, dass die öffentliche pytest Paket, das obskure Ausnahmen zur Laufzeit auslöst. Vielen Dank, py.test. Wirklich robuste Architektur haben Sie dort.
  • Auch wenn Sie tun herausfinden, wie man den privaten _pytest API auf sichere Weise zu nutzen, müssen Sie dies tun antes de Leitung der Öffentlichkeit pytest Paket, das von dem externen py.test Befehl. Sie kann nicht dies in einem Plugin zu tun (z. B. in einem Top-Level conftest Modul in Ihrer Testsuite). Bis py.test sich dazu durchringt, Ihr Plugin dynamisch zu importieren, ist jede py.test-Klasse, die Sie einbauen wollten, schon längst instanziiert - und Sie müssen no Zugang zu dieser Instanz haben. Dies bedeutet, dass Sie, wenn Sie wollen, dass Ihr Monkey-Patch sinnvoll angewendet wird, nicht mehr sicher die externe py.test Befehl. Stattdessen müssen Sie die Ausführung dieses Befehls mit einem benutzerdefinierten setuptools verpacken test Befehl (in dieser Reihenfolge):
    1. Affenflicken das Private _pytest API.
    2. Ruft die Öffentlichkeit an pytest.main() Funktion zur Ausführung der py.test Befehl.

Diese Antwort patcht die py.test's -s y --capture=no Optionen, um stderr zu erfassen, aber no stdout. Standardmäßig erfassen diese Optionen weder stderr noch stdout. Das ist natürlich nicht wirklich ein Abschlag. Aber jede große Reise beginnt mit einer mühsamen Vorgeschichte, die jeder in fünf Jahren vergessen hat.

Warum dies tun? Ich werde es Ihnen jetzt sagen. Meine py.test-driven Testsuite enthält langsame funktionale Tests. Die Anzeige des stdout dieser Tests ist hilfreich und beruhigend und verhindert leycec vom Griff nach killall -9 py.test wenn wieder einmal ein langwieriger Funktionstest wochenlang nichts bringt. Die Anzeige der stderr dieser Tests verhindert jedoch, dass py.test bei Testfehlern Ausnahme-Tracebacks ausgibt. Das ist absolut nicht hilfreich. Daher zwingen wir py.test dazu, stderr zu erfassen, aber no stdout.

Bevor wir dazu kommen, geht diese Antwort davon aus, dass Sie bereits ein benutzerdefiniertes setuptools test Befehl, der py.test aufruft. Wenn Sie das nicht tun, lesen Sie die Manuelle Integration Unterabschnitt von py.test's gut geschriebenem Bewährte Praktiken Seite.

Do no installieren pytest-runner ein Setuptools-Plugin eines Drittanbieters, das ein benutzerdefiniertes Setuptools test Befehl, der auch py.test aufruft. Wenn pytest-runner bereits installiert ist, müssen Sie wahrscheinlich dieses pip3-Paket deinstallieren und dann den oben verlinkten manuellen Ansatz anwenden.

Angenommen, Sie haben die Anweisungen in Manuelle Integration wie oben hervorgehoben, sollte Ihre Codebasis nun eine PyTest.run_tests() Methode. Ändern Sie diese Methode so, dass sie ähnlich aussieht:

class PyTest(TestCommand):
             .
             .
             .
    def run_tests(self):
        # Import the public "pytest" package *BEFORE* the private "_pytest"
        # package. While importation order is typically ignorable, imports can
        # technically have side effects. Tragicomically, that is the case here.
        # Importing the public "pytest" package establishes runtime
        # configuration required by submodules of the private "_pytest" package.
        # The former *MUST* always be imported before the latter. Failing to do
        # so raises obtuse exceptions at runtime... which is bad.
        import pytest
        from _pytest.capture import CaptureManager, FDCapture, MultiCapture

        # If the private method to be monkey-patched no longer exists, py.test
        # is either broken or unsupported. In either case, raise an exception.
        if not hasattr(CaptureManager, '_getcapture'):
            from distutils.errors import DistutilsClassError
            raise DistutilsClassError(
                'Class "pytest.capture.CaptureManager" method _getcapture() '
                'not found. The current version of py.test is either '
                'broken (unlikely) or unsupported (likely).'
            )

        # Old method to be monkey-patched.
        _getcapture_old = CaptureManager._getcapture

        # New method applying this monkey-patch. Note the use of:
        #
        # * "out=False", *NOT* capturing stdout.
        # * "err=True", capturing stderr.
        def _getcapture_new(self, method):
            if method == "no":
                return MultiCapture(
                    out=False, err=True, in_=False, Capture=FDCapture)
            else:
                return _getcapture_old(self, method)

        # Replace the old with the new method.
        CaptureManager._getcapture = _getcapture_new

        # Run py.test with all passed arguments.
        errno = pytest.main(self.pytest_args)
        sys.exit(errno)

Um diesen Monkey-Patch zu aktivieren, führen Sie py.test wie folgt aus:

python setup.py test -a "-s"

Stderr aber no stdout wird nun aufgezeichnet. Raffiniert!

Die Erweiterung des obigen Monkey-Patches auf stdout und stderr wird als Übung dem Leser überlassen, der ein Fass voll Freizeit hat.

46voto

meonstackexchange Punkte 559

pytest --capture=tee-sys wurde kürzlich hinzugefügt ( v5.4.0 ). Sie können die Ausgabe auf stdout/err sowohl erfassen als auch sehen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X