Oberflächentests mit Playwright
ZielEinleitung
DieserOberflächentests Beitrag(UI-Tests) demonstriertstellen densicher, Einsatzdass vonWebanwendungen sich so verhalten, wie es Benutzer erwarten – unabhängig vom internen Code. Mit Playwright steht ein modernes, mächtiges Test-Framework zur Verfügung, das speziell für automatisiertedynamische UI-TestsWeb-UIs imentwickelt Rahmenwurde. einesDieser bestehendenArtikel SvelteKit-5-Projekts.stellt AlsPlaywright Anwendungsfallvor, dientzeigt seinen Einsatz in einem typischen Projekt mit SvelteKit und vergleicht es mit Alternativen wie Cypress und Selenium. Darüber hinaus werden praktische Strategien zur Teststruktur, Fehlervermeidung und Debugging vermittelt.
Was ist Playwright?
Playwright ist ein interaktivesvon Vier-Gewinnt-Spiel,Microsoft dasentwickeltes bereitsOpen-Source-Tool für UI-Tests von Webanwendungen. Tests werden in modularerechten KomponentenstrukturBrowserinstanzen umgesetzt(Chromium, wurde.Firefox, ImWebKit) Fokusausgeführt stehenund dieüber Teststrategie,DevTools-Protokolle diegesteuert. technischeBesonders Umsetzunghervorzuheben sowie bewährte Praktiken zur Testbarkeit.sind:
Tech-Stack
-
Framework:UnterstützungSvelteKitmehrerer5 (mit SSR, runes, TypeScript)Browser -
StylingAutomatische& UI:TailwindCSS, shadcn-svelte, Lucide IconsWarte-Mechanismen -
Testing:Netzwerk-Interception,PlaywrightScreenshot,(imTracing,e2e/-Verzeichnis)Debugging
Komponenten-Typischer und Logikstruktur
Das Spiel ist aufgeteilt in UI-Komponenten und eine von der Darstellung entkoppelte Spiel-Logik. Dies erleichtert das Testen, da Interaktionen klar über definierte Zustände und DOM-Selektoren nachvollziehbar sind.
Auszug der Komponentenstruktur:
|
|
|---|---|
|
|
|
|
|
|
|
|
|
|
Testansatz mit PlaywrightPlaywright-Workflow
Playwright wirderkennt fürstandardmäßig klassischealle End-to-End-TestsTestdateien genutzt.mit Zielden Endungen .spec.ts oder .test.ts. Es ist es,also dieüblich, wichtigstenTestdateien Interaktions-nach unddem ZustandsänderungenSchema xyz.spec.ts zu benennen. Dies ist keine Pflicht, aber eine empfohlene Konvention, da sie vom Test-Runner automatisch erkannt wird.
Ein vollständiger Testdurchlauf mit Playwright besteht in der UIRegel automatisiertaus zudrei prüfen. Die Tests befinden sich im Verzeichnis e2e/ und greifen über dedizierte data-test-Attribute auf UI-Elemente zu.Schritten:
-
BeispieleTestgetesteter Szenarien:schreiben-
InitialzustandDerdesTestBoardswird(allealsZellenJavaScript-leer)oder TypeScript-Datei ime2e/-Verzeichnis abgelegt. -
Abwechselndes Setzen von SpielsteinenBeispiel: Gewinnszenarien (z. B. vertikale Viererreihe)Anzeige des Gewinners
Beispiel: Vertikaler Siegtesttest('einzeigtSpieler gewinnt vertikal'Loginformular', async ({ page }) => {forawait page.goto('/login'); await expect(page.locator('form')).toBeVisible(); }); -
-
Test ausführen
-
Im Terminal ausführen:
npx playwright test -
Optional: Nur bestimmte Tests oder Dateien ausführen:
npx playwright test login.spec.ts
-
-
Ergebnisse analysieren
-
Playwright gibt im Terminal an, ob Tests bestanden oder fehlgeschlagen sind.
-
Bei Fehlern:
-
Trace-Dateien oder Screenshots analysieren
-
Optional:
--debugoder--trace onverwenden
Beispiel:
npx playwright show-trace trace.zip -
-
Dieser Workflow ist die Grundlage für einfache lokale Tests, funktioniert aber auch identisch in CI/CD-Umgebungen (letz. B. iGitHub Actions).
Automatische Warte-Mechanismen
Playwright wartet intelligent und automatisch auf Ereignisse im DOM. Das bedeutet: Wenn du z. B. ein Element anklickst oder eine Seite neu lädst, wartet Playwright so lange, bis die Seite bereit ist (Ladezustand, Sichtbarkeit, Interaktivität), ohne dass du explizit wait-Befehle schreiben musst. Das reduziert Fehler durch Timing-Probleme erheblich und macht Tests stabiler als bei älteren Tools wie Selenium.
Beispiel:
await page.click('text=Speichern'); // wartet intern, bis der Button sichtbar & klickbar ist
Netzwerk-Interception
Mit Playwright kannst du HTTP-Anfragen abfangen und manipulieren, bevor sie den Server erreichen oder nachdem sie empfangen wurden. Das ermöglicht z. B.:
-
das Mocken von Backend-Antworten
-
das Blockieren von Requests (z. B. zu externen APIs)
-
das Simulieren von Fehlerzuständen (z. B. 500er-Fehler)
Beispiel:
await page.route('**/api/user', route => 0;{
iroute.fulfill({ <status: 3;200, i++body: JSON.stringify({ name: 'Testuser' }) });
});
Screenshot
Playwright kann jederzeit einen Screenshot vom aktuellen Zustand der Seite aufnehmen – z. B. zur Fehlerdokumentation, zur visuellen Regression oder einfach als Debugging-Hilfe. Das ist besonders nützlich bei CI-Testläufen, wenn ein Test fehlschlägt.
Beispiel:
await page.screenshot({ path: 'screenshot.png', fullPage: true });
Tracing
Das Tracing-System von Playwright erstellt eine vollständige Aufzeichnung eines Testlaufs. Die generierte Datei (trace.zip) kann mit dem Trace Viewer analysiert werden. Dieser zeigt:
-
DOM-Zustände und Screenshots nach jeder Aktion
-
Klickpfade und Zeitverlauf
-
Netzwerkanfragen und -antworten
-
Konsolenausgaben und Fehler
Der Trace Viewer eignet sich ideal zum Debuggen, wenn Tests unerwartet fehlschlagen oder das Timing von UI-Interaktionen unklar ist.
Verwendung:
npx playwright test --trace on
npx playwright show-trace trace.zip
Das Tool ist interaktiv und CI-fähig – es gehört zu den zentralen Debugging-Funktionen von Playwright.
HTML-Report
Playwright enthält standardmäßig einen HTML-Reporter, der nach einem Testlauf einen interaktiven Bericht erzeugen kann.
Verwendung:
npx playwright test --reporter=html
npx playwright show-report
Dabei entsteht ein Verzeichnis playwright-report/, in dem die Testergebnisse als durchklickbarer HTML-Bericht gespeichert werden. Der Report enthält:
-
Status jedes Tests (✔ / ✖)
-
Detaillierte Fehlerbeschreibung (Stacktrace)
-
Screenshots bei Fehlern
-
Trace-Links, sofern aktiviert
Hinweis: Reporter lassen sich auch dauerhaft in playwright.config.ts setzen:
reporter: ['list', 'html']
Der HTML-Report eignet sich besonders gut für Reviews, Testprotokolle oder zur Weitergabe an Stakeholder.
Das Tracing-System von Playwright erstellt eine vollständige Aufzeichnung eines Testlaufs. Die generierte Datei (trace.zip) kann mit dem Trace Viewer analysiert werden. Dieser zeigt:
-
DOM-Zustände und Screenshots nach jeder Aktion
-
Klickpfade und Zeitverlauf
-
Netzwerkanfragen und -antworten
-
Konsolenausgaben und Fehler
Der Trace Viewer eignet sich ideal zum Debuggen, wenn Tests unerwartet fehlschlagen oder das Timing von UI-Interaktionen unklar ist.
Verwendung:
npx playwright test --trace on
npx playwright show-trace trace.zip
Das Tool ist interaktiv und CI-fähig – es gehört zu den zentralen Debugging-Funktionen von Playwright.
Das Tracing-System von Playwright erstellt einen kompletten „Film“ eines fehlgeschlagenen Testlaufs: Es enthält Informationen über:
-
alle DOM-Änderungen
-
Netzwerk-Anfragen
-
Konsolenmeldungen
-
Screenshots und Zeitleisten
Diese Daten können im Playwright Trace Viewer visuell nachvollzogen werden – ideal zum Debuggen komplexer Fehler in CI/CD.
npx playwright test --trace on
npx playwright show-trace trace.zip
Debugging
Zusätzlich zum Tracing bietet Playwright u. a.:
-
einen Inspector (GUI zum „Step-by-Step-Debuggen“ im Browser)
-
codegenzur Aufzeichnung von Tests -
Pause-Funktion für interaktives Testen (
page.pause())
Beispiel:
await page.pause(); // öffnet Debugger-Fenster mit DOM-Explorer
Integration in moderne Frameworks
Ein großer Pluspunkt ist die nahtlose Integration in moderne Toolchains. Bei der Installation eines SvelteKit-Projekts wird Playwright beispielsweise direkt mit angeboten. Es ist kein manueller Konfigurationsaufwand nötig.
Typische Teststruktur
Playwright-Konfigurationen werden in der Datei playwright.config.ts definiert. Besonders praktisch ist dabei die Möglichkeit, den lokalen Server automatisch zu starten, bevor die Tests ausgeführt werden:
import { defineConfig } from '@playwright/test';
export default defineConfig({
webServer: {
command: 'npm run build && npm run preview',
port: 4173
},
testDir: 'e2e'
});
-
commandstartet den lokalen Server, z. B. den SvelteKit-Preview-Modus. -
portlegt fest, wo der Test-Runner auf die Anwendung wartet. -
testDirgibt das Verzeichnis an, in dem die Tests gespeichert sind.
Diese automatische Startlogik ist besonders hilfreich für CI/CD, da kein separater Serverlauf erforderlich ist. Wer möchte, kann hier auch eigene Kommandos oder Ports verwenden – etwa um eine andere Umgebung zu testen oder eine API-Instanz parallel zu starten.
Playwright sucht standardmäßig in dem Ordner nach Tests, in dem sich deine playwright.config.ts befindet. Zudem erkennt es von sich aus alle Dateien mit den Endungen .spec.ts, .test.ts, .spec.js, .test.js.
Viele Framework-Vorlagen – z. B. SvelteKit – legen hierfür das Verzeichnis e2e/ an. Dies ist aber keine Vorgabe seitens Playwright, sondern eine Empfehlung, um Frontend- und End-to-End-Tests (E2E) strukturiert zu trennen.
Du kannst stattdessen auch beliebige andere Verzeichnisse nutzen (z. B. tests/, ui-tests/), solange sie sich im selben Verzeichnis wie playwright.config.ts befinden – oder du testDir in der Konfiguration entsprechend anpasst.
Nach dem Setup legt Playwright ein e2e/-Verzeichnis an (z. B. durch SvelteKit). Ein einfacher Test könnte so aussehen:
test('zeigt ein leeres Board mit 6x7 Zellen', async ({ page }) => {
await page.locator(goto('[data-test=column-0]/').click();
// red
await page.locator('[data-test=column-1]').click(); // yellow
}
await page.locator('[data-test=column-0]').click(); // red gewinnt
const winnerTextcells = await page.locator('[data-test=winner]test^=cell-]');
await expect(winnerText)cells).toHaveText(/red/)toHaveCount(6 * 7);
});
WeitereHäufig Testsverwendete überprüfen korrekte DOM-Zustände nach Klicks, das Wechseln des Spielers und die visuelle Darstellung des Ergebnisses.Befehle:
Projektstruktur (Ausschnitt)
├── e2e/
│ └── game.spec.ts # Playwright-Tests
├── src/
│ ├── lib/
│ │ ├── components/
│ │ │ ├── game/ # Spiel-Komponenten
│ │ │ └── ui/ # Generische UI-Komponenten
│ │ └── logic/
│ │ └── game.ts # Spiellogik
│ └── routes/
│ └── +page.svelte # Einstiegspunkt der App
├── playwright.config.ts # Playwright-Konfiguration
Best Practices für UI-Tests
-
Stabilepage.click(selector)Selektoren:–DurchgehendeKlickVerwendungaufvonein Element -
page.fill(selector, text)– Eingabe simulieren -
expect(locator).toHaveText()– Zustand prüfen -
page.screenshot()– Fehler sichtbar machen -
test.beforeEach()– Setup vor jedem Test
Nach dem Setup legt Playwright ein e2e/-Verzeichnis an. Ein einfacher Test könnte so aussehen:
test('zeigt ein leeres Board mit 6x7 Zellen', async ({ page }) => {
await page.goto('/');
const cells = await page.locator('[data-test-Attributentest^=cell-]');
zurawait gezieltenexpect(cells).toHaveCount(6 DOM-* 7);
});
Häufig verwendete Befehle:
-
page.click(selector)– Klick auf ein Element -
page.fill(selector, text)– Eingabe simulieren -
expect(locator).toHaveText()– Zustand prüfen -
page.screenshot()– Fehler sichtbar machen -
test.beforeEach()– Setup vor jedem Test
Vergleich: Playwright, Cypress, Selenium
| Merkmal | Playwright | Cypress | Selenium |
|---|---|---|---|
| Ausführungskontext | Außerhalb des Browsers über native DevTools-Protokolle | Im Browser | Extern via WebDriver |
| Sprachen | JS/TS, Python, C#, Java | Nur JS/TS | Viele (Java, Python, etc.) |
| Browser-Support | Chromium, Firefox, WebKit | Chromium-basiert, Firefox (beta) | Alle, inkl. IE |
| Multi-Tab, Multi-Window | Voll unterstützt | Eingeschränkt | Möglich, aber komplex |
| Netzwerk-Interception | Einfach via page.route() |
Eingeschränkt | Aufwendig |
| Debugging | Trace Viewer, Screenshots, CLI | Zeitreise im Browser, GUI | Schwerfällig |
| Setup-Aufwand | Minimal (bei modernen Frameworks) | Mittel | Hoch |
Geeignete Einsatzzwecke
Playwright eignet sich besonders für:
-
SPAs und dynamische Benutzeroberflächen
-
Tests in mehreren Browsern (inkl. WebKit)
-
CI/CD-Systeme mit paralleler Ausführung
-
Komplexe User-Flows mit mehreren Tabs oder Netzwerkaktionen
Weniger geeignet ist Playwright für klassische Unit-Tests oder Alt-Systeme mit Internet Explorer.
Erweiterte Konzepte & Best Practices
1. Locator-Strategien
Robuste Selektoren sind entscheidend:
-
data-test="..."als Attribut-Selektoren -
getByRole('button', { name: 'Senden' })für semantisch korrekte Auswahl -
CSS-Selektoren vermeiden
2. Teststruktur
-
TestbareIsolierteArchitektur:Tests:TrennungJedervonTestSpiellogikstartetundmitDarstellungbeforeEach()erhöhtindieeinerWiederverwendbarkeiteigenenund TestbarkeitUmgebung. -
VorhersehbarePageZustände:Object Pattern:EinsatzUI-Interaktionenvonauslagern,beforeEach()umzurdieInitialisierungTestsdeslesbarSpielzustandsund wartbar zu halten. -
AtomicFixtures:Testing:Wiederverwendbare Setup-Schritte intest.extend()kapseln.
3. Parallelisierung & Stabilität
Playwright führt Tests standardmäßig parallel aus, um die Laufzeit zu optimieren – lokal ebenso wie in CI/CD. Das bringt große Vorteile, erfordert aber, dass die Tests entsprechend gestaltet sind.
Grundprinzip:
Schreibe Tests so, als würden sie gleichzeitig laufen.
Das bedeutet:
-
Jeder Test
prüftsollteeineunabhängigisoliertevonFunktionalitätanderen(SingleTestsResponsibility)funktionieren. -
LesbareEsTests:darfNamenkeine geteilten Daten, Zustände oder Seiteneffekte zwischen Tests geben. -
Testdaten sollten innerhalb des Tests erzeugt und
Kommentaregenutztbeschreibenwerden.das -
Falls Setup nötig ist: mit
beforeEach()arbeiten, nichtdiemitImplementierunggeteilten Variablen.
Typisches Problem: Zwei Tests nutzen denselben Nutzer oder Datensatz – je nach Reihenfolge oder Timing schlägt einer davon fehl. Das wirkt dann wie ein „flaky test“ – ist aber ein Architekturproblem.
Hilfreiche Optionen in der Konfiguration oder beim Aufruf:
-
--shard=1/3– teilt die Tests in gleichmäßige Gruppen für parallele Ausführung -
--retries=2– Wiederholung fehlgeschlagener Tests (z. B. bei Netzwerkaussetzern) -
--workers=4– legt explizit die Anzahl paralleler Worker fest
Fazit: Parallele Tests sparen Zeit – aber nur, wenn sie wirklich unabhängig voneinander sind. Genau das sollte beim Schreiben konsequent beachtet werden.
-
--shard,--retries,--workersnutzen für schnelle, stabile CI-Runs. -
Traces (
--trace on) für Fehleranalyse aktivieren.
4. Netzwerkinterception & Mocking
-
Mit
page.route()lassen sich APIs mocken oder blockieren. -
Reduziert Abhängigkeiten zu externen Diensten und beschleunigt die Tests.
5. Umfang planen statt alles testen
E2E-Tests sollten sich auf kritische Workflows konzentrieren:
-
Registrierung & Login
-
Kernfunktionalitäten (z. B. Spielzug, Bestellung, Zahlung)
-
Fehlermeldungen und Berechtigungslogik
Weiterführende RessourcenLinks
Fazit
Durch die Integration von Playwright lassen sich komplexe UI-Interaktionen in SvelteKit-Anwendungen automatisiert und zuverlässig testen. Die klare Trennung von Logik und Oberfläche, kombiniert mit stabilen Selektoren, bildet die Grundlage für robuste und wartbare UI-Tests – sowohl in Lernkontexten als auch in produktionsnahen Szenarien.