Protokollierung innerhalb von Pytest-Tests

Lesezeit: 9 Minuten

Benutzeravatar von superselector
Superselektor

Ich möchte einige Protokollierungsanweisungen in die Testfunktion einfügen, um einige Zustandsvariablen zu untersuchen.

Ich habe folgenden Codeschnipsel:

import pytest,os
import logging

logging.basicConfig(level=logging.DEBUG)
mylogger = logging.getLogger()

#############################################################################

def setup_module(module):
    ''' Setup for the entire module '''
    mylogger.info('Inside Setup')
    # Do the actual setup stuff here
    pass

def setup_function(func):
    ''' Setup for test functions '''
    if func == test_one:
        mylogger.info(' Hurray !!')

def test_one():
    ''' Test One '''
    mylogger.info('Inside Test 1')
    #assert 0 == 1
    pass

def test_two():
    ''' Test Two '''
    mylogger.info('Inside Test 2')
    pass

if __name__ == '__main__':
    mylogger.info(' About to start the tests ')
    pytest.main(args=[os.path.abspath(__file__)])
    mylogger.info(' Done executing the tests ')

Ich bekomme folgende Ausgabe:

[bmaryada-mbp:/Users/bmaryada/dev/platform/main/proto/tests/tpch $]python minitest.py
INFO:root: About to start the tests 
======================================================== test session starts =========================================================
platform darwin -- Python 2.6.2 -- pytest-2.0.0
collected 2 items 

minitest.py ..

====================================================== 2 passed in 0.01 seconds ======================================================
INFO:root: Done executing the tests 

Beachten Sie, dass nur die Protokollierungsmeldungen von der '__name__ == __main__' Block werden an die Konsole übertragen.

Gibt es eine Möglichkeit zu erzwingen pytest Protokollierung auch von Testmethoden an die Konsole ausgeben?

  • Sie können sich diese Antwort ansehen, die vom Ersteller von py.test gepostet wurde. Er schlägt ein Pytest-Plugin vor, das ein hohes Maß an Vielseitigkeit bietet.

    – chb

    2. Juli 2013 um 9:06 Uhr

Benutzeravatar von hoefling
Höfling

Seit Version 3.3, pytest unterstützt Live-Protokollierung, was bedeutet, dass alle in Tests ausgegebenen Protokolldatensätze sofort auf dem Terminal gedruckt werden. Die Funktion ist unter dokumentiert Live-Protokolle Sektion. Die Live-Protokollierung ist standardmäßig deaktiviert; um es zu aktivieren, setzen log_cli = 1 in dem pyproject.toml1 oder pytest.ini2 Konfig. Die Live-Protokollierung unterstützt die Ausgabe an Terminal und Datei; die relevanten Optionen ermöglichen die Anpassung von Datensätzen:

Terminal:

  • log_cli_level
  • log_cli_format
  • log_cli_date_format

Datei:

  • log_file
  • log_file_level
  • log_file_format
  • log_file_date_format

Wie von Kévin Barré in diesem Kommentar hervorgehoben, Vorrang ini Optionen von der Befehlszeile können ausgeführt werden über:

-o OVERRIDE_INI, --override-ini=OVERRIDE_INI

Ini-Option mit “option=value”-Stil überschreiben, zB
-o xfail_strict=True -o cache_dir=cache

Also anstatt zu deklarieren log_cli in pytest.inirufen Sie einfach an:

$ pytest -o log_cli=true ...

Beispiele

Einfache Testdatei zur Demonstration:

# test_spam.py

import logging

LOGGER = logging.getLogger(__name__)


def test_eggs():
    LOGGER.info('eggs info')
    LOGGER.warning('eggs warning')
    LOGGER.error('eggs error')
    LOGGER.critical('eggs critical')
    assert True

Wie Sie sehen können, ist keine zusätzliche Konfiguration erforderlich; pytest richtet den Logger automatisch ein, basierend auf den in angegebenen Optionen pytest.ini oder von der Befehlszeile übergeben.

Live-Protokollierung zum Terminal, INFO Ebene, schicke Ausgabe

Konfiguration ein pyproject.toml:

[tool.pytest.ini_options]
log_cli = true
log_cli_level = "INFO"
log_cli_format = "%(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)"
log_cli_date_format = "%Y-%m-%d %H:%M:%S"

Die identische Konfiguration in Legacy pytest.ini:

[pytest]
log_cli = 1
log_cli_level = INFO
log_cli_format = %(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)
log_cli_date_format=%Y-%m-%d %H:%M:%S

Ausführen des Tests:

$ pytest test_spam.py
=============================== test session starts ================================
platform darwin -- Python 3.6.4, pytest-3.7.0, py-1.5.3, pluggy-0.7.1 -- /Users/hoefling/.virtualenvs/stackoverflow/bin/python3.6
cachedir: .pytest_cache
rootdir: /Users/hoefling/projects/private/stackoverflow/so-4673373, inifile: pytest.ini
collected 1 item

