Protokollierung verwalten¶
pytest erfasst Protokollnachrichten der Stufe WARNING oder höher automatisch und zeigt sie in einem eigenen Abschnitt für jeden fehlgeschlagenen Test an, ebenso wie erfasste stdout und stderr.
Ausführung ohne Optionen
pytest
Zeigt fehlgeschlagene Tests wie folgt an
----------------------- Captured stdlog call ----------------------
test_reporting.py 26 WARNING text going to logger
----------------------- Captured stdout call ----------------------
text going to stdout
----------------------- Captured stderr call ----------------------
text going to stderr
==================== 2 failed in 0.02 seconds =====================
Standardmäßig zeigt jede erfasste Protokollnachricht das Modul, die Zeilennummer, die Protokollstufe und die Nachricht an.
Wenn gewünscht, können das Protokoll- und Datumsformat auf alles gesetzt werden, was das Protokollierungsmodul unterstützt, indem spezifische Formatierungsoptionen übergeben werden
pytest --log-format="%(asctime)s %(levelname)s %(message)s" \
--log-date-format="%Y-%m-%d %H:%M:%S"
Zeigt fehlgeschlagene Tests wie folgt an
----------------------- Captured stdlog call ----------------------
2010-04-10 14:48:44 WARNING text going to logger
----------------------- Captured stdout call ----------------------
text going to stdout
----------------------- Captured stderr call ----------------------
text going to stderr
==================== 2 failed in 0.02 seconds =====================
Diese Optionen können auch über eine Konfigurationsdatei angepasst werden
[pytest]
log_format = "%(asctime)s %(levelname)s %(message)s"
log_date_format = "%Y-%m-%d %H:%M:%S"
[pytest]
log_format = %(asctime)s %(levelname)s %(message)s
log_date_format = %Y-%m-%d %H:%M:%S
Spezifische Logger können über --log-disable={logger_name} deaktiviert werden. Dieses Argument kann mehrmals übergeben werden
pytest --log-disable=main --log-disable=testing
Darüber hinaus ist es möglich, die Berichterstattung über erfasste Inhalte (stdout, stderr und Protokolle) bei fehlgeschlagenen Tests vollständig zu deaktivieren mit
pytest --show-capture=no
caplog-Fixture¶
Innerhalb von Tests ist es möglich, die Protokollstufe für die erfassten Protokollnachrichten zu ändern. Dies wird von der caplog-Fixture unterstützt
def test_foo(caplog):
caplog.set_level(logging.INFO)
Standardmäßig wird die Stufe für den Root-Logger gesetzt, aber zur Bequemlichkeit ist es auch möglich, die Protokollstufe eines beliebigen Loggers zu setzen
def test_foo(caplog):
caplog.set_level(logging.CRITICAL, logger="root.baz")
Die gesetzten Protokollstufen werden am Ende des Tests automatisch wiederhergestellt.
Es ist auch möglich, einen Kontextmanager zu verwenden, um die Protokollstufe innerhalb eines with-Blocks vorübergehend zu ändern
def test_bar(caplog):
with caplog.at_level(logging.INFO):
pass
Auch hier wird standardmäßig die Stufe des Root-Loggers beeinflusst, aber die Stufe eines beliebigen Loggers kann stattdessen mit geändert werden
def test_bar(caplog):
with caplog.at_level(logging.CRITICAL, logger="root.baz"):
pass
Schließlich sind alle während der Testausführung an den Logger gesendeten Protokolle auf der Fixture in Form von sowohl logging.LogRecord-Instanzen als auch des endgültigen Protokolltexts verfügbar. Dies ist nützlich, wenn Sie die Inhalte einer Nachricht überprüfen möchten
def test_baz(caplog):
func_under_test()
for record in caplog.records:
assert record.levelname != "CRITICAL"
assert "wally" not in caplog.text
Für alle verfügbaren Attribute der Protokolldatensätze siehe die Klasse logging.LogRecord.
Sie können auch auf record_tuples zurückgreifen, wenn Sie nur sicherstellen möchten, dass bestimmte Nachrichten unter einem bestimmten Loggernamen mit einer bestimmten Schwere und Nachricht protokolliert wurden
def test_foo(caplog):
logging.getLogger().info("boo %s", "arg")
assert caplog.record_tuples == [("root", logging.INFO, "boo arg")]
Sie können caplog.clear() aufrufen, um die erfassten Protokolldatensätze in einem Test zurückzusetzen
def test_something_with_clearing_records(caplog):
some_method_that_creates_log_records()
caplog.clear()
your_test_method()
assert ["Foo"] == [rec.message for rec in caplog.records]
Das Attribut caplog.records enthält Datensätze nur aus der aktuellen Phase. Innerhalb der setup-Phase enthält es also nur Setup-Protokolle, ebenso wie die Phasen call und teardown.
Um auf Protokolle aus anderen Phasen zuzugreifen, verwenden Sie die Methode caplog.get_records(when). Wenn Sie zum Beispiel sicherstellen möchten, dass Tests, die eine bestimmte Fixture verwenden, niemals Warnungen protokollieren, können Sie die Datensätze für die Phasen setup und call während des Teardown wie folgt überprüfen
@pytest.fixture
def window(caplog):
window = create_window()
yield window
for when in ("setup", "call"):
messages = [
x.message for x in caplog.get_records(when) if x.levelno == logging.WARNING
]
if messages:
pytest.fail(f"warning messages encountered during testing: {messages}")
Die vollständige API ist unter pytest.LogCaptureFixture verfügbar.
Warnung
Die caplog-Fixture fügt dem Root-Logger einen Handler hinzu, um Protokolle zu erfassen. Wenn der Root-Logger während eines Tests geändert wird, z. B. mit logging.config.dictConfig, kann dieser Handler entfernt werden und es werden keine Protokolle erfasst. Um dies zu vermeiden, stellen Sie sicher, dass jede Root-Logger-Konfiguration nur vorhandene Handler ergänzt.
Live-Protokolle¶
Durch Setzen der Konfigurationsoption log_cli auf true gibt pytest Protokollierungseinträge aus, sobald sie emittiert werden, direkt auf die Konsole.
Sie können die Protokollierungsstufe festlegen, für die Protokollierungseinträge mit gleicher oder höherer Stufe auf der Konsole ausgegeben werden, indem Sie --log-cli-level übergeben. Diese Einstellung akzeptiert die Namen der Protokollierungsstufen oder numerische Werte, wie in der Dokumentation von logging zu sehen.
Zusätzlich können Sie auch --log-cli-format und --log-cli-date-format angeben, die --log-format und --log-date-format spiegeln und standardmäßig diese übernehmen, wenn sie nicht angegeben sind, aber nur auf den Konsolen-Protokoll-Handler angewendet werden.
Alle CLI-Protokolloptionen können auch in der Konfigurationsdatei gesetzt werden. Die Optionsnamen sind
Wenn Sie die gesamten Test-Suite-Protokollaufrufe in eine Datei schreiben müssen, können Sie --log-file=/pfad/zur/protokoll/datei übergeben. Diese Protokolldatei wird standardmäßig im Schreibmodus geöffnet, d. h. sie wird bei jeder Testlauf-Sitzung überschrieben. Wenn die Datei stattdessen im Anhänge-Modus geöffnet werden soll, können Sie --log-file-mode=a übergeben. Beachten Sie, dass relative Pfade für den Speicherort der Protokolldatei, sei es auf der CLI oder in einer Konfigurationsdatei deklariert, immer relativ zum aktuellen Arbeitsverzeichnis aufgelöst werden.
Sie können auch die Protokollierungsstufe für die Protokolldatei festlegen, indem Sie --log-file-level übergeben. Diese Einstellung akzeptiert die Namen der Protokollierungsstufen oder numerische Werte, wie in der Dokumentation von logging zu sehen.
Zusätzlich können Sie auch --log-file-format und --log-file-date-format angeben, die gleich --log-format und --log-date-format sind, aber auf den Protokoll-Handler für die Protokolldatei angewendet werden.
Alle Protokolldatei-Optionen können auch in der Konfigurationsdatei gesetzt werden. Die Optionsnamen sind
Sie können set_log_path() aufrufen, um den Pfad der Protokolldatei dynamisch anzupassen. Diese Funktionalität gilt als experimentell. Beachten Sie, dass set_log_path() die Option log_file_mode berücksichtigt.
Farben anpassen¶
Protokollstufen werden farblich hervorgehoben, wenn eine farbige Terminalausgabe aktiviert ist. Das Ändern von Standardfarben oder das Hinzufügen von Farben zu benutzerdefinierten Protokollstufen wird über add_color_level() unterstützt. Beispiel
@pytest.hookimpl(trylast=True)
def pytest_configure(config):
logging_plugin = config.pluginmanager.get_plugin("logging-plugin")
# Change color on existing log level
logging_plugin.log_cli_handler.formatter.add_color_level(logging.INFO, "cyan")
# Add color to a custom log level (a custom log level `SPAM` is already set up)
logging_plugin.log_cli_handler.formatter.add_color_level(logging.SPAM, "blue")
Warnung
Dieses Feature und seine API gelten als experimentell und können sich zwischen den Versionen ohne vorherige Ankündigung ändern.
Versionshinweise¶
Diese Funktion wurde als Drop-in-Ersatz für das Plugin pytest-catchlog eingeführt und sie widersprechen sich. Die Abwärtskompatibilitäts-API mit pytest-capturelog wurde fallen gelassen, als diese Funktion eingeführt wurde. Wenn Sie aus diesem Grund pytest-catchlog noch benötigen, können Sie die interne Funktion deaktivieren, indem Sie Ihrer Konfigurationsdatei Folgendes hinzufügen
[pytest]
addopts = ["-p", "no:logging"]
[pytest]
addopts = -p no:logging
Inkompatible Änderungen in pytest 3.4¶
Diese Funktion wurde in 3.3 eingeführt und einige inkompatible Änderungen wurden in 3.4 nach Feedback aus der Community vorgenommen
Protokollstufen werden nicht mehr geändert, es sei denn, sie werden explizit durch die Konfiguration
log_leveloder die Befehlszeilenoptionen--log-levelangefordert. Dies ermöglicht es Benutzern, Logger-Objekte selbst zu konfigurieren. Das Setzen vonlog_levelsetzt die Stufe, die global erfasst wird. Wenn ein bestimmter Test eine niedrigere Stufe als diese benötigt, verwenden Sie die Funktionalitätcaplog.set_level(), andernfalls wird dieser Test wahrscheinlich fehlschlagen.Live-Protokolle sind jetzt standardmäßig deaktiviert und können durch Setzen der Konfigurationsoption
log_cliauftrueaktiviert werden. Wenn aktiviert, wird die Ausführlichkeit erhöht, so dass Protokolle für jeden Test sichtbar sind.Live-Protokolle werden jetzt an
sys.stdoutgesendet und erfordern nicht mehr die Befehlszeilenoption-s, um zu funktionieren.
Wenn Sie das Protokollierungsverhalten von Version 3.3 teilweise wiederherstellen möchten, können Sie diese Optionen zu Ihrer Konfigurationsdatei hinzufügen
[pytest]
log_cli = true
log_level = "NOTSET"
[pytest]
log_cli = true
log_level = NOTSET
Weitere Details zur Diskussion, die zu diesen Änderungen geführt hat, finden Sie unter #3013.