Umgang mit fehlgeschlagenen Tests

Beenden nach dem ersten (oder N) Fehlschlag

Um den Testprozess nach dem ersten (N) Fehlschlag zu beenden

pytest -x           # stop after first failure
pytest --maxfail=2  # stop after two failures

Verwendung von pdb — Der Python-Debugger mit pytest

Absturz in pdb bei Fehlern

Python wird mit einem integrierten Python-Debugger namens pdb geliefert. pytest ermöglicht es, über eine Kommandozeilenoption in die pdb-Eingabeaufforderung zu wechseln

pytest --pdb

Dies ruft den Python-Debugger bei jedem Fehlschlag (oder KeyboardInterrupt) auf. Oft möchten Sie dies vielleicht nur beim ersten fehlgeschlagenen Test tun, um eine bestimmte Fehlersituation zu verstehen.

pytest -x --pdb   # drop to PDB on first failure, then end test session
pytest --pdb --maxfail=3  # drop to PDB for first three failures

Beachten Sie, dass bei jedem Fehlschlag die Ausnahmeinformationen in sys.last_value, sys.last_type und sys.last_traceback gespeichert werden. In interaktiver Nutzung ermöglicht dies den Wechsel in das Postmortem-Debugging mit jedem Debugging-Tool. Man kann auch manuell auf die Ausnahmeinformationen zugreifen, zum Beispiel

>>> import sys
>>> sys.last_traceback.tb_lineno
42
>>> sys.last_value
AssertionError('assert result == "ok"',)

Absturz in pdb zu Beginn eines Tests

pytest ermöglicht es, über eine Kommandozeilenoption sofort zu Beginn jedes Tests in die pdb-Eingabeaufforderung zu wechseln

pytest --trace

Dies ruft den Python-Debugger zu Beginn jedes Tests auf.

Setzen von Haltepunkten

Um einen Haltepunkt in Ihrem Code zu setzen, verwenden Sie den nativen Python-Aufruf import pdb;pdb.set_trace() in Ihrem Code, und pytest deaktiviert automatisch die Ausgabeerfassung für diesen Test

  • Die Ausgabenerfassung in anderen Tests wird nicht beeinflusst.

  • Jede vorherige Testausgabe, die bereits erfasst wurde, wird entsprechend verarbeitet.

  • Die Ausgabenerfassung wird nach Beendigung der Debugging-Sitzung (mit dem Befehl continue) wieder aufgenommen.

Verwendung der integrierten Breakpoint-Funktion

Python 3.7 führt eine integrierte Funktion breakpoint() ein. Pytest unterstützt die Verwendung von breakpoint() mit den folgenden Verhaltensweisen

  • Wenn breakpoint() aufgerufen wird und PYTHONBREAKPOINT auf den Standardwert gesetzt ist, verwendet pytest die benutzerdefinierte interne PDB-Trace-Oberfläche anstelle des systemweiten Standard-Pdb.

  • Wenn die Tests abgeschlossen sind, wird standardmäßig wieder die systemweite Pdb-Trace-Oberfläche verwendet.

  • Mit --pdb, das an pytest übergeben wird, wird die benutzerdefinierte interne PDB-Trace-Oberfläche sowohl für breakpoint() als auch für fehlgeschlagene Tests/unbehandelte Ausnahmen verwendet.

  • --pdbcls kann verwendet werden, um eine benutzerdefinierte Debugger-Klasse anzugeben.

Fehlerbehandlungsroutine

Hinzugefügt in Version 5.0.

Das Standardmodul faulthandler kann verwendet werden, um Python-Tracebacks bei einem Segfault oder nach einem Timeout auszugeben.

Das Modul wird automatisch für pytest-Läufe aktiviert, es sei denn, -p no:faulthandler wird auf der Kommandozeile angegeben.

Auch die Konfigurationsoption faulthandler_timeout=X kann verwendet werden, um den Traceback aller Threads auszugeben, wenn ein Test länger als X Sekunden dauert, um abgeschlossen zu werden.

Hinweis

Diese Funktionalität wurde aus dem externen Plugin pytest-faulthandler integriert, mit zwei kleinen Unterschieden

  • Um es zu deaktivieren, verwenden Sie -p no:faulthandler anstelle von --no-faulthandler: Ersteres kann mit jedem Plugin verwendet werden, sodass es eine Option spart.

  • Die Kommandozeilenoption --faulthandler-timeout wurde zur Konfigurationsoption faulthandler_timeout. Sie kann immer noch von der Kommandozeile mit -o faulthandler_timeout=X konfiguriert werden.

Warnung vor nicht abfangbaren Ausnahmen und unbehandelten Thread-Ausnahmen

Hinzugefügt in Version 6.2.

Unbehandelte Ausnahmen sind Ausnahmen, die in einer Situation ausgelöst werden, in der sie nicht an einen Aufrufer weitergegeben werden können. Der häufigste Fall ist eine Ausnahme, die in einer Implementierung von __del__ ausgelöst wird.

Unbehandelte Thread-Ausnahmen sind Ausnahmen, die in einem Thread ausgelöst und nicht behandelt werden, was dazu führt, dass der Thread unsauber beendet wird.

Beide Arten von Ausnahmen gelten normalerweise als Fehler, können aber unbemerkt bleiben, da sie nicht dazu führen, dass das Programm selbst abstürzt. Pytest erkennt diese Bedingungen und gibt eine Warnung aus, die in der Zusammenfassung des Testlaufs sichtbar ist.

Die Plugins werden automatisch für pytest-Läufe aktiviert, es sei denn, die Optionen -p no:unraisableexception (für nicht abfangbare Ausnahmen) und -p no:threadexception (für Thread-Ausnahmen) werden auf der Kommandozeile angegeben.

Die Warnungen können selektiv mit dem Markierer pytest.mark.filterwarnings unterdrückt werden. Die Warnungskategorien sind pytest.PytestUnraisableExceptionWarning und pytest.PytestUnhandledThreadExceptionWarning.