test_spam.py::test_eggs
---------------------------------- live log call -----------------------------------
2018-08-01 14:33:20 [    INFO] eggs info (test_spam.py:7)
2018-08-01 14:33:20 [ WARNING] eggs warning (test_spam.py:8)
2018-08-01 14:33:20 [   ERROR] eggs error (test_spam.py:9)
2018-08-01 14:33:20 [CRITICAL] eggs critical (test_spam.py:10)
PASSED                                                                        [100%]

============================= 1 passed in 0.01 seconds =============================

Live-Protokollierung auf Terminal und Datei, nur Nachricht & CRITICAL Pegel im Terminal, schicker Ausgang in pytest.log Datei

Konfiguration ein pyproject.toml:

[tool.pytest.ini_options]
log_cli = true
log_cli_level = "CRITICAL"
log_cli_format = "%(message)s"

log_file = "pytest.log"
log_file_level = "DEBUG"
log_file_format = "%(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)"
log_file_date_format = "%Y-%m-%d %H:%M:%S"

Die identische Konfiguration in Legacy pytest.ini:

[pytest]
log_cli = 1
log_cli_level = CRITICAL
log_cli_format = %(message)s

log_file = pytest.log
log_file_level = DEBUG
log_file_format = %(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)
log_file_date_format=%Y-%m-%d %H:%M:%S

Testlauf:

$ pytest test_spam.py
=============================== test session starts ================================
platform darwin -- Python 3.6.4, pytest-3.7.0, py-1.5.3, pluggy-0.7.1 -- /Users/hoefling/.virtualenvs/stackoverflow/bin/python3.6
cachedir: .pytest_cache
rootdir: /Users/hoefling/projects/private/stackoverflow/so-4673373, inifile: pytest.ini
collected 1 item

test_spam.py::test_eggs
---------------------------------- live log call -----------------------------------
eggs critical
PASSED                                                                        [100%]

============================= 1 passed in 0.01 seconds =============================

$ cat pytest.log
2018-08-01 14:38:09 [    INFO] eggs info (test_spam.py:7)
2018-08-01 14:38:09 [ WARNING] eggs warning (test_spam.py:8)
2018-08-01 14:38:09 [   ERROR] eggs error (test_spam.py:9)
2018-08-01 14:38:09 [CRITICAL] eggs critical (test_spam.py:10)

1 pyproject.toml wird seit Version 6.0 unterstützt und ist meiner Meinung nach die beste Option. Sehen PEP 518 für die Spezifikationen.

2 Obwohl Sie auch konfigurieren können pytest in setup.cfg unter dem [tool:pytest] Seien Sie nicht versucht, dies zu tun, wenn Sie ein benutzerdefiniertes Live-Protokollierungsformat bereitstellen möchten. Andere Tools lesen setup.cfg könnte Dinge behandeln wie %(message)s als String-Interpolation und scheitern. Die beste Wahl ist die Verwendung pyproject.toml wie auch immer, aber wenn Sie gezwungen sind, das alte ini-Format zu verwenden, bleiben Sie dabei pytest.ini Fehler zu vermeiden.

  • Über die Notiz, dass log_cli muss drin sein pytest.inies scheint, dass Sie verwenden können -o Option zum Überschreiben des Werts von der Befehlszeile. pytest -o log_cli=true --log-cli-level=DEBUG funktioniert bei mir.

    – Kevin Barre

    31. August 2018 um 9:46 Uhr

  • @KévinBarré sehr schöner Kommentar und allgemein ein sehr nützlicher Hinweis, danke! Antwort aktualisiert.

    – Hacken

    2. September 2018 um 16:12 Uhr

  • Dies ist definitiv die richtige Antwort, wenn Sie die Protokollierung verwenden. Obwohl ich gerne Protokolle innerhalb der Tests und Protokolle innerhalb der zu testendes System die gesondert betrachtet werden sollten.

    – CMCDragonkai

    21. Februar 2019 um 5:00 Uhr

  • @OfekAgmon, wenn Sie speichern möchten pytest Ausgabe können Sie die verwenden --result-log Argument (obwohl beachten Sie, dass es veraltet ist, Hier sind die Alternativen). Sie können nicht speichern pytest Ausgabe und Live-Logging-Ausgabe jedoch in derselben Datei.

    – Hacken

    24. März 2020 um 17:57 Uhr

  • @andrea ja, du kannst die Optionen programmgesteuert ändern; Ich kann keine Ausschnitte in den Kommentaren posten, also schau dir die Antwort an, die ich zu einem ähnlichen Problem gegeben habe (Link). Die Anpassungsmöglichkeit ist log_file Anstatt von htmlpath; Sollten Sie damit Schwierigkeiten haben, schreiben Sie eine neue Frage und pingen Sie mich hier erneut an, ich werde ein funktionierendes Beispiel hinzufügen.

    – Hacken

    4. Februar 2021 um 11:16 Uhr


Benutzeravatar von TryPyPy
TryPyPy

Funktioniert für mich, hier ist die Ausgabe, die ich bekomme: [snip -> example was incorrect]

Edit: Es scheint, dass Sie das passieren müssen -s Option für py.test, damit stdout nicht erfasst wird. Hier (py.test nicht installiert) war es ausreichend zu verwenden python pytest.py -s pyt.py.

