Doctests ausführen¶
Standardmäßig werden alle Dateien, die dem Muster test*.txt entsprechen, über das Standardmodul doctest von Python ausgeführt. Sie können das Muster ändern, indem Sie
pytest --doctest-glob="*.rst"
auf der Kommandozeile angeben. --doctest-glob kann mehrmals in der Kommandozeile angegeben werden.
Wenn Sie dann eine Textdatei wie diese haben
# content of test_example.txt
hello this is a doctest
>>> x = 3
>>> x
3
dann können Sie pytest einfach direkt aufrufen
$ pytest
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y
rootdir: /home/sweet/project
collected 1 item
test_example.txt . [100%]
============================ 1 passed in 0.12s =============================
Standardmäßig sammelt pytest test*.txt Dateien auf der Suche nach Doctest-Direktiven, aber Sie können zusätzliche Globs über die Option --doctest-glob (mehrfach erlaubt) übergeben.
Zusätzlich zu Textdateien können Sie Doctests auch direkt aus Docstrings Ihrer Klassen und Funktionen ausführen, einschließlich aus Testmodulen.
# content of mymodule.py
def something():
"""a doctest in a docstring
>>> something()
42
"""
return 42
$ pytest --doctest-modules
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y
rootdir: /home/sweet/project
collected 2 items
mymodule.py . [ 50%]
test_example.txt . [100%]
============================ 2 passed in 0.12s =============================
Sie können diese Änderungen in Ihrem Projekt dauerhaft machen, indem Sie sie in eine Konfigurationsdatei wie diese eintragen
# content of pytest.toml
[pytest]
addopts = ["--doctest-modules"]
Encoding¶
Das Standard-Encoding ist UTF-8, aber Sie können das Encoding, das für diese Doctest-Dateien verwendet wird, mit der Konfigurationsoption doctest_encoding festlegen.
[pytest]
doctest_encoding = "latin1"
[pytest]
doctest_encoding = latin1
Verwendung von 'doctest'-Optionen¶
Das Standardmodul doctest von Python bietet einige Optionen zur Konfiguration der Strenge von Doctests. In pytest können Sie diese Flags über die Konfigurationsdatei aktivieren.
Um beispielsweise nachgestellte Leerzeichen und lange Exception-Stacktraces zu ignorieren, können Sie einfach Folgendes schreiben
[pytest]
doctest_optionflags = ["NORMALIZE_WHITESPACE", "IGNORE_EXCEPTION_DETAIL"]
[pytest]
doctest_optionflags = NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL
Alternativ können Optionen durch einen Inline-Kommentar im Doctest selbst aktiviert werden.
>>> something_that_raises() # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
ValueError: ...
pytest führt auch neue Optionen ein
ALLOW_UNICODE: Wenn aktiviert, wird das Präfixuvon Unicode-Strings in erwarteten Doctest-Ausgaben entfernt. Dies ermöglicht die unveränderte Ausführung von Doctests in Python 2 und Python 3.ALLOW_BYTES: Ähnlich wird das Präfixbvon Byte-Strings in erwarteten Doctest-Ausgaben entfernt.NUMBER: Wenn aktiviert, müssen Gleitkommazahlen nur bis zur von Ihnen im erwarteten Doctest-Output angegebenen Genauigkeit übereinstimmen. Die Zahlen werden mitpytest.approx()mit einer relativen Toleranz verglichen, die der Genauigkeit entspricht. Zum Beispiel müsste die folgende Ausgabe nur bis zu 2 Dezimalstellen übereinstimmen, wenn3.14mitpytest.approx(math.pi, rel=10**-2)verglichen wird.>>> math.pi 3.14
Wenn Sie
3.1416geschrieben hätten, müsste die tatsächliche Ausgabe ungefähr auf 4 Dezimalstellen übereinstimmen; und so weiter.Dies vermeidet falsch-positive Ergebnisse aufgrund begrenzter Gleitkommapräzision, wie hier:
Expected: 0.233 Got: 0.23300000000000001
NUMBERunterstützt auch Listen von Gleitkommazahlen – tatsächlich gleicht es Gleitkommazahlen ab, die irgendwo in der Ausgabe vorkommen, selbst innerhalb eines Strings! Das bedeutet, dass es möglicherweise nicht ratsam ist, dies global indoctest_optionflagsin Ihrer Konfigurationsdatei zu aktivieren.Hinzugefügt in Version 5.1.
Fortfahren bei Fehlern¶
Standardmäßig würde pytest nur den ersten Fehler für einen gegebenen Doctest melden. Wenn Sie den Test auch bei Fehlern fortsetzen möchten, tun Sie Folgendes:
pytest --doctest-modules --doctest-continue-on-failure
Ausgabeformat¶
Sie können das Diff-Ausgabeformat bei Fehlern für Ihre Doctests ändern, indem Sie eine der Standardformatoptionen des Doctest-Moduls verwenden (siehe doctest.REPORT_UDIFF, doctest.REPORT_CDIFF, doctest.REPORT_NDIFF, doctest.REPORT_ONLY_FIRST_FAILURE).
pytest --doctest-modules --doctest-report none
pytest --doctest-modules --doctest-report udiff
pytest --doctest-modules --doctest-report cdiff
pytest --doctest-modules --doctest-report ndiff
pytest --doctest-modules --doctest-report only_first_failure
pytest-spezifische Funktionen¶
Einige Funktionen werden bereitgestellt, um das Schreiben von Doctests zu erleichtern oder eine bessere Integration mit Ihrer bestehenden Testsuite zu ermöglichen. Beachten Sie jedoch, dass Sie durch die Verwendung dieser Funktionen Ihre Doctests mit dem Standardmodul doctests inkompatibel machen.
Verwendung von Fixtures¶
Es ist möglich, Fixtures mit dem getfixture-Helfer zu verwenden.
# content of example.rst
>>> tmp = getfixture('tmp_path')
>>> ...
>>>
Beachten Sie, dass das Fixture an einem Ort definiert sein muss, der für pytest sichtbar ist, z. B. in einer conftest.py-Datei oder einem Plugin; normale Python-Dateien, die Docstrings enthalten, werden normalerweise nicht nach Fixtures durchsucht, es sei denn, sie werden explizit über python_files konfiguriert.
Außerdem werden die Markierung usefixtures und als autouse markierte Fixtures beim Ausführen von Text-Doctest-Dateien unterstützt.
'doctest_namespace'-Fixture¶
Das doctest_namespace-Fixture kann verwendet werden, um Elemente in den Namespace einzufügen, in dem Ihre Doctests ausgeführt werden. Es ist dazu gedacht, innerhalb Ihrer eigenen Fixtures verwendet zu werden, um die Tests, die sie verwenden, mit Kontext zu versorgen.
doctest_namespace ist ein Standard-Objekt vom Typ dict, in das Sie die Objekte einfügen, die im Doctest-Namespace erscheinen sollen.
# content of conftest.py
import pytest
import numpy
@pytest.fixture(autouse=True)
def add_np(doctest_namespace):
doctest_namespace["np"] = numpy
was dann direkt in Ihren Doctests verwendet werden kann
# content of numpy.py
def arange():
"""
>>> a = np.arange(10)
>>> len(a)
10
"""
Beachten Sie, dass die Fixtures, wie die normale conftest.py, im Verzeichnisbaum gefunden werden, in dem sich conftest befindet. Das bedeutet, wenn Sie Ihren Doctest mit Ihrem Quellcode zusammenlegen, muss die entsprechende conftest.py im selben Verzeichnisbaum liegen. Fixtures werden nicht in einem Geschwister-Verzeichnisbaum gefunden!
Tests überspringen¶
Aus den gleichen Gründen, aus denen man normale Tests überspringen möchte, ist es auch möglich, Tests innerhalb von Doctests zu überspringen.
Um eine einzelne Prüfung innerhalb eines Doctests zu überspringen, können Sie die Standarddirektive doctest.SKIP verwenden.
def test_random(y):
"""
>>> random.random() # doctest: +SKIP
0.156231223
>>> 1 + 1
2
"""
Dies überspringt die erste Prüfung, aber nicht die zweite.
pytest erlaubt auch die Verwendung der Standard-pytest-Funktionen pytest.skip() und pytest.xfail() innerhalb von Doctests, was nützlich sein kann, da Sie dann Tests basierend auf externen Bedingungen überspringen/xfailen können.
>>> import sys, pytest
>>> if sys.platform.startswith('win'):
... pytest.skip('this doctest does not work on Windows')
...
>>> import fcntl
>>> ...
Die Verwendung dieser Funktionen wird jedoch nicht empfohlen, da sie die Lesbarkeit des Docstrings verringert.
Hinweis
pytest.skip() und pytest.xfail() verhalten sich unterschiedlich, je nachdem, ob die Doctests in einer Python-Datei (in Docstrings) oder in einer Textdatei mit Doctests, die mit Text durchsetzt sind, enthalten sind.
Python-Module (Docstrings): Die Funktionen wirken nur in diesem speziellen Docstring, während andere Docstrings im selben Modul normal ausgeführt werden.
Textdateien: Die Funktionen überspringen/xfailen die Prüfungen für den Rest der gesamten Datei.
Alternativen¶
Während die integrierte pytest-Unterstützung eine gute Funktionalität für die Verwendung von Doctests bietet, könnten Sie, wenn Sie sie ausgiebig nutzen, an folgenden externen Paketen interessiert sein, die viele weitere Funktionen hinzufügen und pytest-Integration beinhalten:
pytest-doctestplus: Bietet erweiterte Doctest-Unterstützung und ermöglicht das Testen von reStructuredText (".rst") Dateien.
Sybil: Bietet eine Möglichkeit, Beispiele in Ihrer Dokumentation zu testen, indem sie aus dem Quelldokumentation geparst und die geparsten Beispiele als Teil Ihres normalen Testlaufs ausgewertet werden.