Workflow für visuelle Playwright-Tests

Playwright Visual Testing, das in CI stabil bleibt

Kurz erklärt

Playwright vergleicht mit `toHaveScreenshot()` eine aktuelle Browseraufnahme mit einer gespeicherten Baseline. Stabile Tests fixieren Browserprojekt, Viewport, Sprache, Zeitzone und Daten und warten danach auf einen sichtbaren Bereitschaftszustand. CI muss Baseline, aktuelle Aufnahme, Diff und Bericht speichern, damit der Fehler überprüfbar bleibt.

Geprüft von RenderLog ProduktteamAktualisiert
RenderLog-Laufdetail mit Baseline, aktueller Aufnahme, visuellem Diff und Review-Aktionen

Eine visuelle Assertion ist in wenigen Zeilen hinzugefügt und kann eine Woche später zufällig fehlschlagen. Meist liegt es nicht am Bildvergleich. Die Seite wurde mit einer anderen Schrift, einem Live-Preis, einem anderen Animationsbild, einem abweichenden Cookie-Zustand oder einer neuen Browserversion aufgenommen. Visual Testing macht diese verborgenen Variablen sichtbar und zwingt den Test, sie bewusst zu kontrollieren.

Der folgende Ablauf beginnt mit einer einzigen Preisseite und wächst erst, wenn deren Fehler verständlich sind. Er trennt außerdem zwei Verantwortungen: Der Repository-Test blockiert riskante Codeänderungen, während RenderLog eine veröffentlichte oder geplante Seite für Produkt, Marketing oder einen Kunden sichtbar macht, ohne dass diese Personen CI-Archive durchsuchen müssen.

Den Browserzustand vor der ersten Baseline festlegen

Verwenden Sie benannte Playwright-Projekte statt des gerade installierten Entwicklerbrowsers. Setzen Sie Viewport, Sprache, Zeitzone und Farbschema ausdrücklich. Browser und Schriften sollten in CI aus derselben gesperrten Konfiguration stammen, mit der die Baseline freigegeben wurde. Eine auf macOS erzeugte Aufnahme darf nicht stillschweigend zum erwarteten Bild für einen Linux-Runner mit anderer Schriftrasterung werden.

Legen Sie fest, wo Baselines leben. Im Repository sind Änderungen im Pull Request sichtbar und für eine überschaubare Suite gut handhabbar. Ein separater Artefaktspeicher kann eine große Matrix aufnehmen, braucht aber Versionierung und Zugriffsregeln. In beiden Fällen muss der Test genau die Baseline seines Browserprojekts, Viewports und Zustands abrufen und nicht einfach die zuletzt hochgeladene Datei.

  • Ein benanntes Projekt je wirklich relevantem Rendering-Ziel verwenden.
  • Browser- und Schriftinstallation in CI reproduzierbar halten.
  • Baselines nach Projekt, Viewport und erwartetem Zustand trennen.
  • Keine gemeinsame Baseline für sichtbar unterschiedlich rendernde Browser nutzen.

Die Bereitschaft auf der Seite sichtbar machen

`networkidle` garantiert keine fertige Seite. Ein Timer kann das DOM nach dem Netzwerkstillstand ändern und eine Schrift kann später wechseln. Warten Sie auf eine Überschrift, eine vollständige Kartengruppe oder einen eindeutigen Anwendungszustand, den auch ein Nutzer erkennen würde. Ein testbezogenes Ready-Merkmal sollte abgeschlossenes Rendering bedeuten und nicht bloß, dass JavaScript eine Komponente eingebunden hat.

Vermeiden Sie feste Wartezeiten. Zwei Sekunden sind langsam, wenn die Seite nach 200 Millisekunden bereit ist, und unzuverlässig, wenn CI 2,2 Sekunden braucht. Web-Assertions wiederholen die Prüfung bis zum sichtbaren Zustand und nennen einen verständlichen Grund. Der Screenshot sollte erst danach entstehen, damit eine fehlende Karte als fehlende Karte gemeldet wird und nicht als rätselhafter Full-Page-Diff.

  • Auf Überschrift, stabile Kartengruppe oder ein echtes Ready-Merkmal warten.
  • Kritischen Text oder Zustand vor der Aufnahme bestätigen.
  • Animationen über Playwright und Testeinstellungen des Produkts deaktivieren.
  • Einen Timeout als Lauffehler und nicht als visuelle Änderung behandeln.

