Konfiguration¶
Mit Konfigurationsdateien könnt ihr den Ablauf von pytest beeinflussen. Wenn ihr
immer wieder bestimmte Optionen in euren Tests verwendet, wie --verbose
oder --strict-markers
, könnt ihr diese in einer Konfigurationsdatei
ablegen und müsst sie nicht immer wieder eingeben. Zusätzlich zu den
Konfigurationsdateien gibt es eine Handvoll anderer Dateien, die bei der
Verwendung von pytest nützlich sind, um die Arbeit beim Schreiben und Ausführen
von Tests zu erleichtern:
pytest.ini
Dies ist die wichtigste Konfigurationsdatei von pytest, mit der ihr das Standardverhalten von pytest ändern könnt. Sie legt auch das Stammverzeichnis von pytest fest, oder
rootdir
.conftest.py
Diese Datei enthält Test-Fixtures und Hook-Funktionen. Sie kann in
rootdir
oder in einem beliebigen Unterverzeichnis existieren.__init__.py
Wenn diese Datei in Test-Unterverzeichnissen abgelegt wird, ermöglicht sie die Verwendung identischer Testdateinamen in mehreren Testverzeichnissen.
Wenn ihr bereits eine tox.ini
, pyproject.toml
oder
setup.cfg
in eurem Projekt habt, können sie an die Stelle der
pytest.ini
-Datei treten: tox.ini
wird von tox
verwendet, pyproject.toml
und setup.cfg
werden für die
Paketierung von Python-Projekten verwendet und können zum Speichern von
Einstellungen für verschiedene Werkzeuge, einschließlich pytest, verwendet
werden.
Ihr solltet eine Konfigurationsdatei haben, entweder pytest.ini
, oder
einem pytest
-Abschnitt in tox.ini
, pyproject.toml
oder in
setup.cfg
.
Sie Konfigurationsdatei legt das oberste Verzeichnis fest, von dem aus
pytest
gestartet wird.
Schauen wir uns einige dieser Dateien im Zusammenhang mit einer Projektverzeichnisstruktur an:
items
├── …
├── pytest.ini
├── src
│ └── …
└── tests
├── __init__.py
├── conftest.py
└── test_….py
Im Falle des items
-Projekts, das wir bisher zum Testen verwendet haben, gibt
es auf der obersten Ebene eine pytest.ini
-Datei und ein Verzeichnis
tests
. Wir werden uns auf diese Struktur beziehen, wenn wir im weiteren
Verlauf dieses Abschnitts über die verschiedenen Dateien sprechen.
Speichern von Einstellungen und Optionen in pytest.ini
¶
[pytest]
addopts =
--strict-markers
--strict-config
-ra
testpaths = tests
markers =
smoke: Small subset of all tests
exception: Only run expected exceptions
[pytest]
kennzeichnet den Beginn des pytest-Abschnitts. Danach folgen die
einzelnen Einstellungen. Bei Konfigurationseinstellungen, die
mehr als einen Wert zulassen, können die Werte entweder in eine oder in mehrere
Zeilen geschrieben werden in der Form EINSTELLUNG = WERT1 WERT2
.
Bei markers
hingegen ist nur ein Marker pro Zeile erlaubt.
Dieses Beispiel ist eine einfache pytest.ini
-Datei, die ich so, oder so
ähnlich in fast allen meinen Projekten verwende. Gehen wir kurz die einzelnen
Zeilen durch:
addopts =
erlaubt die Angabe der pytest-Optionen, die wir immer in diesem Projekt ausführen wollen.
--strict-markers
weist pytest an, bei jedem nicht registrierten Marker, der im Testcode auftaucht, einen Fehler statt einer Warnung auszugeben. Hierdurch können wir Tippfehler bei Marker-Namen vermeiden.
--strict-config
weist pytest an, wenn beim Parsen von Konfigurationsdateien Schwierigkeiten auftauchen, nicht nur eine Warnung sondern einen Fehler auszugeben. Damit vermeiden wir, dass Tippfehler in der Konfigurationsdatei unbemerkt bleiben.
-ra
weist pytest an, am Ende eines Testlaufs nicht nur zusätzliche Informationen zu Failures und Errors anzuzeigen sondern auch eine Testzusammenfassung.
-r
zeigt zusätzliche Informationen zur Testzusammenfassung an.
a
zeigt alle außer den bestanden Tests an. Dies fügt den Failures und Errors die Informationen
skipped
,xfailed
oderxpassed
hinzu.
testpaths = tests
teilt pytest mit, wo es nach Tests suchen soll, wenn ihr auf der Kommandozeile keinen Datei- oder Verzeichnisnamen angegeben habt. In unserem Fall sucht pytest im
tests
-Verzeichnis.Auf den ersten Blick mag es überflüssig erscheinen,
testpaths
auftests
zu setzen, da pytest sowieso dort sucht, und wir keinetest_
-Dateien in unserensrc
- oderdocs
-Verzeichnissen haben. Allerdings kann die Angabe einestestpaths
-Verzeichnisses ein wenig Startzeit sparen, besonders wenn unseresrc
- oderdocs
- oder andere Verzeichnisse recht groß sind.markers =
wird verwendet, um Marker zu deklarieren, wie in Auswahl von Tests mit eigenen Markern beschrieben.
Siehe auch
In den Konfigurationsdateien könnt ihr viele weitere
Konfigurationseinstellungen und Befehlszeilenoptionen angeben, die ihr euch
mit dem Befehl pytest --help
anzeigen lassen könnt.
Andere Konfigurationsdateien verwenden¶
Wenn ihr Tests für ein Projekt schreibt, das bereits eine
pyproject.toml
, tox.ini
oder setup.cfg
-Datei hat, könnt
ihr pytest.ini
verwenden, um eure pytest-Konfigurationseinstellungen zu
speichern, oder ihr könnt eure Konfigurationseinstellungen in einer dieser
alternativen Konfigurationsdateien speichern. Die Syntax der beiden
Nicht-ini-Dateien unterscheidet sich ein wenig, daher werden wir uns beide
Dateien genauer ansehen.
pyproject.toml
¶
Die pyproject.toml
-Datei war ursprünglich für die Paketierung von
Python-Projekten gedacht; sie kann jedoch auch für die Definition von
Projekteinstellungen verwendet werden.
Da TOML
ein anderer Standard für Konfigurationsdateien ist als .ini
-Dateien, ist
das Format auch ein wenig anders:
[tool.pytest.ini_options]
addopts = [
"--strict-markers",
"--strict-config",
"-ra"
]
testpaths = "tests"
markers = [
"exception: Only run expected exceptions",
"finish: Only run finish tests",
"smoke: Small subset of all tests",
"num_items: Number of items to be pre-filled for the items_db fixture"
]
Anstelle von [pytest]
beginnt der Abschnitt mit
[tool.pytest.ini_options]
, die Werte müssen in Anführungszeichen gesetzt
werden und Listen von Werten müssen Listen von Zeichenketten in eckigen Klammern
sein.
setup.cfg
¶
Das Dateiformat der setup.cfg
entspricht einer .ini
-Datei:
[tool:pytest]
addopts =
--strict-markers
--strict-config
-ra
testpaths = tests
markers =
smoke: Small subset of all tests
exception: Only run expected exceptions
Der einzige Unterschied zwischen dieser und der pytest.ini
ist die
Angabe des Abschnitts [tool:pytest]
.
Warnung
Der Parser der .cfg
-Datei unterscheidet sich jedoch vom Parser der
.ini
-Datei, und dieser Unterschied kann Probleme verursachen, die
schwer aufzuspüren sind, s.a. pytest-Dokumentation.
rootdir
festlegen¶
Noch bevor pytest nach auszuführenden Testdateien sucht, liest es die
Konfigurationsdatei pytest.ini
, tox.ini
, pyproject.toml
oder setup.cfg
, die einen pytest-Abschnitt enthält:
wenn ihr ein Testverzeichnis angegeben habt, beginnt pytest dort zu suchen
wenn ihr mehrere Dateien oder Verzeichnisse angegeben habt, beginnt pytest mit dem übergeordneten Verzeichnis
wenn ihr keine Datei oder kein Verzeichnis angebt, beginnt pytest im aktuellen Verzeichnis.
Wenn pytest eine Konfigurationsdatei im Startverzeichnis findet, ist das die
Wurzel und wenn nicht, geht pytest den Verzeichnisbaum hoch, bis es eine
Konfigurationsdatei findet, die einen pytest-Abschnitt enthält. Sobald pytest
eine Konfigurationsdatei gefunden hat, markiert es das Verzeichnis, in dem es
sie gefunden hat, als rootdir
. Dieses Wurzelverzeichnis ist auch die
relative Wurzel der IDs. pytest sagt euch auch, wo es eine Konfigurationsdatei
gefunden hat. Durch diese Regeln können wir Tests auf verschiedenen Ebenen
durchführen und sicher sein, dass pytest die richtige Konfigurationsdatei
findet:
$ cd items
$ pytest
============================= test session starts ==============================
...
rootdir: /Users/veit/cusy/prj/items
configfile: pyproject.toml
testpaths: tests
plugins: Faker-19.11.0
collected 39 items
...
conftest.py
für die gemeinsame Nutzung von lokalen Fixtures und Hook-Funktionen¶
Die conftest.py
-Datei wird verwendet, um Fixtures und Hook-Funktionen zu
speichern, s.a. Test-Fixtures und Plugins. Ihr
könnt so viele conftest.py
-Dateien in einem Projekt haben, wie ihr
wollt. Alles, was in einer conftest.py
-Datei definiert ist, gilt für
Tests in diesem Verzeichnis und allen Unterverzeichnissen.
Wenn ihr eine conftest.py
-Datei auf der obersten Testebene habt, können
die dort definierten Fixtures für alle Tests verwendet werden. Wenn es dann
spezielle Fixtures gibt, die nur für ein Unterverzeichnis gelten, können diese
in einer anderen conftest.py
-Datei in diesem Unterverzeichnis definiert
werden. Zum Beispiel könnten die CLI-Tests andere Fixtures benötigen als die
API-Tests, und einige könnt ihr auch gemeinsam nutzen.
Tipp
Es ist jedoch eine gute Idee, nur eine einzige conftest.py
-Datei zu
halten, damit ihr die Fixture-Definitionen leicht finden können. Auch wenn
wir mit pytest --fixtures -v
immer herausfinden können, wo eine
Fixture definiert ist, so ist es dennoch einfacher, wenn sie immer in der
einen conftest.py
-Datei definiert ist.
__init__.py
um Kollision von Testdateinamen zu vermeiden¶
Die __init__.py
-Datei erlaubt es, doppelte Testdateinamen zu haben. Wenn
ihr __init__.py
-Dateien in jedem Test-Unterverzeichnis habt, könnt ihr
denselben Testdateinamen in mehreren Verzeichnissen verwenden, z.B.:
items
├── …
├── pytest.ini
├── src
│ └── …
└── tests
├── api
│ ├── __init__.py
│ └── test_add.py
├── cli
│ ├── __init__.py
│ ├── conftest.py
│ └── test_add.py
└── conftest.py
Nun können wir die add
-Funktionalität sowohl über die API als auch über die CLI testen, wobei eine test_add.py
in beiden Verzeichnissen liegt:
$ pytest
============================= test session starts ==============================
...
rootdir: /Users/veit/cusy/prj/items
configfile: pyproject.toml
testpaths: tests
plugins: Faker-19.11.0
collected 6 items
tests/api/test_add.py .... [ 66%]
tests/cli/test_add.py .. [100%]
============================== 6 passed in 0.03s ===============================
Die meisten meiner Projekte starten mit folgender Konfiguration:
addopts =
--strict-markers
--strict-config
-ra
Siehe auch