UI-Tests mit Playwright

Sven Hennessen

In der modernen Softwareentwicklung ist automatisiertes Testen ein zentraler Baustein, um die Qualität und Zuverlässigkeit von Anwendungen sicherzustellen. In diesem Beitrag gehe ich als Softwarearchitekt und Experte für Tests und Softwarequalität auf UI-Tests mit Playwright ein – ein mächtiges Werkzeug, das nicht nur bei End-to-End (E2E) Tests überzeugt, sondern auch flexibel in Kombination mit Mocking-Strategien und containerisierten Testumgebungen eingesetzt werden kann.

Warum Playwright?

Playwright hat sich in den letzten Jahren als eine der führenden Frameworks für Browser-Automatisierung etabliert. Mit seiner Unterstützung für verschiedene Browser-Engines (Chromium, Firefox, WebKit) ermöglicht es, Anwendungen in realen Browser-Umgebungen zu testen. Dadurch erhalten Entwickler und Tester ein authentisches Feedback zu Benutzerinteraktionen und -erlebnissen.

Tests gegen echte Systeme

Ein großer Vorteil von Playwright ist die Möglichkeit, Tests gegen echte Systeme auszuführen – beispielsweise in einer Staging-Umgebung. Dies bietet den enormen Vorteil, dass die Test-Szenarien möglichst realitätsnah sind. Allerdings ist dabei zu beachten:

  • Stabile Testdaten: Damit Tests zuverlässig ablaufen, müssen die Daten in der Testumgebung konsistent und vorhersagbar sein. Instabile oder sich ändernde Testdaten können zu flüchtigen Fehlern (Flakiness) führen.
  • Reproduzierbarkeit des Datenzustandes: Es ist entscheidend, dass der Zustand der Testdaten nach jedem Testlauf wiederhergestellt werden kann. Nur so lassen sich Probleme effizient debuggen und die Testausführung standardisieren.

Durch diese Voraussetzungen kann Playwright Tests in echten Systemen mit hohem Vertrauensgrad durchführen, was insbesondere in der späten Entwicklungsphase oder im Release-Candidate-Zyklus sinnvoll ist.

Isolierte UI-Tests mit gemockten API-Calls

Nicht selten ist es aber nicht immer sinnvoll – oder gar möglich – Tests gegen ein komplettes System auszuführen. In solchen Fällen bietet es sich an, reine UI-Tests durchzuführen, bei denen die API-Calls gemockt werden. Die Vorteile liegen auf der Hand:

  • Schnellere Ausführung: Da externe Services nicht angesteuert werden, können Tests schneller abgeschlossen werden.
  • Erhöhte Stabilität: Durch das Mocking werden externe Einflussfaktoren wie Netzwerkprobleme oder instabile Backends eliminiert.
  • Fokus auf das Frontend: Entwickler können sich gezielt auf die Benutzeroberfläche und das UI-Verhalten konzentrieren, ohne sich um das Zusammenspiel mit dem Backend zu kümmern.

Die Entscheidung für gemockte API-Calls sollte jedoch nicht als Allheilmittel verstanden werden, da so wichtige Integrationsaspekte zwischen UI und Backend nicht getestet werden.

Auch muss sich ein Team bei dieser Testvariante klar entschieden, wo die grenze zwischen UI Tests mit gemockten API calls und Unit/Component-Tests mit Frameworks wie Jest und React Testing Library liegen um Redundanz und damit unnötige Mehrarbeit ohne Mehrwert zu vermeiden.

Integration mit Testcontainers und DockerComposeEnvironment

Eine weitere interessante Möglichkeit, Playwright unabhängig von einem echten System auszuführen, ist die Nutzung von containerisierten Testumgebungen. Mittels Testcontainers & DockerComposeEnvironment (Dokumentation) lassen sich komplexe Systeme in isolierten Containern simulieren. Vorteile dieser Herangehensweise:

  • Reproduzierbare Umgebungen: Container - beispielsweise ein Service der eine REST-Api für das UI zur Verfügung stellt, und seine Datenbank - können in einem definierten Zustand gestartet werden, wodurch Testdaten und Konfigurationen exakt reproduziert werden können.
  • Isolierung von Abhängigkeiten: Externe Services werden innerhalb der Containerlandschaft kontrolliert und können gezielt ein- und ausgeschaltet werden.
  • Kontinuierliche Integration: Durch die Containerisierung wird es leichter, UI-Tests in automatisierte CI/CD-Pipelines zu integrieren.