Daten kontrollieren, ohne das geprüfte Verhalten zu entfernen

Simulieren Sie die Preisantwort, wenn der Test das Layout prüft und Live-Preise unabhängig wechseln. Tun Sie es nicht, wenn ein falscher Produktionspreis gefunden werden soll. Bereiten Sie ein Konto vor, wenn der angemeldete Zustand relevant ist. Frieren Sie die Uhr für eine beiläufige relative Zeit ein, lassen Sie das reale Datum aber sichtbar, wenn ein Release-Banner geprüft wird.

Die Regel lautet: Stabilisieren Sie Eingaben außerhalb der Entscheidung und behalten Sie Eingaben innerhalb der Entscheidung real. Dokumentieren Sie diese Grenze im Testnamen und in einem kurzen Kommentar. Ein Reviewer sollte erkennen, ob `pricing.png` einen Live-Preis belegt, ein Layout mit Fixture-Daten oder lediglich das Browser-Rendering einer statischen Route.

  • Externe oder Live-Daten nur simulieren, wenn deren Wert nicht geprüft wird.
  • Fixtures so benennen, dass die Grenze des Nachweises erkennbar ist.
  • Unabhängige Widgets eng maskieren statt große Bereiche auszublenden.
  • Anmelde- und Consent-Zustand ausdrücklich setzen.

Toleranzen erst nach echten Fehlschlägen festlegen

Beginnen Sie mit dem strengen Playwright-Vergleich auf dem festgelegten Runner. Wiederholen Sie denselben Test ohne Seitenänderung. Schlägt er fehl, prüfen Sie die Pixel, bevor Sie `maxDiffPixels` oder `maxDiffPixelRatio` verändern. Schriftkanten deuten auf die Umgebung, ein Cursor oder Übergang auf den Seitenzustand und ein großer bewegter Block auf instabile Daten oder eine Komponente, die einen eigenen Check braucht.

Wählen Sie die kleinste Toleranz, die bekannte Rendering-Schwankungen auffängt. Jede Änderung daran gehört ins Code-Review und sollte mit dem konkreten Beispiel begründet werden. Ein Verhältnis, das für eine lange Seite klein wirkt, kann einen kompletten Button verbergen. Für ein kleines kritisches Element ist eine gezielte Komponentenaufnahme besser, während der Full-Page-Screenshot den Layoutkontext behält.

  • Unveränderte Tests mehrfach ausführen, bevor eine Toleranz gewählt wird.
  • Deterministische Ursachen beseitigen, bevor Pixelrauschen akzeptiert wird.
  • Änderungen an Grenzwerten wie Produktionscode prüfen.
  • Für kleine risikoreiche Komponenten fokussierte Aufnahmen verwenden.

Jedes Fehlerartefakt behalten, auch wenn CI den Merge stoppt

Ein CI-Fehler ohne tatsächliches, erwartetes und Diff-Bild zwingt den Reviewer zur lokalen Wiederholung. Laden Sie den Playwright-Bericht und das Verzeichnis `test-results` bei Erfolg und Fehler hoch. Die Aufbewahrungszeit muss für den normalen Review-Zyklus reichen. Projekt- und Testname gehören in den Artefaktpfad, damit Desktop- und Mobilresultate nicht verwechselt werden.

Der Bericht ist ein Beleg, aber nicht die einzige Aufzeichnung einer akzeptierten Änderung. Eine neue Baseline sollte in einem eigenen Commit ohne fremde Produktänderungen landen. Das Diff erklärt, warum der Test scheiterte, und die Baseline-Änderung zeigt, was das Team akzeptiert hat. Diese Trennung macht eine spätere Regression wesentlich leichter nachvollziehbar.

  • HTML-Bericht und rohe Bildartefakte bei Fehlern hochladen.
  • Artefakte nach Test und Browserprojekt benennen.
  • Sie lange genug für den üblichen Review-Zyklus aufbewahren.
  • Baseline-Updates von Produktänderungen trennen.

Veröffentlichte Seiten dort übergeben, wo ihr Besitzer arbeitet