Für Ihren Code brauchen Sie nur zu bestehen -s in args zu main:

 pytest.main(args=['-s', os.path.abspath(__file__)])

Siehe die py.test-Dokumentation auf Ausgabe erfassen.

  • Es tut uns leid. Ich habe den Code in Eile eingefügt. Bitte entfernen Sie „assert 0 == 1“ aus der Funktion „test_one“, um das „Problem“ zu bemerken. Nur wenn ein Fehler auftritt (den ich durch eine falsche Behauptung erzwungen habe), scheint py.test die Protokollinformationen zu drucken.

    – Superselektor

    12. Januar 2011 um 21:23 Uhr

  • Kein Problem, ich habe herausgefunden, wie man das Problem in der Befehlszeile beheben kann, und nach einem programmgesteuerten Weg gesucht.

    – TryPyPy

    12. Januar 2011 um 21:36 Uhr

  • Sie könnten die Protokollausgabe auch in eine Datei umleiten, anstatt auf die implizite Standardeinstellung stderr.

    – hpk42

    12. Januar 2011 um 21:59 Uhr

  • @superselector hpk42 ist der Typ von py.test, hör zu. IIUC, in Ihrem Code wäre es logging.basicConfig(filename="somelog.txt", level=logging.DEBUG).

    – TryPyPy

    12. Januar 2011 um 22:24 Uhr

Benutzeravatar von Fabrice Jammes
Fabrice Jammes

Verwenden pytest --log-cli-level=DEBUG funktioniert gut mit pytest (getestet von 6.2.2 bis 7.1.1)

Verwenden pytest --log-cli-level=DEBUG --capture=tee-sys wird auch gedruckt stdtout.

Verwenden Sie send, um die Loggerausgabe einzuschalten --capture=no Flag von der Kommandozeile.
--capture=no zeigt alle Ausgaben von Logger- und Druckanweisungen. Wenn Sie Ausgaben von Loggern erfassen und keine Anweisungen drucken möchten, verwenden Sie --capture=sys

pytest --capture=no tests/system/test_backoffice.py

Hier Weitere Informationen zu “Capturing of the stdout/stderr output”

Standardmäßig ist die Logger-Ausgangsstufe „WARNING“. Um die Log-Ausgangsstufe zu ändern, verwenden Sie --log-cli-level Flagge.

pytest --capture=no --log-cli-level=DEBUG tests/system/test_backoffice.py

Wenn Sie Protokolle mit der Befehlszeile filtern möchten, können Sie weitergeben –log-cli-level (pytest –log-cli-level) und Protokolle werden ab der von Ihnen angegebenen Ebene und darüber angezeigt

(z.B pytest –log-cli-level=INFO zeigt INFO und darüber Protokolle (WARNUNG, ERROR, CRITICAL))

Beachten Sie Folgendes: default –log-cli-level ist eine WARNUNG, wenn Sie sie nicht angeben (https://docs.pytest.org/en/6.2.x/logging.html)

Aber wenn Sie nicht verwenden möchten –log-cli-level Jedes Mal, wenn Sie pytest verwenden, können Sie festlegen Log-Ebene
in Ihrer pytest-Konfigurationsdatei (pytest.ini/tox.ini/setup.cfg)

z.B

stellen log-level=INFO in pytest.ini (oder anderen Konfigurationsdateien, die ich erwähnt habe)

wenn du rennst pytestsehen Sie nur INFO und höhere Protokolle

Wenn du benutzt vscodeverwenden Sie die folgende Konfiguration, vorausgesetzt, Sie haben sie installiert
Offizielles Python-Plugin (ms-python.python) für Ihr Python-Projekt.

./.vscode/setting.json unter deinem proj

{
  ....
  "python.testing.pytestArgs": ["-s", "src"], //here before discover-path src
  "python.testing.unittestEnabled": false,
  "python.testing.nosetestsEnabled": false,
  "python.testing.pytestEnabled": true,
  ...
}

PS Einige Plugins funktionieren daran, einschließlich, aber nicht beschränkt auf:

  • Python-Test-Explorer für Visual Studio Code (littlefoxteam.vscode-python-test-adapter)
  • Test-Explorer für Visual Studio Code(hbenl.vscode-test-explorer)

Benutzeravatar von Flinck Clissan
Flink Clissan

Du kannst lesen:
Dokumentation zum Einloggen in pytest

Hier ist ein einfaches Beispiel, das Sie ausführen und ein Protokoll von der foo-Funktion abrufen können.

#./test_main.py
from main import foo
import logging

def test_foo(caplog):
    caplog.set_level(logging.INFO)

    logging.getLogger().info('Log inside a test function!')

    assert foo(1, 2) == 5
    /* your test here*/
# ./main.py
import logging

def foo(a, b):
    logging.getLogger().info('a: ' + str(a))
    logging.getLogger().info('b: ' + str(b))
    return a + b

Jetzt können Sie pytest ausführen und Protokollinformationen von der Funktion abrufen, die Sie benötigen.
Wenn Sie keine Fehler haben, werden Protokolle ausgelassen.

1436030cookie-checkProtokollierung innerhalb von Pytest-Tests

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy