Cypress: End-to-End-Tests für Webanwendungen schreiben und automatisieren

Was ist Cypress?

Cypress ist ein modernes, JavaScript-basiertes Test-Framework, das speziell für Webanwendungen entwickelt wurde. Anders als ältere Lösungen läuft Cypress direkt im Browser – nicht durch einen externen Treiber –, was die Ausführung deutlich schneller und zuverlässiger macht. Das Tool wurde 2017 veröffentlicht und hat sich seitdem zum De-facto-Standard für End-to-End-Tests in der JavaScript-Welt etabliert.

Cypress unterstützt sowohl End-to-End-Tests als auch Component Tests und bietet eine interaktive Benutzeroberfläche, in der Entwicklerinnen und Entwickler jeden Testschritt in Echtzeit verfolgen können. Die enge Integration in den Browser erlaubt es, Netzwerkanfragen abzufangen, den DOM zu manipulieren und auf interne Anwendungszustände zuzugreifen – Möglichkeiten, die mit klassischen Selenium-basierten Ansätzen schwer umsetzbar sind.

E2E-Tests vs. Unit-Tests: Was ist der Unterschied?

Unit-Tests überprüfen einzelne Funktionen oder Komponenten isoliert von ihrer Umgebung. Sie sind schnell, einfach zu schreiben und bilden die Basis einer soliden Teststrategie. E2E-Tests hingegen simulieren das vollständige Nutzerverhalten: Sie öffnen den Browser, navigieren durch die Anwendung, füllen Formulare aus und prüfen, ob das Ergebnis den Erwartungen entspricht.

Das klassische Testpyramiden-Modell empfiehlt viele Unit-Tests, einige Integrationstests und wenige E2E-Tests. Cypress bedient vor allem die oberen Schichten dieser Pyramide. Gerade bei komplexen Formularen, Multi-Step-Workflows oder Authentifizierungsabläufen sind E2E-Tests unverzichtbar, um Regressionsfehler frühzeitig zu erkennen.

Der Cypress Test Runner: Interaktive Entwicklung

Einer der größten Vorteile von Cypress gegenüber anderen Frameworks ist der interaktive Test Runner. Beim Ausführen von npx cypress open öffnet sich eine grafische Oberfläche, in der alle Testdateien aufgelistet sind. Ein Klick startet den Test in einem echten Browser-Fenster.

Im Test Runner sieht man auf der linken Seite jeden einzelnen Befehl mit seinem Status. Bei einem Hover über einen Befehl springt die rechte Seite zum entsprechenden DOM-Zustand – einem sogenannten Time Travel Snapshot. Das macht die Fehlersuche erheblich einfacher als das bloße Lesen von Stack Traces. Zusätzlich lassen sich Screenshots und Videos automatisch aufzeichnen.

Grundlegende Cypress-Befehle

Die wichtigsten Befehle für den Einstieg sind überschaubar:

Ein typischer Login-Test könnte so aussehen: cy.visit('/login'), dann cy.get('[data-cy="email"]').type('[email protected]'), cy.get('[data-cy="password"]').type('geheimwort') und cy.get('[data-cy="submit"]').click(). Anschließend prüft man mit cy.url().should('include', '/dashboard'), ob die Weiterleitung korrekt erfolgt ist.

Fixtures und cy.intercept: Netzwerkanfragen kontrollieren

In realen Tests möchte man oft nicht gegen echte APIs testen. Mit Fixtures lassen sich statische JSON-Dateien im Ordner cypress/fixtures/ ablegen und als Testdaten verwenden. Der Befehl cy.fixture('benutzer.json') lädt diese Datei und stellt sie im Test bereit.

cy.intercept() ist das mächtige Werkzeug, um HTTP-Anfragen abzufangen und durch Mock-Daten zu ersetzen. Ein Beispiel: cy.intercept('GET', '/api/users', { fixture: 'users.json' }).as('getUsers') fängt alle GET-Anfragen an /api/users ab und antwortet mit der Fixture-Datei. Mit cy.wait('@getUsers') kann man explizit warten, bis diese Anfrage abgeschlossen ist – das verhindert flaky Tests durch Timing-Probleme.

