Rafał Podraza
Zurück zum Blog

6. Juli 2026

Wie führt man Playwright-Tests in GitHub Actions aus?

Automatisierte Tests zu schreiben ist eine Sache. Der eigentliche Mehrwert entsteht aber erst dann, wenn diese Tests automatisch nach jeder Änderung im Code ausgeführt werden. In diesem Beitrag zeige ich, wie man Playwright mit GitHub Actions verbindet und End-to-End-Tests im CI/CD-Prozess ausführt.

Wie führt man Playwright-Tests in GitHub Actions aus?

Wenn du automatisierte Tests mit Playwright schreibst, kommst du ziemlich schnell an den Punkt, an dem es nicht mehr ausreicht, die Tests nur lokal auszuführen.

Am Anfang sieht alles noch ganz einfach aus.

Du startest die Tests auf deinem eigenen Rechner, alles ist grün, die Tests laufen durch und es sieht so aus, als wäre alles erledigt. Das Problem kommt meistens erst später. Jemand ändert etwas in der Anwendung, erstellt einen Pull Request oder deployed eine neue Version, und plötzlich funktioniert ein wichtiger Prozess nicht mehr.

Genau deshalb sollten automatisierte Tests nicht nur lokal, sondern auch im CI/CD-Prozess ausgeführt werden.

In diesem Beitrag zeige ich dir, wie du Playwright-Tests in GitHub Actions starten kannst.

Warum Playwright-Tests in GitHub Actions ausführen?

Ganz einfach: Damit du nicht nach jeder Änderung alles manuell prüfen musst.

GitHub Actions kann Tests automatisch nach einem Push ins Repository oder nach dem Erstellen eines Pull Requests ausführen. Dadurch lässt sich schneller erkennen, ob eine Änderung zum Beispiel den Login, den Warenkorb, ein Kontaktformular, eine Zahlung oder einen anderen wichtigen Prozess in der Anwendung beschädigt hat.

In der Praxis sieht das so aus:

  1. Ein Entwickler nimmt eine Änderung am Code vor.
  2. Die Änderung wird auf GitHub hochgeladen.
  3. GitHub Actions startet den Workflow.
  4. Die Abhängigkeiten werden installiert.
  5. Die Playwright-Tests werden ausgeführt.
  6. Am Ende sieht man, ob die Tests erfolgreich waren oder ob etwas fehlgeschlagen ist.

Und genau an dieser Stelle beginnt Automatisierung wirklich sinnvoll zu werden.

Die Tests sind dann nicht mehr nur etwas, das ein Tester gelegentlich lokal auf seinem Rechner startet. Sie werden zu einem festen Bestandteil des Entwicklungs- und Auslieferungsprozesses.

Beispielprojekt mit Playwright

Ich gehe davon aus, dass du bereits ein Projekt mit Playwright hast.

Falls nicht, kannst du ein neues Projekt mit folgendem Befehl erstellen:

npm init playwright@latest

Nach der Installation solltest du im Projekt unter anderem folgende Dateien und Ordner sehen:

tests/
playwright.config.ts
package.json

Lokal kannst du die Tests mit folgendem Befehl ausführen:

npx playwright test

Wenn lokal alles funktioniert, können wir mit der Konfiguration von GitHub Actions weitermachen.

Wo wird die GitHub-Actions-Konfiguration hinzugefügt?

Erstelle in deinem Repository den folgenden Ordner:

.github/workflows

Darin legst du eine Datei an, zum Beispiel:

playwright.yml

Der vollständige Pfad sieht dann so aus:

.github/workflows/playwright.yml

In dieser Datei beschreiben wir, wann und wie unsere Tests ausgeführt werden sollen.

Einfacher Workflow für Playwright

Für den Anfang reicht eine einfache Konfiguration:

name: Playwright Tests

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  test:
    name: Run Playwright tests
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 22

      - name: Install dependencies
        run: npm ci

      - name: Install Playwright browsers
        run: npx playwright install --with-deps

      - name: Run Playwright tests
        run: npx playwright test

      - name: Upload Playwright report
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: playwright-report
          path: playwright-report/
          retention-days: 7

Das ist bereits eine funktionierende Grundlage.

