Alle Tabs der Lerneinheit (Erklärung · Interaktiv verstehen · Praxis-Übung · Klausur-Quiz) als durchgehender Text. Ideal zum Wiederholen vor der Klausur, und für Suchmaschinen wie Google, Bing und KI-Suche (ChatGPT, Perplexity).
Diese Lerneinheit wurde für typische Bachelor-Klausuren konzipiert. So prüfen wir · Fehler entdeckt? Melde ihn uns oder markiere die fragliche Stelle direkt im Text oben.
Alle Tabs der Lerneinheit (Erklärung · Interaktiv verstehen · Praxis-Übung · Klausur-Quiz) als durchgehender Text. Ideal zum Wiederholen vor der Klausur, und für Suchmaschinen wie Google, Bing und KI-Suche (ChatGPT, Perplexity).
Ungetesteter Code ist gefährlicher als kein Code. Tests sind die Versicherung gegen Regressionen — sie sagen dir SOFORT, wenn deine Änderung etwas kaputt macht.
Klausur-Tipp: Bei der Frage "Wie testet man X?" immer fragen: Welche Ebene macht hier am meisten Sinn? Reine Logik (Berechnungen, Validierung) → Unit. Datenbank-Zugriff → Integration. Komplette User-Flow → E2E. Mische die Ebenen — aber halt die Pyramide ein.
Anmelden, um den Fortschritt zu speichern.
Nächster Schritt
Aktives Abrufen festigt Wissen schneller als nochmal lesen.
Ungetesteter Code ist gefährlicher als kein Code. Tests sind die Versicherung gegen Regressionen — sie sagen dir SOFORT, wenn deine Änderung etwas kaputt macht.
Test-Pyramide (Mike Cohn 2009): Strategie für die Verteilung verschiedener Test-Arten — viele schnelle Unit-Tests, weniger Integrations-Tests, ganz wenig E2E-Tests.
/\
/ \
/E2E\ ← Wenige, langsame, fragile (5-10 %)
/------\
/ \
/Integration\ ← Mehr (15-25 %)
/------------\
/ \
/ Unit \ ← Viele, schnelle, robust (70-80 %)
/-------------------\
Faustregel: Pro Ebene 5-10× weniger Tests als die Ebene darunter.
Was? Eine einzelne Funktion/Methode/Klasse in Isolation testen.
@Test
void einzahlen_erhoeht_kontostand() {
// Arrange
Konto k = new Konto(100.0);
// Act
k.einzahlen(50.0);
// Assert
assertEquals(150.0, k.getKontostand());
}
Charakteristik:
Frameworks: JUnit (Java), pytest (Python), Mocha/Vitest (JS), xUnit (.NET).
Was? Mehrere Komponenten/Module zusammen testen — z.B. mit echter DB, echter API.
@Test
void bestellung_speichern_persistiert_in_db() {
// Arrange
BestellungRepository repo = new BestellungRepository(dataSource);
Bestellung b = new Bestellung("kunde-1", List.of(...));
// Act
repo.save(b);
// Assert
Bestellung gespeichert = repo.findById(b.getId());
assertEquals(b.getKunde(), gespeichert.getKunde());
}
Charakteristik:
Frameworks: Spring Boot Test (Java), Django Test (Python), Testcontainers (für DB-Container).
Was? Komplette User-Journeys durch die gesamte Anwendung — Browser + UI + Backend + DB.
test('user kann sich registrieren und einloggen', async ({ page }) => {
await page.goto('https://shop.example.com');
await page.click('text=Registrieren');
await page.fill('#email', 'test@example.com');
await page.fill('#password', 'sicher123');
await page.click('button:has-text("Registrieren")');
await expect(page).toHaveURL(/.*\/dashboard/);
});
Charakteristik:
Frameworks: Selenium, Cypress, Playwright.
| Aspekt | Unit | Integration | E2E |
|---|---|---|---|
| Geschwindigkeit | ms | s | min |
| Anzahl | sehr viele | mittel | wenige |
| Isolation | hoch | mittel | keine |
| Wartungsaufwand | gering | mittel | sehr hoch |
| Falsch-positiv-Rate | gering | mittel | hoch (flaky tests) |
| Bug-Findung pro Test | gering | mittel | hoch |
Goldstandard für Test-Struktur:
@Test
void test_method_name() {
// Arrange: Vorbedingungen
Konto k = new Konto(100.0);
// Act: die zu testende Aktion
k.einzahlen(50.0);
// Assert: Erwartetes Ergebnis prüfen
assertEquals(150.0, k.getKontostand());
}
| Buchstabe | Prinzip |
|---|---|
| Fast | Schnell — sonst werden Tests nicht ausgeführt |
| Independent | Unabhängig — Tests dürfen keine Reihenfolge brauchen |
| Repeatable | Wiederholbar — gleiches Ergebnis in jeder Umgebung |
| Self-Validating | Selbst-prüfend — eindeutig PASS/FAIL, kein manueller Check |
| Timely | Rechtzeitig — am besten VOR oder MIT dem Code (TDD) |
Wenn echte Abhängigkeiten zu langsam/komplex sind:
| Typ | Was tut er? |
|---|---|
| Dummy | Wird gar nicht benutzt, nur zum Befüllen von Parametern |
| Stub | Gibt vorgegebene Antworten zurück (z.B. immer "Sonne" als Wetter) |
| Mock | Wie Stub, prüft aber auch ob er aufgerufen wurde |
| Spy | Wie Mock, ruft echte Methode + zeichnet auf |
| Fake | Eigene einfache Implementierung (z.B. In-Memory-DB) |
Code-Coverage: Prozent der Code-Zeilen, die von Tests durchlaufen werden.
1. Test-Pyramide: Unten viele Unit-Tests, oben wenige E2E.
2. Unit-Test: Eine Funktion isoliert. Mocks für Abhängigkeiten.
3. Integration: Mehrere Komponenten zusammen, echte DB.
4. E2E: Komplette User-Journey via Browser.
5. AAA: Arrange / Act / Assert.
6. FIRST: Fast / Independent / Repeatable / Self-Validating / Timely.
1. Test-Eis-Hut statt Pyramide. Wenn man unten WENIGE Unit-Tests und oben VIELE E2E-Tests hat (umgekehrte Pyramide), ist die Test-Suite langsam, fragil und teuer in der Wartung. Anti-Pattern.
2. Mocks überall. Wenn man jede Abhängigkeit mockt, testet man im Endeffekt die Mocks, nicht den Code. Faustregel: möglichst wenig mocken, am liebsten echte Implementierungen.
3. Tests von externer Reihenfolge abhängig. Test A muss vor Test B laufen, sonst schlägt B fehl. Das verletzt FIRST (Independent). Jeder Test muss eigenständig laufen können.
4. Test-Coverage als Goldstandard. 100 % Coverage mit schlechten Tests sagt nichts aus. Wichtiger als Coverage: testen die Tests die WICHTIGSTEN Pfade und Edge Cases?
5. Flaky Tests ignorieren. Tests, die manchmal grün, manchmal rot sind — sind ein RIESEN-Problem. Entweder Bug im Test oder im Code. NICHT einfach "retry" einbauen.
Verschiebe die Test-Verteilung und sieh die Auswirkungen auf Geschwindigkeit, Wartung und Fehler-Findung.
Interaktive Visualisierung
Interaktive Komponente: probiere sie im Topic-Player oben aus.
Klausur-Tipp: Bei der Frage "Wie testet man X?" immer fragen: Welche Ebene macht hier am meisten Sinn? Reine Logik (Berechnungen, Validierung) → Unit. Datenbank-Zugriff → Integration. Komplette User-Flow → E2E. Mische die Ebenen — aber halt die Pyramide ein.
6 Aufgaben zu Test-Ebenen, AAA-Pattern und Test Doubles.
Klausurfragen mit Lösungen (6)
Antwort: Unit-Tests
Erklärung: Die BASIS der Pyramide besteht aus Unit-Tests (70-80 % aller Tests). Sie sind schnell, isoliert, robust. Darüber kommen Integrations-Tests (15-25 %), an der Spitze die E2E-Tests (5-10 %). Die Form 'breit unten, schmal oben' garantiert schnelle Tests und niedrigen Wartungs-Aufwand.
Antwort: Arrange, Act, Assert
Erklärung: AAA = Arrange / Act / Assert. Standard-Struktur eines Tests: 1) Arrange = Vorbedingungen schaffen (Test-Daten, Mocks), 2) Act = die zu testende Methode aufrufen, 3) Assert = erwartetes Ergebnis prüfen. Diese Struktur macht Tests lesbar und konsistent.
Zuordnungen:
Erklärung: Die 4 wichtigsten Test-Doubles (nach Meszaros, xUnit Patterns): Dummy = wird nicht benutzt. Stub = liefert feste Antworten. Mock = Stub + prüft Aufrufe. Fake = eigene einfache Implementierung. Spy = wie Mock + ruft echte Methode auf. Wichtig in Klausuren: Mock vs Stub-Unterschied.
Typ: Zuordnung
Antwort: Unit-Tests mit Mocks
Erklärung: Unit-Tests mit Mocks sind am schnellsten — Millisekunden pro Test, da keine echten DB-Zugriffe, kein Netzwerk, kein Filesystem. Integration-Tests dauern Sekunden (echte DB-Operationen), E2E sogar Minuten (Browser starten, Seiten laden). Daher: Unit-Tests in jedem CI-Lauf, Integration nur bei Pull-Requests, E2E vielleicht nur in Nightly-Builds.
Antwort: Falsch
Erklärung: FALSCH. Coverage misst nur, welche Code-Zeilen durchlaufen werden, NICHT ob die Assertions sinnvoll sind. Man kann 100 % Coverage haben mit Tests wie `assertTrue(true)` — die nichts wirklich prüfen. Außerdem werden Edge Cases (Null-Werte, Grenz-Werte) oft nicht durch Coverage erfasst. Mutation Testing ist eine bessere Metrik.
Typ: Wahr/Falsch
Antwort: Unit-Test mit gemockten Services
Erklärung: Unit-Test mit Mocks ist optimal: schnell, isoliert, fokussiert auf die Rabatt-LOGIK ohne Service-Abhängigkeiten. Du mockst `UserService` und `ProductService` mit gewünschten Test-Daten und prüfst, ob `berechneRabatt` korrekt rechnet. Integration-Test wäre Overkill für reine Berechnungs-Logik. E2E wäre extreme Verschwendung.
6 typische Klausurfragen.
Klausurfragen mit Lösungen (6)
Antwort: Mike Cohn
Erklärung: Mike Cohn beschrieb die Test-Pyramide 2009 in seinem Buch 'Succeeding with Agile'. Robert C. Martin schrieb über Clean Code, Martin Fowler über Refactoring, Kent Beck über TDD und XP. Alle relevant in der Test-Welt, aber Test-Pyramide = Cohn.
Antwort: Viele Unit, weniger Integration, ganz wenig E2E (~70/20/10)
Erklärung: Klassische Test-Pyramide: ~70-80 % Unit, ~15-25 % Integration, ~5-10 % E2E. Untere Ebene MUSS am breitesten sein — sonst wird die Test-Suite zu langsam und zu fragil. Wenn dein Profil umgekehrt aussieht (Eis-Hut statt Pyramide), hast du ein Problem.
Lösungen pro Lücke:
Erklärung: FIRST = Fast (schnell), Independent (unabhängig), Repeatable (wiederholbar), Self-Validating (eindeutig pass/fail), Timely (rechtzeitig — am besten TDD). Test-Pyramide-Ebenen: Unit (Basis), Integration (Mitte), E2E/End-to-End (Spitze). Klausur-Klassiker.
Typ: Lückentext
Richtige Reihenfolge:
Erklärung: Reihenfolge: 1) Arrange (Test-Daten erstellen, Mocks konfigurieren), 2) Act (zu testende Methode aufrufen — meist 1 Zeile), 3) Assert (Erwartetes Ergebnis prüfen — meistens mit assertEquals/assertTrue), 4) Aufräumen (z.B. DB-State zurücksetzen, in @AfterEach). Letzter Schritt wichtig für Independent-FIRST-Prinzip.
Typ: Reihenfolge
Antwort: Mocks prüfen, ob sie aufgerufen wurden (verify), Stubs nur Antworten geben
Erklärung: Stub LIEFERT vordefinierte Antworten. Mock TUT DAS AUCH, prüft aber ZUSÄTZLICH, ob/wie er aufgerufen wurde (z.B. `verify(mockUserService).getUser('id-1')`). Praxis-Tipp: Mockito unterscheidet das nicht streng, viele Frameworks haben beide in einem. Aber konzeptionell: Mock = mit Aufruf-Verifikation, Stub = nur Antworten.
Antwort: Falsch
Erklärung: FALSCH. E2E-Tests sind zwar realistisch, aber LANGSAM (Minuten pro Test), FRAGIL (UI-Änderung bricht Test), AUFWENDIG IN DER WARTUNG. Sie sollten die MINDERHEIT der Tests sein (5-10 %). Die Mehrheit (70-80 %) sind Unit-Tests — die schnell, robust und fokussiert sind. Eine Test-Suite, die hauptsächlich aus E2E besteht (Eis-Hut), ist ein Anti-Pattern.
Typ: Wahr/Falsch
| Debug-Aufwand bei Fehler | gering | mittel | hoch |