Diese Strategie ermöglicht es, die Vorteile von echten Systemtests (wie Integration und realitätsnahes Verhalten) mit der Kontrolle und Stabilität isolierter Testumgebungen zu kombinieren. Hier ist aber ebenfalls auf einen sauberen Bootstrap und Teardown der Tests zu achten um diese in Umgebungen wie CICD-Pipelines zuverlässig ausführbar zu machen.

Das kann beispielsweise beim Bootstrap am Beispiel einer Postgres-Datenbank so aussehen:

const environment = await new DockerComposeEnvironment("./", "docker-compose.yml").up();
const container = environment.getContainer('postgres');
const host = container.getHost();
const port = container.getMappedPort(databasePort);
process.env.URI_DATABASE = `postgresql://myUser:myPassword@${host}:${port}/my-service-db`;

Der Verbindungsstring kann dann in Form der definierten Umgebungsvariable genutzt werden um den Container eines API-Services zu konfigurieren. Das gleiche Vorgehen lässt sich beispielsweise für die URL anwenden, die ein UI benötigt um sich gegen die API zu verbinden, usw.

Die Testpyramide und die Herausforderungen von End-to-End Tests

Im Kontext der Testpyramide wird häufig empfohlen, den Schwerpunkt auf Unit- und Integrationstests zu legen, da diese in der Regel schneller, robuster und wartbarer sind. End-to-End Tests – zu denen auch UI-Tests mit Playwright zählen – ergänzen diese, um den Gesamtfluss der Anwendung sicherzustellen. Dabei gilt es folgende Risiken und Herausforderungen zu beachten:

  • Hoher Aufwand und Wartungskosten: End-to-End Tests sind oft komplexer und anfälliger für Veränderungen im System. Jeder kleine UI- oder Backend-Änderung kann zu fehlschlagenden Tests führen, die zeitaufwendig angepasst werden müssen.
  • Langsame Ausführung: Aufgrund der Vielzahl an Interaktionen und der Notwendigkeit, komplette Systeme zu starten, können E2E Tests deutlich langsamer sein als Unit-Tests.
  • Flakiness: Selbst bei stabilen Testdaten können Netzwerkbedingungen, asynchrone Prozesse oder externe Abhängigkeiten zu intermittierenden Testfehlern führen, was das Vertrauen in das Test-Framework mindern kann.

Daher ist es ratsam, E2E Tests sparsam und gezielt einzusetzen – als „Smoketests“ oder für kritische Pfade, während der Großteil der Testabdeckung durch schnellere und deterministische Unit- und Integrationstests erfolgt.

Fazit

Playwright bietet als Tool für UI-Tests zahlreiche Möglichkeiten, um die Qualität von Webanwendungen sicherzustellen – sei es durch Tests in echten Systemen wie Staging-Umgebungen, bei denen stabile Testdaten und ein reproduzierbarer Datenzustand Voraussetzung sind, oder durch isolierte Tests mit gemockten API-Calls. Zusätzlich ermöglichen die Integration von Testcontainers und DockerComposeEnvironment eine flexible und kontrollierte Testumgebung.

Wichtig ist jedoch, den hohen Aufwand und die potenzielle Flakiness von End-to-End Tests im Blick zu behalten und diese im Kontext der Testpyramide sinnvoll einzusetzen. Durch eine ausgewogene Teststrategie, die die Stärken verschiedener Testarten kombiniert, können robuste und wartbare Test-Suites erstellt werden, die langfristig zur Softwarequalität beitragen.

Keinen Artikel mehr verpassen

Kein Spam. Nur relevante News über und von uns. Jederzeit abbestellbar.