Nachdem du diese Datei zum Repository hinzugefügt hast, startet GitHub Actions die Tests nach einem Push in den Branch main sowie bei Pull Requests in Richtung main.

Was machen die einzelnen Schritte?

Gehen wir diese Datei kurz durch, weil YAML am Anfang etwas ungewohnt aussehen kann.

name: Playwright Tests

Das ist der Name des Workflows. Er wird später im Tab „Actions” auf GitHub angezeigt.

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

Hier definieren wir, wann der Workflow gestartet werden soll.

In diesem Fall werden die Tests nach einem Push auf main und bei Pull Requests nach main ausgeführt.

runs-on: ubuntu-latest

Dieser Abschnitt bedeutet, dass der Job auf einer Ubuntu-Maschine ausgeführt wird. Für die meisten Playwright-Tests ist das vollkommen ausreichend.

uses: actions/checkout@v4

Dieser Schritt lädt den Code des Repositorys in die Umgebung von GitHub Actions.

uses: actions/setup-node@v4

Hier wird Node.js installiert. Im Beispiel verwende ich Version 22.

run: npm ci

Dieser Befehl installiert die Projektabhängigkeiten auf Basis der Datei package-lock.json.

In CI-Umgebungen ist npm ci meistens die bessere Wahl als npm install, weil es vorhersehbarer ist und besser zu automatisierten Umgebungen passt.

run: npx playwright install --with-deps

Dieser Schritt installiert die Browser und Systemabhängigkeiten, die Playwright benötigt.

Das ist wichtig, weil wir auf einer frischen Maschine in GitHub Actions nicht davon ausgehen können, dass bereits alles vorhanden ist.

run: npx playwright test

Hier werden die Tests gestartet.

if: always()

Dieser Teil beim Hochladen des Reports bedeutet, dass der Report auch dann gespeichert wird, wenn die Tests fehlschlagen.

Und das ist sehr wichtig.

Denn wenn Tests fehlschlagen, brauchen wir den Report, Screenshots oder Traces meistens am dringendsten.

HTML-Report aus den Tests

Playwright kann standardmäßig einen HTML-Report erzeugen. Nach der Ausführung der Tests kann dieser Report als Artefakt in GitHub Actions gespeichert werden.

In unserem Workflow ist dafür dieser Abschnitt zuständig:

- name: Upload Playwright report
  uses: actions/upload-artifact@v4
  if: always()
  with:
    name: playwright-report
    path: playwright-report/
    retention-days: 7

Nach Abschluss des Workflows kannst du in GitHub Actions den konkreten Run öffnen und den Report im Bereich der Artefakte herunterladen.

Das hilft sehr bei der Fehleranalyse.

Statt zu raten, was passiert ist, kannst du prüfen, welcher Test fehlgeschlagen ist, an welchem Schritt das Problem aufgetreten ist und was der Browser tatsächlich gesehen hat.

Trace Viewer als Hilfe bei schwierigen Fehlern

Eine Funktion, die ich an Playwright besonders mag, ist der Trace Viewer.

Wenn ein Test fehlschlägt, kann man mit dem Trace die Ausführung Schritt für Schritt analysieren. Man sieht Aktionen, Assertions, Screenshots, Logs, Requests und Responses.

In der Praxis ist das deutlich angenehmer, als nur eine Fehlermeldung in der Konsole zu lesen.

In der Datei playwright.config.ts lohnt sich zum Beispiel folgende Konfiguration:

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

export default defineConfig({
  testDir: './tests',
  retries: process.env.CI ? 2 : 0,
  reporter: 'html',
  use: {
    trace: 'on-first-retry',
    screenshot: 'only-on-failure',
    video: 'retain-on-failure',
  },
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
  ],
});

In diesem Beispiel:

  • wird der Trace beim ersten erneuten Versuch gespeichert,
  • wird ein Screenshot nur bei einem Fehler erstellt,
  • wird ein Video nur behalten, wenn der Test fehlschlägt,
  • werden in CI zwei Wiederholungen für Tests gesetzt.

Natürlich muss man Retry nicht immer verwenden. Gut geschriebene Tests sollten stabil sein. In echten Projekten kann Retry aber manchmal helfen, kurzfristige Umgebungsprobleme von echten Fehlern in der Anwendung zu unterscheiden.

