EMZETT.
Login

Kurz: Ein Programm, das heute läuft, kann morgen nach einer kleinen Änderung kaputt sein. Automatische Tests prüfen deinen Code auf Knopfdruck. Sie sind das Sicherheitsnetz, mit dem du ohne Angst ändern kannst.

Teil des Kurses Python

Kapitel 41 von 44 im Kurs Python. Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

Ein Programm, das heute läuft, kann morgen nach einer kleinen Änderung kaputt sein. Automatische Tests prüfen deinen Code auf Knopfdruck. Sie sind das Sicherheitsnetz, mit dem du ohne Angst ändern kannst.

Die Idee

Du schreibst kleine Funktionen, die deinen Code mit bekannten Eingaben aufrufen und das Ergebnis mit der erwarteten Ausgabe vergleichen. Stimmt etwas nicht, schlägt der Test fehl.

Der einfachste Test ist assert:

def addiere(a, b):
    return a + b
 
assert addiere(2, 3) == 5
assert addiere(-1, 1) == 0
print("alle Prüfungen bestanden")
 
try:
    assert addiere(2, 2) == 5, "2 + 2 sollte 4 sein"
except AssertionError as e:
    print("Fehler:", e)

Ausgabe:

alle Prüfungen bestanden
Fehler: 2 + 2 sollte 4 sein

unittest (Standardbibliothek)

import unittest
 
def ist_primzahl(n):
    if n < 2:
        return False
    return all(n % t for t in range(2, int(n ** 0.5) + 1))
 
class TestPrimzahl(unittest.TestCase):
    def test_primzahlen(self):
        for p in (2, 3, 5, 7, 11):
            self.assertTrue(ist_primzahl(p))
 
    def test_keine_primzahlen(self):
        for n in (0, 1, 4, 9, 15):
            self.assertFalse(ist_primzahl(n))
 
    def test_fehler(self):
        with self.assertRaises(TypeError):
            ist_primzahl("a")
 
suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestPrimzahl)
ergebnis = unittest.TextTestRunner(verbosity=0, stream=open("/dev/null", "w")).run(suite)
print("Tests:", ergebnis.testsRun, "Fehler:", len(ergebnis.failures) + len(ergebnis.errors))

Ausgabe:

Tests: 3 Fehler: 0

In einer eigenen Datei test_irgendwas.py genügt am Ende:

if __name__ == "__main__":
    unittest.main()

Oder du startest alle Tests mit python -m unittest. Wichtige Prüfmethoden:

MethodePrüft
assertEqual(a, b)a == b
assertTrue(x) / assertFalse(x)Wahrheitswert
assertIn(a, b)a in b
assertAlmostEqual(a, b)fast gleich (Kommazahlen)
assertRaises(Fehler)löst die Ausnahme aus

pytest

pytest (pip install pytest) ist der beliebteste Testrunner. Tests sind einfache Funktionen mit assert, und bei Fehlern zeigt pytest sehr genau, was abwich:

# datei: test_rechnen.py
def test_addition():
    assert 1 + 1 == 2
 
def test_division_durch_null():
    import pytest
    with pytest.raises(ZeroDivisionError):
        1 / 0

Ausführen im Terminal:

pytest              # alle Tests im Projekt
pytest -v           # ausführliche Ausgabe
pytest -k primzahl  # nur Tests, deren Name "primzahl" enthält

Parametrisierte Tests

Mit @pytest.mark.parametrize läuft derselbe Test mit vielen Eingaben:

import pytest
 
@pytest.mark.parametrize("n, erwartet", [(2, True), (4, False), (13, True)])
def test_prim(n, erwartet):
    assert ist_primzahl(n) == erwartet

Fixtures

Fixtures liefern wiederverwendbare Testdaten oder Vorbereitungen:

import pytest
 
@pytest.fixture
def warenkorb():
    return {"Apfel": 2, "Birne": 1}
 
def test_menge(warenkorb):
    assert sum(warenkorb.values()) == 3

Was testet man?

  • Normale Fälle (das erwartete Verhalten)
  • Grenzfälle: leere Liste, Null, negative Zahlen, sehr große Werte
  • Fehlerfälle: Was passiert bei falscher Eingabe?
  • Jeden Fehler, den du gefunden hast, als Test festhalten, damit er nicht zurückkommt

Tipp

Schreibe die Funktion so, dass sie ein Ergebnis zurückgibt statt nur etwas auszugeben. Dann kannst du sie leicht testen.

Merke

  • Tests prüfen automatisch, ob Code das Erwartete tut
  • assert ist der einfachste Test, unittest ist eingebaut
  • pytest: Funktionen mit assert, parametrize und Fixtures
  • Teste normale Fälle, Grenzfälle und Fehlerfälle
  • Jeder gefundene Fehler wird zum Test

Übungsaufgabe

Schreibe eine Funktion ist_palindrom(text) und mindestens fünf Tests dafür, darunter Groß-/Kleinschreibung und den leeren Text.

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: Typ-Hints

Weiter: Kommandozeilen-Programme mit argparse

Alle Kapitel: Python im Überblick