Zurück zur Startseite

Stabilisierung von Playwright-Tests in CI

Der Artikel beschreibt die Methodik zur Stabilisierung von Playwright-Tests in CI unter Verwendung von Dependency Projects, web-first asserts und geeigneter Locator-Auswahl. Beispiele für Konfiguration und Code für Enterprise-Projekte werden bereitgestellt.

Playwright: Flakes in CI mit Dependency Projects eliminieren
Advertisement 728x90

Playwright-Tests in CI stabilisieren: Abhängigkeitsprojekte und webfirst-Assertionen

Verkettete Abhängigkeiten in Playwright verhindern die Ausführung von Tests in instabilen Umgebungen und sparen CI-Ressourcen sowie falsch-positive Ergebnisse.

Zunächst erfolgt die Authentifizierung über API mit Speicherzustandspersistenz. Anschließend prüft ein Healthcheck die Erreichbarkeit der API. Erst danach werden die Haupt-UI-Tests ausgeführt.

Vorteile gegenüber globalSetup:

Google AdInline article slot
  • Vollständige Traces mit Netzwerkanfragen, Screenshots und Konsolenprotokollen.
  • Fail-fast-Verhalten: Wenn die Einrichtung fehlschlägt, werden abhängige Projekte sofort angehalten.
  • Isolation: Individuelle Phasen können mit npx playwright test --project=auth-setup getestet werden.

Konfiguration in playwright.config.ts:

export default defineConfig({
  projects: [
    {
      name: 'auth-setup',
      testMatch: /.*\.auth\.setup\.ts/,
    },
    {
      name: 'healthcheck',
      testMatch: /.*\.health\.setup\.ts/,
      dependencies: ['auth-setup'],
    },
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
      dependencies: ['healthcheck'],
    },
  ],
});

API-basierte Authentifizierung reduziert die Einrichtungszeit drastisch: Eine POST-Anfrage dauert 50–100 ms gegenüber 2–5 Sekunden bei UI-Login.

Beispiel für auth-setup-Test:

Google AdInline article slot
test('setup', async ({ request }) => {
  await request.post('/api/login', { data: { user, pass } });
  await request.storageState({ path: '.auth/user.json' });
});

Abhängigkeitsgraphen beseitigen Rennbedingungen bei parallelen Testläufen.

Lokatoren gezielt wählen

Die Auswahl der Lokatoren beeinflusst direkt die Robustheit gegenüber UI-Änderungen. Trennen Sie sie nach Zweck: Verwenden Sie getByTestId für Aktionen und getByRole oder getByLabel für Assertionen.

Best Practices:

Google AdInline article slot
  • Aktionen (Klick, Eingabe): page.getByTestId('add-to-cart-button').click() – unabhängig von Text oder Styling.
  • Text-/Status-Validierung: expect(page.getByRole('heading')).toHaveText('Mein Konto').
  • Eingabefelder: page.getByLabel('E-Mail').fill('[email protected]').
  • Zähler: expect(locator).toHaveText('3').

CSS-Selektoren sollten nur als Rückfall dienen. Die Schulung Ihres Teams im richtigen Umgang mit Lokatoren zahlt sich im großen Maßstab um das Zehnfache aus.

Web-first-Assertionen vs. Flakiness

Snapshot-Prüfungen wie await loc.isVisible() sind anfällig für Rennbedingungen. Web-first-Assertionen mit Polling bieten Stabilität.

Vergleich von Assertionen:

| Prüfung | Snapshot (kein Warten) | Web-first (Polling) |

|-------|--------------------|---------------------|

| Sichtbarkeit | await loc.isVisible() | expect(loc).toBeVisible() |

| Text | await loc.textContent() | expect(loc).toHaveText('Text') |

| Anzahl | await loc.count() | expect(loc).toHaveCount(3) |

| Attribut | await loc.getAttribute('href') | expect(loc).toHaveAttribute('href', '/pfad') |

| Checkbox | await loc.isChecked() | expect(loc).toBeChecked() |

| Zustand | await loc.isEnabled() | expect(loc).toBeEnabled() |

Das Polling wiederholt alle 100 ms, bis der Timeout erreicht ist, und ignoriert temporäre UI-Flicker.

Hydratation und force: true

Hydratationsmismatch tritt in SSR/SSG-Anwendungen auf, wenn serverseitiger Markup existiert, aber JavaScript-Handler noch nicht angehängt sind.

Warten auf Hydratations-Marker:

  • await page.waitForSelector('.hydrated', { state: 'attached' })
  • await expect(page.locator('#global-loader')).toBeHidden()

force: true deaktiviert die Aktivitätsprüfungen (sichtbar, stabil, aktiv, Ereignisempfang), verwandelt den Test in einen reinen DOM-Skript. Nur selten verwenden und stets mit Kommentar versehen – ideal für Edge-Cases wie Datei-Uploads.

Wichtige Erkenntnisse

  • Abhängigkeitsprojekte bauen einen Abhängigkeitsgraphen auf, verhindern, dass Tests auf nicht bereiten Umgebungen laufen.
  • Web-first-Assertionen mit Polling beseitigen 80 % der Flakiness durch Rennbedingungen.
  • Trennung der Lokatoren nach Rolle erhöht die Robustheit gegenüber UI-Refactoring.
  • API-Authentifizierung beschleunigt die Einrichtung um das 20- bis 50-fache gegenüber UI-Login.
  • Traces statt Screenshots liefern den vollen Kontext für Fehler im CI.

— Editorial Team

Advertisement 728x90

Weiterlesen