Was ist, wenn die Anwendung vor den Tests gestartet werden muss?

Sehr oft brauchen End-to-End-Tests eine laufende Anwendung.

Lokal läuft deine Anwendung vielleicht unter:

http://localhost:3000

In GitHub Actions muss sie aber zuerst gestartet werden.

Das kann man auf verschiedene Arten lösen. Eine sehr praktische Möglichkeit ist die webServer-Konfiguration in Playwright.

Beispiel:

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

export default defineConfig({
  testDir: './tests',
  webServer: {
    command: 'npm run dev',
    url: 'http://127.0.0.1:3000',
    reuseExistingServer: !process.env.CI,
    timeout: 120 * 1000,
  },
  use: {
    baseURL: 'http://127.0.0.1:3000',
    trace: 'on-first-retry',
  },
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
  ],
});

Dadurch startet Playwright vor den Tests die Anwendung, wartet, bis sie unter der angegebenen Adresse erreichbar ist, und führt erst danach die Tests aus.

In den Tests kannst du dann relative Pfade verwenden:

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

test('homepage should load', async ({ page }) => {
  await page.goto('/');
  await expect(page).toHaveTitle(/Example/);
});

Das ist deutlich bequemer, als in jedem Test die vollständige Adresse einzutragen.

Tests nur für Pull Requests ausführen

Du musst Tests nicht immer nach jedem Push in jeden Branch ausführen.

Oft ist es sinnvoll, Tests bei Pull Requests nach main zu starten.

Beispiel:

on:
  pull_request:
    branches:
      - main

Dadurch wird eine Änderung geprüft, bevor sie in den Hauptbranch gemergt wird.

In Teamprojekten ist das sehr sinnvoll, weil ein Pull Request eigentlich nicht gemergt werden sollte, wenn die automatisierten Tests nicht erfolgreich durchlaufen.

Tests auf mehreren Browsern ausführen

Playwright erlaubt es, eine Anwendung auf verschiedenen Browsern zu testen, zum Beispiel auf Chromium, Firefox und WebKit.

In der Datei playwright.config.ts kann die Konfiguration so aussehen:

projects: [
  {
    name: 'chromium',
    use: { ...devices['Desktop Chrome'] },
  },
  {
    name: 'firefox',
    use: { ...devices['Desktop Firefox'] },
  },
  {
    name: 'webkit',
    use: { ...devices['Desktop Safari'] },
  },
],

Sollte man Tests immer auf drei Browsern ausführen?

Das kommt darauf an.

Wenn das Projekt klein ist, reicht am Anfang oft Chromium. Wenn die Anwendung aber von vielen Kunden genutzt wird und zuverlässig in verschiedenen Browsern funktionieren muss, sollte man eine breitere Konfiguration in Betracht ziehen.

Ich beginne meistens mit den wichtigsten Szenarien auf Chromium und ergänze weitere Browser erst dann, wenn es im Projekt wirklich Sinn ergibt.

Häufige Probleme in GitHub Actions

Bei der ersten Konfiguration von Playwright in GitHub Actions tauchen oft ähnliche Probleme auf.

1. Browser wurden nicht installiert

Wenn du einen Fehler siehst, der mit einem fehlenden Browser zusammenhängt, prüfe, ob dieser Schritt im Workflow vorhanden ist:

- name: Install Playwright browsers
  run: npx playwright install --with-deps

Ohne diesen Schritt kann es passieren, dass Playwright nicht die nötige Umgebung für die Testausführung hat.

2. Die Anwendung wurde vor den Tests nicht gestartet

Wenn Tests versuchen, localhost zu öffnen, die Anwendung aber nicht läuft, schlagen die Tests natürlich fehl.

In diesem Fall lohnt sich die Verwendung von webServer in der Playwright-Konfiguration oder ein separater Schritt im Workflow, der die Anwendung vor den Tests startet.

3. Der Test funktioniert lokal, aber nicht in CI

Das ist ein Klassiker.