Der Repository-Test ist richtig, wenn Entwickler den Zustand besitzen und ein Fehler Code blockieren soll. Preis-, Kampagnen-, Dokumentations- und Kundenseiten ändern sich jedoch oft außerhalb eines einzelnen Pull Requests. Ihr Besitzer sitzt vielleicht im Produkt, Marketing oder in einer Agentur. Diese Person in ein CI-Archiv zu schicken schafft Reibung, aber noch keine klare Verantwortung.

Belassen Sie Komponenten und Merge-Gates in Playwright und prüfen Sie die veröffentlichte URL nach dem Release per Zeitplan oder API in RenderLog. Dort sieht der Besitzer Baseline, aktuelles Bild, Diff und Verlauf und kann eine Änderung freigeben. Kopieren Sie denselben Test nicht blind: Definieren Sie, welche Oberfläche Code blockiert und welche den tatsächlichen Zustand der veröffentlichten Seite bestätigt.

  • Playwright für entwicklerverantwortete Merge-Entscheidungen einsetzen.
  • RenderLog für den Zustand der veröffentlichten Seite verwenden.
  • Für jede Ergebnisart einen namentlichen Reviewer festlegen.
  • Keine identischen Aufnahmen ohne unterschiedliche Folgeentscheidung doppeln.

Einen fehlgeschlagenen Playwright-Screenshot einordnen

Aktualisieren Sie nicht sofort die Baseline. Form des Diffs und Laufzustand zeigen meist, ob Umgebung, Seite oder eine erwartete Änderung die Ursache ist.

BeobachtungWahrscheinliche UrsachePrüfenNächster Schritt
Ränder um TextSchrift oder BrowserImage, Browserversion und FontsUmgebung angleichen, nicht Toleranz erhöhen
Großer Block verschobenDaten, Zustand oder LayoutAPI-Antwort, Viewport und BereitschaftZustand korrigieren oder Regression untersuchen
Leere SeiteLauffehlerAntwort, Protokolle und TimeoutLauf reparieren, Baseline nicht ändern
Bekannte LayoutänderungErwartete ProduktänderungPull Request, Entwurf und NachbarbereicheGezielte neue Baseline freigeben

Grundkonfiguration für Screenshots und CI-Artefakte

Die Beispiele zeigen Vergleich, Browserprojekt, Preisprüfung und Artefaktübergabe. Ersetzen Sie Selektoren und Daten durch den echten Produktzustand und setzen Sie Grenzwerte erst nach Wiederholungen im selben CI-System.

playwright.config.ts

import { defineConfig, devices } from "@playwright/test";

export default defineConfig({
  testDir: "./tests/visual",
  expect: {
    toHaveScreenshot: {
      animations: "disabled",
      caret: "hide",
      maxDiffPixelRatio: 0.001
    }
  },
  use: {
    locale: "en-US",
    timezoneId: "UTC",
    colorScheme: "light"
  },
  projects: [
    { name: "desktop-chromium", use: { ...devices["Desktop Chrome"] } },
    { name: "mobile-chromium", use: { ...devices["Pixel 7"] } }
  ]
});

tests/visual/pricing.spec.ts

import { test, expect } from "@playwright/test";

test("pricing page", async ({ page }) => {
  await page.route("**/api/prices", async route => {
    await route.fulfill({ json: { plan: "Pro", price: 49 } });
  });
  await page.goto("https://example.com/pricing", { waitUntil: "networkidle" });
  await page.getByRole("heading", { name: "Pricing" }).waitFor();
  await expect(page).toHaveScreenshot("pricing.png", {
    fullPage: true,
    mask: [page.getByTestId("live-chat-launcher")]
  });
});

CI artifact handoff

npx playwright test --project=desktop-chromium
# Upload test-results/ and playwright-report/ even when the job fails.
# Send the public page to RenderLog when review must continue outside the repository.

Offizielle Dokumentation zur Implementierung

Playwright entwickelt Syntax und Funktionen weiter. Prüfen Sie die Details in den offiziellen Quellen. Die RenderLog-API ist nur für den getrennten Review der veröffentlichten Seite erforderlich.

Den Workflow fortsetzen

Eine Post-Release-Aufnahme zum vorhandenen Test ergänzen

Belassen Sie den Komponentencheck in Playwright. Starten Sie nach dem Deployment einen gespeicherten Check der öffentlichen Seite in RenderLog und lassen Sie den Produktbesitzer die Änderung mit vollständiger Historie prüfen.

RenderLog-Check erstellen