- 1 Section
- 10 Lessons
- unbegrenzt
- Testen & Testmanagement10
- 1.1Warum testen? Fehlerkosten und V-Modell
- 1.2Teststufen: Unit, Integration, System, Abnahme
- 1.3Black-Box-Test: Äquivalenzklassen und Grenzwertanalyse
- 1.4White-Box-Test: Zweig- und Pfadüberdeckung
- 1.5TDD: Red-Green-Refactor
- 1.6Unit-Tests schreiben (JUnit / pytest)
- 1.7Mocking und Test-Doubles
- 1.8Testplan, Testprotokoll und Dokumentation
- 1.9Testergebnisse multimedial aufbereiten
- 1.10Aufgaben Testen
Unit-Tests schreiben (JUnit / pytest)
In L5 hast du das TDD-Prinzip kennengelernt. Jetzt zeigen wir konkret, wie Unit-Tests in den beiden wichtigsten Sprachen für deine Ausbildung aussehen: Java mit JUnit und Python mit pytest. Beide stehen im IHK-Rahmenplan (B2c).
Du lernst hier das AAA-Pattern (Arrange-Act-Assert) – die Struktur, der jeder vernünftige Test folgt. Dazu Assertions, Fixtures (Vor- und Nachbereitung), Test-Naming und typische Anti-Patterns. Diese Lektion ist praktisch – schreib die Beispiele bei dir nach.
1) Was ist ein Unit-Test technisch?
Ein Unit-Test ist eine Methode/Funktion, die: eine andere Methode unter klaren Bedingungen aufruft, das Ergebnis vergleicht und einen Test-Fehler produziert, falls die Erwartung nicht erfüllt ist. Frameworks wie JUnit oder pytest helfen, viele solche Tests automatisiert laufen zu lassen und einen Report zu erzeugen.
Wichtige Eigenschaften eines guten Unit-Tests:
- Schnell: Millisekunden, nicht Sekunden.
- Isoliert: testet eine Sache. Andere Tests bleiben unbeeindruckt.
- Wiederholbar: Tausende Male, gleicher Code = gleiches Ergebnis.
- Selbsterklärend: aus dem Testnamen und Body sofort erkennbar, was getestet wird.
- Selbstvalidierend: automatische pass/fail-Aussage – kein manuelles Hinschauen nötig.
Diese fünf Punkte sind als FIRST-Prinzip bekannt: Fast, Isolated, Repeatable, Self-validating, Timely. Klausurrelevant.
2) Das AAA-Pattern: jeder Test in drei Blöcken
Der Klassiker zur Strukturierung eines Tests heißt Arrange-Act-Assert. Jeder Test besteht aus drei Phasen:
3) Das gleiche Beispiel in JUnit und pytest
Wir testen eine simple Funktion add(a, b), die zwei Zahlen addiert. Hier dieselbe Logik in beiden Sprachen:
@Test-Annotation reicht eine Funktion mit dem Präfix test_. Statt assertEquals(erwartet, tatsächlich) ein simples assert == . Java/JUnit ist zeremonieller, dafür stärker typisiert. Beide funktionieren nach dem AAA-Schema und beide werden vom Test-Runner automatisch erkannt und ausgeführt.4) JUnit 5 – die wichtigsten Annotations
JUnit ist das Java-Test-Framework. Aktuelle Version: JUnit 5 („Jupiter"). Die zentralen Annotations:
@Test– markiert eine Testmethode. Wird vom Runner ausgeführt.@BeforeEach– läuft vor jedem Test (z.B. fresh Setup).@AfterEach– läuft nach jedem Test (z.B. Cleanup).@BeforeAll/@AfterAll– läuft einmal vor/nach der gesamten Testklasse (statische DB-Verbindungen).@DisplayName("...")– eingeblendeter Name im Report.@Disabled("...")– Test temporär deaktivieren mit Begründung.@ParameterizedTest– derselbe Test mit verschiedenen Eingabewerten.@Nested– verschachtelte Testklassen zur Strukturierung.
Typische Assertions in JUnit: assertEquals(expected, actual), assertTrue(condition), assertNull(x), assertThrows(Exception.class, () -> ...). Achtung Reihenfolge bei assertEquals: erwartet zuerst, tatsächlich danach.
5) pytest – die wichtigsten Konzepte
Pytest ist das beliebteste Python-Test-Framework. Konzeptionell viel schlanker als JUnit:
- Test-Funktionen beginnen mit
test_– kein Annotations-System nötig. - Test-Klassen beginnen mit
Test(Singular). assertist das einzige Stichwort, das du brauchst.assert x == y,assert x in liste,assert pattern.match(s).- Fixtures ersetzen
@BeforeEach: mit@pytest.fixture-Dekorator und Funktion. Tests bekommen sie als Parameter. - Parametrisierung mit
@pytest.mark.parametrize. - Ausführung: einfach
pytestim Projekt-Root.
Beide Frameworks integrieren sich nahtlos in CI/CD und Coverage-Tools (JaCoCo bzw. coverage.py – vgl. L4).
6) Test-Naming – die unterschätzte Disziplin
Ein guter Testname ist wichtiger als ein cleverer Test-Body. Lese diese drei Namen:
test1()– wertlos, niemand weiß was gemeint ist.testAdd()– immerhin ein Hinweis, aber unklar was geprüft wird.add_gibtSummeZurueck_beiZweiPositivenZahlen()– klar: was, unter welchen Bedingungen, mit welcher Erwartung.
Das letzte Schema heißt Given-When-Then im Namen: methode_erwartetesVerhalten_bedingungen(). Vorteil: wenn der Test rot wird, weißt du sofort aus dem Namen, was kaputt ist. Kein Hineingucken nötig.
7) Wichtige Assertion-Arten
assertEquals(7, x) (JUnit) / assert x == 7 (pytest). Bei Objekten greift equals() bzw. __eq__.assertTrue(...), assertFalse(...). Für boolesche Ausdrücke ohne Vergleich.assertNull(x) / assertNotNull(x). In pytest assert x is None.assertThrows(Ex.class, () -> code()) (JUnit) / with pytest.raises(Exception): (pytest).assertIterableEquals(...) / assert sorted(a) == sorted(b). Auf Inhalte und Reihenfolge achten.assertEquals(0.1, x, 0.001) mit Toleranz – wegen Rundungsfehlern niemals exakt vergleichen!0.1 + 0.2 == 0.3 ist false in fast jeder Programmiersprache (Floating-Point-Repräsentation, vgl. K38). Für Floats immer mit Toleranz vergleichen.8) Fixtures: Vor- und Nachbereitung
Viele Tests brauchen denselben Setup-Code – etwa „lege ein leeres User-Objekt an, eine leere Liste, ein Mock-Repository". Statt das in jedem Test zu wiederholen, definiert man Fixtures:
In JUnit: eine Methode mit @BeforeEach. Sie läuft vor jedem Test. Klassenvariablen werden befüllt, Tests greifen darauf zu.
In pytest: eine Funktion mit @pytest.fixture. Tests, die sie als Parameter haben, bekommen sie automatisch übergeben. Vorteil: explizit, kein verstecktes Magic. Fixtures können scope haben (per test, per class, per session), parametrisiert sein und auch Cleanup machen (mit yield).
9) Best Practices und Anti-Patterns
System.out.println im Test ist nutzlos. Nur Assertions zählen.10) Parametrisierte Tests
Wenn die gleiche Methode mit vielen Eingaben getestet werden soll, vermeide Copy-Paste:
JUnit: @ParameterizedTest mit @ValueSource oder @CsvSource. Eine Testmethode, n Aufrufe mit verschiedenen Parametern.
pytest: @pytest.mark.parametrize("x,erwartet", [(1,1), (3,"Fizz"), (5,"Buzz"), (15,"FizzBuzz")]). Sehr elegant.
Vorteil: ein Bug-Fix muss nur an einer Stelle gemacht werden, alle Fälle bleiben automatisch konsistent.
11) Klausurklassiker
- AAA-Pattern erklären und auf ein Beispiel anwenden.
- FIRST-Prinzip: Fast, Isolated, Repeatable, Self-validating, Timely.
- JUnit-Annotations kennen:
@Test,@BeforeEach,@AfterEach. - assertEquals(erwartet, tatsächlich) – Reihenfolge!
- Test-Naming: method_expectedBehavior_condition.
- Was sind Fixtures? Setup vor jedem Test.
Zusammenfassung
Unit-Tests prüfen einzelne Methoden isoliert. Frameworks: JUnit (Java), pytest (Python). FIRST-Prinzip: Fast, Isolated, Repeatable, Self-validating, Timely. AAA-Pattern: Arrange (Setup), Act (eine Zeile), Assert (eine Aussage). JUnit: @Test, @BeforeEach, @ParameterizedTest. pytest: Funktionen mit test_, schlichtes assert, Fixtures als Parameter. Naming: methode_verhalten_bedingung(). Floats mit Toleranz vergleichen. Nächste Lektion: Mocking.
