Wie man Subtests verwendet

Hinzugefügt in Version 9.0.

Hinweis

Dieses Feature ist experimentell. Sein Verhalten, insbesondere wie Fehler gemeldet werden, kann sich in zukünftigen Versionen weiterentwickeln. Die Kernfunktionalität und Verwendung gelten jedoch als stabil.

pytest ermöglicht die Gruppierung von Assertions innerhalb eines normalen Tests, bekannt als Subtests.

Subtests sind eine Alternative zur Parametrisierung und besonders nützlich, wenn die exakten Parametrisierungswerte zur Sammelzeit nicht bekannt sind.

# content of test_subtest.py


def test(subtests):
    for i in range(5):
        with subtests.test(msg="custom message", i=i):
            assert i % 2 == 0

Jeder Assertionsfehler oder Fehler wird vom Context Manager abgefangen und einzeln gemeldet

$ pytest -q test_subtest.py
uuuuuF                                                               [100%]
================================= FAILURES =================================
_______________________ test [custom message] (i=1) ________________________

subtests = <_pytest.subtests.Subtests object at 0xdeadbeef0001>

    def test(subtests):
        for i in range(5):
            with subtests.test(msg="custom message", i=i):
>               assert i % 2 == 0
E               assert (1 % 2) == 0

test_subtest.py:6: AssertionError
_______________________ test [custom message] (i=3) ________________________

subtests = <_pytest.subtests.Subtests object at 0xdeadbeef0001>

    def test(subtests):
        for i in range(5):
            with subtests.test(msg="custom message", i=i):
>               assert i % 2 == 0
E               assert (3 % 2) == 0

test_subtest.py:6: AssertionError
___________________________________ test ___________________________________
contains 2 failed subtests
========================= short test summary info ==========================
SUBFAILED[custom message] (i=1) test_subtest.py::test - assert (1 % 2) == 0
SUBFAILED[custom message] (i=3) test_subtest.py::test - assert (3 % 2) == 0
FAILED test_subtest.py::test - contains 2 failed subtests
3 failed, 3 subtests passed in 0.12s

In der obigen Ausgabe

  • Subtestfehler werden als SUBFAILED gemeldet.

  • Subtests werden zuerst gemeldet und der "Top-Level"-Test wird am Ende allein gemeldet.

Beachten Sie, dass subtests mehrmals im selben Test verwendet werden können, oder sogar mit normalen Assertions außerhalb des subtests.test Blocks gemischt werden können

def test(subtests):
    for i in range(5):
        with subtests.test("stage 1", i=i):
            assert i % 2 == 0

    assert func() == 10

    for i in range(10, 20):
        with subtests.test("stage 2", i=i):
            assert i % 2 == 0

Hinweis

Siehe Wie man Fixtures und Testfunktionen parametrisiert für eine Alternative zu Subtests.

Ausführlichkeit

Standardmäßig werden nur Subtestfehler angezeigt. Höhere Ausführlichkeitsstufen (-v) zeigen auch Fortschrittsausgaben für erfolgreiche Subtests.

Die Ausführlichkeit von Subtests kann durch Setzen von verbosity_subtests gesteuert werden.

Typisierung

pytest.Subtests wird exportiert, damit es in Typannotationen verwendet werden kann

def test(subtests: pytest.Subtests) -> None: ...

Parametrisierung vs. Subtests

Während die traditionelle pytest-Parametrisierung und subtests ähnlich sind, gibt es wichtige Unterschiede und Anwendungsfälle.

Parametrisierung

  • Findet zur Sammelzeit statt.

  • Generiert einzelne Tests.

  • Parametrisierte Tests können von der Kommandozeile referenziert werden.

  • Funktioniert gut mit Plugins, die die Testausführung handhaben, wie z.B. --last-failed.

  • Ideal für Decision-Table-Tests.

Subtests

  • Finden während der Testausführung statt.

  • Sind zur Sammelzeit nicht bekannt.

  • Können dynamisch generiert werden.

  • Können nicht einzeln von der Kommandozeile referenziert werden.

  • Plugins, die die Testausführung handhaben, können nicht auf einzelne Subtests abzielen.

  • Ein Assertionsfehler innerhalb eines Subtests unterbricht den Test nicht und ermöglicht es Benutzern, alle Fehler im selben Bericht zu sehen.

Hinweis

Dieses Feature wurde ursprünglich als separates Plugin in pytest-subtests implementiert, wurde aber seit 9.0 in den Kern integriert.

Die Kernimplementierung sollte mit der Plugin-Implementierung kompatibel sein, außer dass sie keine benutzerdefinierten Kommandozeilenoptionen zur Steuerung der Subtestausgabe enthält.