Typing in pytest¶
Hinweis
Diese Seite setzt voraus, dass der Leser mit Pythons Typsystem und seinen Vorteilen vertraut ist.
Weitere Informationen finden Sie in der Dokumentation zu Pythons Typen.
Warum Tests typisieren?¶
Das Typisieren von Tests bietet erhebliche Vorteile
Lesbarkeit: Definiert klar erwartete Eingaben und Ausgaben, was die Lesbarkeit verbessert, insbesondere bei komplexen oder parametrisierten Tests.
Refactoring: Dies ist der Hauptvorteil beim Typisieren von Tests, da es beim Refactoring erheblich hilft und den Typüberprüfer die notwendigen Änderungen sowohl in der Produktions- als auch in der Testumgebung aufzeigen lässt, ohne die vollständige Testsuite ausführen zu müssen.
Für Produktionscode hilft Typisierung auch dabei, einige Fehler zu erkennen, die von Tests überhaupt nicht erfasst werden könnten (unabhängig von der Abdeckung), zum Beispiel
def get_caption(target: int, items: list[tuple[int, str]]) -> str:
for value, caption in items:
if value == target:
return caption
Der Typüberprüfer wird korrekt einen Fehler melden, dass die Funktion None zurückgeben könnte. Eine vollständige Testsuite mit voller Abdeckung könnte diesen Fall jedoch verpassen.
def test_get_caption() -> None:
assert get_caption(10, [(1, "foo"), (10, "bar")]) == "bar"
Beachten Sie, dass der obige Code eine Abdeckung von 100 % hat, der Fehler jedoch nicht erkannt wird (natürlich ist das Beispiel „offensichtlich“, dient aber zur Veranschaulichung).
Typisierung in Testsuiten verwenden¶
Um Fixtures in pytest zu typisieren, fügen Sie einfach normale Typen zu den Fixture-Funktionen hinzu – es gibt nichts Besonderes, das getan werden muss, nur wegen des fixture-Dekorators.
import pytest
@pytest.fixture
def sample_fixture() -> int:
return 38
Auf die gleiche Weise müssen die an Testfunktionen übergebenen Fixtures mit dem Rückgabetyp der Fixture annotiert werden
def test_sample_fixture(sample_fixture: int) -> None:
assert sample_fixture == 38
Aus Sicht des Typüberprüfers spielt es keine Rolle, dass sample_fixture tatsächlich eine von pytest verwaltete Fixture ist; alles, was für ihn zählt, ist, dass sample_fixture ein Parameter vom Typ int ist.
Die gleiche Logik gilt für @pytest.mark.parametrize
@pytest.mark.parametrize("input_value, expected_output", [(1, 2), (5, 6), (10, 11)])
def test_increment(input_value: int, expected_output: int) -> None:
assert input_value + 1 == expected_output
Die gleiche Logik gilt, wenn Fixture-Funktionen typisiert werden, die andere Fixtures empfangen
@pytest.fixture
def mock_env_user(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setenv("USER", "TestingUser")
Schlussfolgerung¶
Die Einbeziehung von Typisierung in pytest-Tests verbessert die Klarheit, optimiert Debugging und Wartung und gewährleistet Typsicherheit. Diese Praktiken führen zu einer robusten, lesbaren und leicht wartbaren Testsuite, die besser gerüstet ist, zukünftige Änderungen mit minimalem Fehlerrisiko zu bewältigen.