Komponententests: Testfälle und Isolation verstehen
Ein Komponententest prüft einen abgegrenzten Softwarebaustein gegen erwartete Ergebnisse, möglichst ohne störende Einflüsse anderer Bausteine. So kannst du Fehler früh eingrenzen. Ein bestandener Test beweist aber nur das Verhalten in den gewählten Testfällen – nicht die Fehlerfreiheit der Komponente.
Hake ab, was du schon kannst — und komm am Ende hierher zurück!
Was genau wird beim Komponententest geprüft?
Stell dir eine Funktion vor, die aus einem Warenwert die Versandkosten berechnet. Du möchtest wissen, ob diese eine Berechnung richtig arbeitet – unabhängig von Benutzeroberfläche, Datenbank und Zahlungsdienst.
Komponententest
Ein Komponententest prüft eine einzelne, abgegrenzte Komponente anhand festgelegter Anforderungen. Dazu wird ein Ausgangszustand hergestellt, die Komponente mit bestimmten Eingaben ausgeführt und das beobachtete Ist-Ergebnis mit einem erwarteten Soll-Ergebnis verglichen.
Was als Komponente gilt, hängt vom Projekt ab. In einem Softwareprojekt kann es eine Funktion, Methode, Klasse oder ein Modul sein. In einem technischen System kann eine Komponente auch Mechanik, Elektronik und Software enthalten. Vor dem Test muss deshalb klar festgelegt sein, wo die Grenze des Prüfgegenstands verläuft.
In vielen Softwarekontexten werden Unit-Test, Modultest und Komponententest ähnlich oder sogar gleichbedeutend verwendet. „Unit“ betont meist eine kleine Codeeinheit. „Komponente“ kann je nach vereinbarter Grenze weiter gefasst sein. Entscheidend ist nicht das Wort allein, sondern was isoliert geprüft wird.
Erst die vereinbarte Grenze macht aus einem beliebigen Test einen Komponententest: Was gehört zum Prüfgegenstand, was ist eine Abhängigkeit und welches Verhalten wird erwartet?
Teststufen sicher unterscheiden
Die Teststufen unterscheiden sich vor allem durch Prüfgegenstand und Frage:
| Testart | Prüfgegenstand | Leitfrage |
|---|---|---|
| Unit- oder Komponententest | eine abgegrenzte Einheit, meist isoliert | Erfüllt dieser Baustein seinen Vertrag? |
| Integrationstest | mehrere integrierte Komponenten oder Dienste im Zusammenspiel | Funktionieren Schnittstellen und Datenaustausch zusammen? |
| Systemtest | das integrierte Gesamtsystem | Erfüllt das gesamte System die festgelegten Systemanforderungen? |
Ein Beispiel zeigt den Fokuswechsel:
- Ein Komponententest prüft, ob
berechneVersandkosten(49)den festgelegten Betrag liefert. - Ein Integrationstest prüft, ob Warenkorb und Versanddienst die Daten im richtigen Format austauschen.
- Ein Systemtest prüft den vollständigen Bestellablauf im integrierten System.
Die Stufen ersetzen einander nicht. Ein korrekter einzelner Baustein kann über eine fehlerhafte Schnittstelle falsch eingebunden sein. Umgekehrt kann ein Systemtest einen Fehler zeigen, ohne seine Ursache so genau einzugrenzen wie ein Komponententest.
Einen aussagekräftigen Testfall entwerfen
Ein Testfall beginnt bei einer Anforderung, nicht bei einem zufällig gewählten Eingabewert. Angenommen, die Spezifikation lautet:
rabatt(preis, mitglied) gibt für Mitglieder 10 Prozent des nicht negativen Preises als Rabatt zurück. Für Nichtmitglieder beträgt der Rabatt 0. Negative Preise werden abgewiesen.
Gehe in drei Schritten vor:
- Ausgangszustand und Eingaben festlegen: Welche Werte und Voraussetzungen gelten?
- Operation ausführen: Welche Komponente wird aufgerufen?
- Soll und Ist vergleichen: Welches beobachtbare Ergebnis fordert die Spezifikation?
Für den Normalfall preis = 80 und mitglied = wahr erwartest du einen Rabatt von 8. Der Test richtet die Eingaben ein, ruft rabatt(80, wahr) auf und vergleicht das Ergebnis mit 8. Liefert die Funktion 8, ist genau dieser Testfall bestanden.
Der entscheidende Gedanke: Der Sollwert stammt aus der Anforderung und wird vor der Auswertung festgelegt. Das Ergebnis der Funktion darf nicht nachträglich zum erwarteten Wert erklärt werden.
Ein einzelner Normalfall reicht nicht. Wähle Testfälle mit unterschiedlichen Aufgaben:
- Normalfall: ein typischer gültiger Wert, etwa
80und Mitglied. - Randfall: ein Wert an einer bedeutsamen Grenze, hier
0und Mitglied; erwartet wird0. - Alternative gültige Bedingung:
80und kein Mitglied; erwartet wird0. - Ungültiger Fall: ein negativer Preis; erwartet wird die in der Spezifikation festgelegte Abweisung.
Eine große Anzahl beliebiger Testwerte ist nicht automatisch aussagekräftig. Gute Testfälle stehen für unterschiedliche Anforderungen, Grenzen und mögliche Fehler. Welches Überdeckungsziel nötig ist, hängt vom Projekt und seinem Risiko ab.
Abhängigkeiten kontrollieren und Isolation verstehen
Viele Komponenten rufen andere Teile auf: eine Datenbank, einen Dienst, eine Uhr oder eine Hardware-Schnittstelle. Würdest du alle echten Abhängigkeiten einbinden, könnte ein Fehler außerhalb des Prüfgegenstands den Test beeinflussen. Dann wäre die Ursache schwerer zu erkennen.
Für einen isolierten Komponententest ersetzt du benötigte Abhängigkeiten deshalb bei Bedarf durch Testdoubles. Sie liefern kontrollierte Antworten oder zeichnen Aufrufe auf.
Stub und Driver
Ein Stub ersetzt einen Baustein, den die getestete Komponente aufruft, und liefert vorbereitete Antworten. Ein Driver ersetzt den aufrufenden Teil und startet die zu testende Operation mit festgelegten Eingaben.
Eine Komponente zeigeWetter fragt normalerweise einen Wetterdienst ab. Für ihren Komponententest liefert ein Stub immer die kontrollierte Antwort „18 Grad“. So prüfst du, ob zeigeWetter diese Antwort richtig verarbeitet, auch wenn der echte Dienst nicht verfügbar ist.
Damit hast du jedoch noch nicht geprüft, ob die echte Verbindung, das echte Datenformat und mögliche Netzwerkfehler korrekt behandelt werden. Dafür brauchst du passende Integrations- oder weiterführende Tests.
Ein Testdouble ist selbst nur ein Modell. Bildet es Antwortcodes, Plausibilitätsprüfungen oder Zustände unvollständig ab, kann der Test trotz eines späteren Integrationsfehlers grün sein. Außerdem können Test und Implementierung denselben falschen Denkfehler enthalten.
Isolation macht Ursachen leichter sichtbar, blendet aber bewusst einen Teil der Wirklichkeit aus. Deshalb folgen weitere Teststufen, in denen schrittweise mehr Zusammenspiel geprüft wird.
Fehler auswerten und Korrekturen absichern
Ein fehlgeschlagener Test zeigt zunächst eine Abweichung zwischen Soll und Ist. Er sagt noch nicht automatisch, welche Codezeile die Ursache ist.
Gehe systematisch vor:
- Prüfe, ob Anforderung, Eingaben und Sollwert eindeutig sind.
- Stelle sicher, dass der Testaufbau nicht selbst fehlerhaft ist.
- Verfolge die Verarbeitung bis zur ersten falschen Zustandsänderung oder Ausgabe.
- Behebe die Ursache in der Komponente.
- Führe den fehlgeschlagenen Test und die übrigen passenden Tests erneut aus.
- Bewahre den Test als Regressionstest auf, wenn er einen behobenen Fehler dauerhaft abdecken soll.
Für rabatt(80, wahr) lautet das Soll 8, das Ist aber 72. Die erste auffällige Zustandsänderung zeigt: Die Funktion gibt den zu zahlenden Restbetrag statt des Rabatts zurück. Nach der Korrektur wird derselbe Test erneut ausgeführt. Besteht er nun, belegt das die Korrektur für diesen Fall; andere Testfälle müssen weiterhin laufen, damit die Änderung kein anderes Verhalten beschädigt.
Auch Testcode ist Code. Er kann falsche Erwartungen, ungeeignete Daten oder problematische gemeinsame Zustände enthalten und sollte deshalb nachvollziehbar benannt, gepflegt und überprüft werden.
Karteikasten
Überlege zuerst selbst und drehe die Karte anschließend zum Prüfen um.
Alles auf einen Blick
- Komponententest
- Prüfgegenstand
- abgegrenzte Komponente
- beobachtbares Verhalten
- Testfall
- Ausgangszustand und Eingabe
- Soll-Ist-Vergleich
- Normal-, Rand- und Fehlerfall
- Isolation
- kontrollierte Abhängigkeiten
- Stub oder Driver
- begrenztes Modell der Wirklichkeit
- Teststufen
- Unit oder Komponente
- Integration der Teile
- Gesamtsystem
- Ergebnis
- Fehler eingrenzen
- Korrektur wiederholen
- keine Garantie auf Fehlerfreiheit
- Prüfgegenstand
Mit Google fortfahren