Du änderst eine scheinbar harmlose CSS-Klasse im Header, pushst den Branch – und 20 Minuten später schlägt der Bezahlvorgang im Checkout fehl. Niemand hat den Checkout manuell durchgeklickt, und automatisierte Tests gab es nicht. Manuelles Testen skaliert nicht: Jede neue Codezeile ohne automatisierte Absicherung ist eine riskante Wette gegen die eigene Zukunft.
Frontend-Testing sichert Benutzeroberflächen über eine mehrstufige Pyramide ab: Schnelle Unit-Tests (Vitest) für isolierte Business-Logik, komponentenbasierte Integrations-Tests (React Testing Library) für Nutzerinteraktionen und End-to-End-Tests (Playwright) für kritische User Journeys im echten Browser. Ziel ist maximale Fehlererkennung bei minimaler CI-Laufzeit (unter 2 Minuten).
Teste immer das sichtbare Verhalten aus Nutzersicht, niemals interne Implementierungsdetails: Wenn ein internes Refactoring deine Tests bricht, ohne dass sich das UI ändert, hast du die falschen Dinge getestet.
Die 3 Schichten der modernen Testpyramide
1. Unit Tests (Vitest)
Prüfen isolierte Rechenlogik, Utility-Funktionen, Daten-Transformer und Custom Hooks ohne Browser-Overhead.
2. Integration Tests (RTL)
Rendern Komponenten im virtuellen DOM (jsdom). Simulieren Klicks, Tastatur-Eingaben und prüfen sichtbare Texte und ARIA-Rollen.
3. E2E Tests (Playwright)
Fahren vollständige User Journeys (Login, Warenkorb, Bezahlung) in echten Chromium-, Firefox- und WebKit-Instanzen ab.
Do's & Don'ts: Architektonische Entscheidungen
- Komponenten über ARIA-Rollen und Labels abfragen (
getByRole('button', { name: /speichern/i })) - Externe APIs auf Netzwerk-Ebene mit MSW (Mock Service Worker) abfangen
- Flaky Tests sofort unter Quarantäne stellen oder reparieren, statt sie zu ignorieren
- Kritische Kernpfade (Happy Path) als E2E-Smoke-Tests in der CI blockierend erzwingen
- Nach internen React-States oder CSS-Klassennamen selektieren (
getByClassName) - 100% Mocking betreiben, sodass der Test am Ende nur noch Mocks statt echten Code testet
- Feste
sleep()-Timeouts verwenden, anstelle auf DOM-Zustände zu warten (waitFor) - Visual Regression Tests auf unbemaßten, unruhigen Animationen laufen lassen
Worauf es beim Testen ankommt
- Nicht Implementierungsdetails testen: Frage nicht
wrapper.state('isOpen'), sondern teste, ob der Dialog für den Anwender sichtbar ist. - Speed is King: Unit- und Integrationstests müssen in wenigen Sekunden lokal in der IDE durchlaufen. Dauert die Suite Minuten, führt das Team sie vor dem Commit nicht mehr aus.
- Flakiness rigoros beseitigen: Tests, die manchmal grün und manchmal rot sind (Race Conditions, unkontrollierte Animationen), zerstören das Vertrauen des gesamten Teams in die CI.
Wer mit React Testing Library nach getByRole selektiert, testet automatisch Barrierefreiheit mit: Fehlt dem Button ein Label oder der Überschrift die Hierarchie, schlägt der Test bereits fehl! Siehe dazu unseren Leitfaden zu Accessibility & BITV 2.0.
Checkliste: Frontend-Testing in der Praxis
- Role-basierte Selektoren: Alle UI-Abfragen nutzen
getByRole,getByLabelTextodergetByTextstatt Klassennamen. - Deterministische Wartezeiten: Asynchrone Aktionen nutzen
findBy*oderwaitFor()statt willkürlichersetTimeout-Pausen. - Zero-Mocking für UI-Logik: Komponenten werden mit echtem State gerendert; gemockt werden ausschließlich externe Netzwerk-Requests.
- CI-Laufzeit unter 3 Minuten: Tests laufen parallelisiert in Matrix-Builds, um Entwickler nicht im Arbeitsfluss zu blockieren.
- Keine ungetesteten Business-Pfade: Rechenintensive Logik oder Finanz-Berechnungen sind durch 100% Unit-Test-Branch-Coverage abgesichert.