Die häufigsten Ursachen sind:

  • Abhängigkeit von lokalen Daten,
  • zu starre Timeouts,
  • schlechte Selektoren,
  • fehlendes Warten auf Elemente,
  • Unterschiede zwischen den Umgebungen,
  • Tests, die von der Ausführungsreihenfolge abhängig sind.

In solchen Fällen helfen Trace, Screenshot und HTML-Report sehr.

4. Die Tests dauern zu lange

Wenn die Anzahl der Tests wächst, kann der Workflow irgendwann zu lange dauern.

Am Anfang ist das noch kein großes Problem. Später lohnt es sich aber, über folgende Dinge nachzudenken:

  • Aufteilung der Tests,
  • Ausführung nur der wichtigsten Tests bei jedem Pull Request,
  • separater Workflow für eine vollständige Regression,
  • Sharding der Tests,
  • Ausführung des vollständigen Testsets zum Beispiel einmal täglich oder vor einem größeren Release.

Sollten Playwright-Tests einen Merge blockieren?

Meiner Meinung nach: ja, aber mit Verstand.

Wenn du ein paar stabile Tests hast, die die wichtigsten Prozesse in der Anwendung prüfen, dann sollten diese Tests durchaus einen Merge blockieren können.

Zum Beispiel:

  • Login,
  • Registrierung,
  • Warenkorb,
  • Zahlung,
  • Absenden eines Formulars,
  • grundlegender Kaufprozess,
  • wichtigste Benutzerstrecke.

Ich würde aber nicht damit anfangen, den Merge durch hundert instabile Tests zu blockieren, die zufällig mal grün und mal rot sind.

Besser ist es, zuerst ein kleines, aber stabiles Testset zu haben. Danach kann man es Schritt für Schritt erweitern.

Gute Praxis: separater Workflow für Smoke Tests

In vielen Projekten funktioniert eine Aufteilung der Tests sehr gut.

Zum Beispiel:

  • Smoke Tests bei jedem Pull Request,
  • vollständige Regression manuell oder nach Zeitplan,
  • Cross-Browser-Tests vor einem Release.

Dadurch blockieren wir die Arbeit des Teams nicht mit einer zu langen Pipeline, haben aber trotzdem eine automatische Qualitätskontrolle.

Smoke Tests können zum Beispiel nur die wichtigsten Funktionen der Anwendung prüfen:

npx playwright test --grep @smoke

Und in den Tests können wir Szenarien entsprechend markieren:

test('@smoke user can open homepage', async ({ page }) => {
  await page.goto('/');
  await expect(page).toBeVisible();
});

Das ist eine einfache Möglichkeit, schnelle Tests von einer größeren Regression zu trennen.

Fazit

Playwright-Tests in GitHub Actions auszuführen ist einer dieser Schritte, die den Wert der Testautomatisierung deutlich erhöhen.

Solange Tests nur lokal ausgeführt werden, kann man sie leicht vergessen. Erst wenn sie Teil der Pipeline werden, unterstützen sie das Team wirklich.

Ein gut konfigurierter Workflow ermöglicht es:

  • Tests nach einem Push oder Pull Request auszuführen,
  • Fehler schneller zu erkennen,
  • HTML-Reports zu speichern,
  • Traces und Screenshots zu analysieren,
  • einen Merge zu blockieren, wenn wichtige Szenarien fehlschlagen.

Am Anfang muss die Konfiguration nicht perfekt sein.

Ein einfacher Workflow, ein paar stabile Tests und ein Report als Artefakt reichen völlig aus. Danach kann man Schritt für Schritt weitere Elemente ergänzen: Retries, Traces, Smoke Tests, Sharding, Tests auf mehreren Browsern oder eine vollständige Regression.

Wichtig ist vor allem eines: Automatisierte Tests sollten dort laufen, wo tatsächlich über die Qualität des Codes entschieden wird.

Und in vielen Projekten ist genau dieser Ort GitHub Actions.

Hol dir 15% Rabatt

Melde dich für den Newsletter an und erhalte einen 15% Rabattcode für jeden Kurs in unserem Shop.

Mit der Anmeldung akzeptierst du die Datenschutzbestimmungen.

Beliebteste Kurse

Wenn dich dieses Thema interessiert, sind diese Kurse ein guter nächster Schritt.