Zum Inhalt springen

Aufgabe 19 - pytest I

Zu Zen-Modus wechseln

Vom händischen Ausprobieren zum automatisierten Test: Sie schreiben pytest-Tests für Ihre bestehenden Funktionen und Klassen, testen erwartete Exceptions und decken mit Parametrisierung viele Fälle ohne Copy-Paste ab (siehe Kapitel Testen mit pytest). Getestet wird dabei Ihr eigener Code aus früheren Übungen; nebenbei erfahren Sie, wie gut der wirklich war.

  • Kapitel Testen mit pytest, Abschnitte erster Test, Anatomie, Exceptions, Parametrisierung.
  • Kapitel Bibliotheken und Pakete für venv und pip (oder die Kurzanleitung der Lehrkraft).
  • Ihre Lösungen der Aufgaben 02 (classics.py) und 14 (account.py mit Exceptions).
  • Sie richten pytest ein, führen Testläufe aus und interpretieren deren Ausgabe.
  • Sie schreiben Testfälle nach Arrange-Act-Assert mit sprechenden Namen.
  • Sie testen Fehlerverhalten mit pytest.raises und Testreihen mit parametrize.
  • Reproduktion: die pytest-Konventionen wiedergeben und einfache Tests nach Vorlage erstellen (Teil A).
  • Reorganisation und Transfer: Testmuster auf eigene Klassen übertragen und Testreihen strukturieren (Teile B und C).
  • Reflexion, Problemlösung und Urteilsbildung: Testfälle systematisch auswählen, Lücken aufdecken und die Aussagekraft von Tests beurteilen (Teil D).

Die Übung ist auf etwa zwei Stunden ausgelegt. Teil D ist der Expertenteil.

  1. Legen Sie eine virtuelle Umgebung an, aktivieren Sie sie und installieren Sie pytest (pip install pytest). Prüfen Sie mit pytest --version.
  2. Legen Sie test_classics.py an und schreiben Sie drei Tests für grade_average: normaler Fall, eine einzelne Note, leere Liste (was auch immer Sie damals entschieden haben: der Test dokumentiert die Entscheidung jetzt verbindlich).
  3. Führen Sie pytest -v aus. Alle Tests grün? Machen Sie danach einen Test absichtlich kaputt, lesen Sie die Fehlerausgabe vollständig und notieren Sie, welche Informationen pytest anzeigt (beide Vergleichsseiten!). Reparieren Sie den Test wieder.

Testen Sie Ihr Account aus Aufgabe 14 in test_account.py:

  1. deposit erhöht den Kontostand (sauberes Arrange-Act-Assert, Testname beschreibt das Verhalten).
  2. withdraw mit ungedecktem Betrag wirft InsufficientFundsError: mit pytest.raises.
  3. deposit(-5) wirft InvalidAmountError.
  4. Nach einer geworfenen Exception ist der Kontostand unverändert. Dieser Test findet erfahrungsgemäß echte Fehler; prüfen Sie ehrlich, ob Ihre Klasse ihn besteht.
  1. Schreiben Sie die Tests für caesar (Aufgabe 02) mit @pytest.mark.parametrize: mindestens sechs Fälle in einer Testfunktion (normaler Fall, Umbruch nach z, Verschiebung 0, Verschiebung 26, Leerzeichen bleiben erhalten, Satzzeichen bleiben erhalten).
  2. Führen Sie pytest -v aus und beobachten Sie, wie jeder Parametersatz als eigener Test ausgewiesen wird.
  3. Vergleichen Sie in zwei Kommentarsätzen: Was gewinnt die parametrisierte Form gegenüber sechs einzelnen Testfunktionen, und was verliert sie?

Teil D - Expertenteil: Testen vor dem Implementieren

Abschnitt betitelt „Teil D - Expertenteil: Testen vor dem Implementieren“
  1. Für die Funktion timecode_to_frames(timecode, fps=25) (Umkehrung der Timecode-Umrechnung; falls Sie Aufgabe 01 Teil D gelöst haben, legen Sie diese Fassung beiseite) schreiben Sie zuerst die komplette Testdatei: mindestens acht parametrisierte Normal- und Grenzfälle plus drei Fehlerfälle mit pytest.raises(ValueError) (falsches Format, Sekunden über 59, Framewert nicht kleiner als fps).
  2. Führen Sie die Tests gegen die noch nicht existierende Funktion aus (alles rot) und implementieren Sie dann genau so lange, bis alles grün ist. Kein Test wird nachträglich an die Implementierung angepasst, es sei denn, der Test selbst war falsch; dokumentieren Sie solche Fälle.
  3. Reflektieren Sie in drei bis fünf Sätzen: Wie hat das Testen-zuerst Ihre Implementierung beeinflusst? Welche Grenzfälle hätten Sie ohne die Testliste vermutlich übersehen?
  4. Zusatzfrage mit Beleg: Ihre Testreihe ist grün. Beweist das die Korrektheit der Funktion? Konstruieren Sie einen Fehler, den Ihre aktuelle Testreihe nicht finden würde, und ergänzen Sie den fehlenden Test.
  1. Nach welchen Namenskonventionen findet pytest Testdateien und Testfunktionen?
  2. Wofür stehen die drei Schritte Arrange, Act, Assert?
  3. Wann besteht ein Test mit pytest.raises(ValueError), und wann scheitert er?
  4. Warum gehört zu jedem behobenen Fehler ein neuer Test?
  5. Was bedeutet ein grüner Testlauf, und was bedeutet er ausdrücklich nicht?

test_classics.py, test_account.py, test_timecode.py samt Implementierung; ein Protokoll des Laufs pytest -v mit ausschließlich grünen Tests. Alles committet im Git-Repository, denn Tests gehören zum Code.