Praxis-Tipp: Verwende für alle interaktiven Elemente ein data-cy-Attribut statt CSS-Klassen oder IDs als Selektor. Klassen und IDs ändern sich häufig bei Refactoring, während Test-Attribute stabil bleiben. Eine Konvention wie data-cy="login-submit-button" macht Tests lesbar und wartbar zugleich.

Component Testing mit Cypress

Seit Version 10 bietet Cypress auch Component Testing für React, Vue, Angular und Svelte. Dabei wird die Komponente direkt im Browser gemountet, ohne die gesamte Anwendung zu starten. Das ist schneller als ein vollständiger E2E-Test und präziser als ein reiner Unit-Test mit jsdom.

Component Tests werden in der gleichen Syntax geschrieben wie E2E-Tests. Der Befehl cy.mount(<MeinButton label="Klick mich" />) rendert die Komponente. Danach kann man mit gewohnten Cypress-Befehlen interagieren und Assertions schreiben. Gerade für Bibliothekskomponenten oder Design-System-Elemente ist dieser Ansatz sehr wertvoll.

CI-Integration

Cypress lässt sich nahtlos in alle gängigen CI/CD-Systeme integrieren. Der Befehl npx cypress run führt alle Tests ohne grafische Oberfläche aus und gibt einen Exit-Code zurück – ideal für Pipelines. Mit dem offiziellen Cypress GitHub Action ist die Einrichtung in GitHub Actions in wenigen Zeilen erledigt.

Der kommerzielle Cypress Cloud-Dienst bietet darüber hinaus parallele Testausführung, Testergebnisanalysen und Flaky-Test-Erkennung. Für Open-Source-Projekte ist er kostenlos nutzbar.

Achtung: Cypress unterstützt standardmäßig nur Chromium-basierte Browser (Chrome, Edge, Electron) und Firefox. Safari und WebKit werden nicht offiziell unterstützt. Wer browserübergreifende Tests inklusive Safari benötigt, sollte Playwright in Betracht ziehen.

Vergleich: Cypress vs. Playwright vs. Selenium vs. WebdriverIO

Kriterium Cypress Playwright Selenium WebdriverIO
Ausführungsgeschwindigkeit Schnell (im Browser) Sehr schnell Langsam (WebDriver) Mittel
Developer Experience Sehr gut Sehr gut Mäßig Gut
Browser-Unterstützung Chrome, Firefox, Edge Alle inkl. Safari/WebKit Alle Browser Alle Browser
Parallele Ausführung Kostenpflichtig (Cloud) Kostenlos eingebaut Möglich (Selenium Grid) Möglich
Component Testing Ja (seit v10) Experimentell Nein Nein
Sprachen JavaScript/TypeScript JS/TS, Python, Java, C# Viele Sprachen JavaScript/TypeScript
Einstiegshürde Niedrig Niedrig Hoch Mittel

FAQ zu Cypress

Kann Cypress mehrere Browser-Tabs gleichzeitig steuern?
Nein, Cypress unterstützt keine Multi-Tab-Szenarien. Das ist eine bewusste Designentscheidung. Workflows, die mehrere Tabs erfordern, sollten durch direkte URL-Navigation oder API-Aufrufe simuliert werden. Für echte Multi-Tab-Tests ist Playwright besser geeignet.
Wie unterscheidet sich cy.get() von cy.find()?
cy.get() sucht global im gesamten DOM, während cy.find() innerhalb eines bereits selektierten Elements sucht. cy.find() ist also ein scoped Query, der nach einem cy.get() eingesetzt wird, um die Suche auf einen Teilbaum einzuschränken.
Was sind flaky Tests und wie verhindert Cypress sie?
Flaky Tests sind Tests, die mal bestehen und mal fehlschlagen, ohne dass sich der Code geändert hat – oft durch Timing-Probleme. Cypress wartet automatisch bis zu 4 Sekunden auf DOM-Elemente und Assertions. Mit cy.intercept().as() und cy.wait() lassen sich Netzwerkabhängigkeiten explizit abwarten.
Ist Cypress für das Testen von Mobile Apps geeignet?
Cypress ist ausschließlich für Webanwendungen im Browser ausgelegt. Für native Mobile Apps (iOS/Android) eignet sich Cypress nicht. Für mobile Web-Ansichten kann man jedoch die Browser-Fenstergröße auf typische Smartphone-Dimensionen setzen und so responsive Layouts testen.

Weiterführende Informationen finden sich in der offiziellen Cypress-Dokumentation.