E2E-Tests mit Claude Code und Playwright produktionsreif einführen
Plane Playwright-E2E mit Claude Code: Mobile Screenshots, Auth State, Trace Viewer, Selektoren und CI-Retries.
Claude Code nur mit “füge Playwright-Tests hinzu” zu beauftragen, reicht für Produktion nicht aus. Häufig entstehen Tests, die einmal laufen, aber an CSS-Klassen hängen, jedes Mal den Login durchklicken, keine Mobile-Screenshots speichern und bei CI-Fehlern keine verwertbare Trace hinterlassen.
Praktischer ist es, Claude Code als Partner für Testdesign zu nutzen. Du definierst Geschäftsrisiken, Routen, Selektorregeln und den Verifikationsbefehl; Claude Code liest das Projekt und ergänzt Playwright-Konfiguration und Specs. Dieser Leitfaden deckt E2E für Monetarisierungspfade, Mobile-Layout, Codeblöcke, Auth State, Trace Viewer, CI-Retries und weniger flaky Tests ab.
Als Basis dienen die offiziellen Quellen: Claude Code overview, Claude Code common workflows sowie Playwright zu Locators, Authentication, Screenshots, Trace Viewer, Retries und CI. In ClaudeCodeLab passen dazu Teststrategie, CI/CD Setup und Responsive Design.
Schütze die richtigen Flows
E2E startet echte Browser und ist langsamer als Unit Tests. Es sollte daher Verhalten schützen, das nur im Browser wirklich belegbar ist.
| Use Case | Was geschützt wird | Playwright-Beleg |
|---|---|---|
| Artikel zu Produkten | Leser erreichen /products/ | CTA, URL, Mobile-Tap |
| Eingeloggt zum Dashboard | Authentifizierte Nutzer erreichen geschützte Seiten | storageState, Redirects, Rollen |
| Layout technischer Artikel | Codeblöcke und Tabellen sprengen Mobile nicht | Mobile Screenshot, kein Overflow, Trace |
flowchart LR
A["Umsatz- oder Signup-Pfad"] --> B["Playwright E2E"]
C["Mobile Layout Risiko"] --> B
D["Reine Validierung"] --> E["Unit Tests"]
F["API- oder Komponenten-Grenze"] --> G["Integration Tests"]
Für monetarisierte Inhalte sind versteckte CTAs, zu breite Codezeilen oder ungetestete Käuferseiten keine kosmetischen Probleme. Sie kosten Vertrauen und Conversion.
Claude Code präzise briefen
Der Prompt sollte Zielrouten, erlaubte Selektoren, ausführbare Befehle und erlaubte Dateien enthalten.
Lies die bestehende Astro-Site und ergänze Playwright-E2E-Tests.
Ziele:
- Prüfe, dass `/de/blog/claude-code-playwright-testing/` zu `/products/` und `/training/` führt
- Prüfe bei 390px Mobile-Breite, dass Artikel, Tabellen und Codeblöcke nicht horizontal überlaufen
- Nutze `storageState` für authentifizierte Tests, statt jedes Mal über die UI einzuloggen
- In CI 2 Retries und `trace: "on-first-retry"` verwenden
Einschränkungen:
- Kein `page.waitForTimeout()`
- Role, Label, Text oder Test-ID vor CSS-Klassenketten
- Nur `playwright.config.ts` und `tests/e2e/**` ändern
- `npx playwright test` ausführen und Fehler mit Trace Viewer erklären
Beim Review zählt nicht die Anzahl erzeugter Dateien, sondern ob ein Fehler erklärbar ist und ob der Test ein echtes Nutzerproblem abbildet.
Kopierbare Grundkonfiguration
cd site
npm i -D @playwright/test
npx playwright install
mkdir tests/e2e
// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
const baseURL = process.env.BASE_URL ?? 'http://127.0.0.1:4321';
const hasAuth = Boolean(process.env.TEST_EMAIL && process.env.TEST_PASSWORD);
const authFile = 'playwright/.auth/user.json';
export default defineConfig({
testDir: './tests/e2e',
timeout: 30_000,
expect: { timeout: 5_000 },
fullyParallel: true,
forbidOnly: Boolean(process.env.CI),
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 2 : undefined,
reporter: process.env.CI ? [['html'], ['github']] : 'html',
use: {
baseURL,
trace: 'on-first-retry',
screenshot: 'only-on-failure',
video: 'retain-on-failure',
},
...(process.env.PLAYWRIGHT_WEB_SERVER === '1'
? {
webServer: {
command: 'npm run preview -- --host 127.0.0.1 --port 4321',
url: baseURL,
reuseExistingServer: !process.env.CI,
timeout: 120_000,
},
}
: {}),
projects: [
...(hasAuth
? [
{
name: 'setup',
testMatch: /.*\.setup\.ts/,
},
]
: []),
{
name: 'desktop-chrome',
use: {
...devices['Desktop Chrome'],
storageState: hasAuth ? authFile : undefined,
},
dependencies: hasAuth ? ['setup'] : [],
},
{
name: 'mobile-safari',
use: {
...devices['iPhone 13'],
storageState: hasAuth ? authFile : undefined,
},
dependencies: hasAuth ? ['setup'] : [],
},
],
});
Lokal bleiben Retries aus, damit Fehler sichtbar bleiben. In CI sind Retries sinnvoll, wenn gleichzeitig Trace, Screenshot und Report gesichert werden.
Auth State speichern
Jeder Test sollte nicht erneut über die Login-UI laufen. Das ist langsam und fragil. storageState speichert Cookies und Local Storage eines Testnutzers. playwright/.auth gehört in .gitignore.
// tests/e2e/auth.setup.ts
import { test as setup, expect } from '@playwright/test';
import fs from 'node:fs';
import path from 'node:path';
const authFile = path.resolve('playwright/.auth/user.json');
const email = process.env.TEST_EMAIL;
const password = process.env.TEST_PASSWORD;
setup('save signed-in browser state', async ({ page }) => {
setup.skip(!email || !password, 'Set TEST_EMAIL and TEST_PASSWORD to record auth state.');
await page.goto('/login');
await page.getByLabel(/email|メール|e-mail/i).fill(email!);
await page.getByLabel(/password|パスワード/i).fill(password!);
await page.getByRole('button', { name: /log in|sign in|ログイン/i }).click();
await expect(page).toHaveURL(/dashboard|account|admin/);
await expect(page.locator('body')).toBeVisible();
fs.mkdirSync(path.dirname(authFile), { recursive: true });
await page.context().storageState({ path: authFile });
});
Bitte Claude Code, Login-Tests und bereits authentifizierte Feature-Tests zu trennen. Dann bricht nicht die ganze Suite, nur weil ein Login-Label geändert wurde.
Mobile Screenshots und Codeblöcke testen
Technische Artikel brechen oft durch lange Codezeilen, Tabellen oder eingebettete Medien. Dieser Spec prüft CTAs, speichert einen Mobile-Screenshot und schlägt bei horizontalem Overflow fehl.
// tests/e2e/article-quality.spec.ts
import { test, expect } from '@playwright/test';
const articlePath = process.env.ARTICLE_PATH ?? '/de/blog/claude-code-playwright-testing/';
test.describe('article quality checks', () => {
test('article has monetization CTAs', async ({ page }) => {
await page.goto(articlePath);
await expect(page.getByRole('heading', { level: 1 })).toContainText(/Playwright|E2E|Claude Code/i);
await expect(page.locator('a[href="/products/"], a[href="/products"]').first()).toBeVisible();
await expect(page.locator('a[href="/training/"], a[href="/training"]').first()).toBeVisible();
});
test('mobile layout has no horizontal overflow', async ({ page }, testInfo) => {
await page.setViewportSize({ width: 390, height: 844 });
await page.goto(articlePath);
await expect(page.locator('main, article').first()).toBeVisible();
const overflow = await page.evaluate(() => ({
viewport: window.innerWidth,
documentWidth: document.documentElement.scrollWidth,
offenders: Array.from(document.querySelectorAll('pre, table, img, iframe, .prose'))
.filter((node) => {
const rect = node.getBoundingClientRect();
return rect.left < -1 || rect.right > window.innerWidth + 1;
})
.map((node) => {
const rect = node.getBoundingClientRect();
return `${node.tagName.toLowerCase()} ${Math.round(rect.left)}-${Math.round(rect.right)}`;
}),
}));
expect(overflow.documentWidth, JSON.stringify(overflow)).toBeLessThanOrEqual(overflow.viewport + 2);
expect(overflow.offenders).toEqual([]);
await page.screenshot({ path: testInfo.outputPath('article-mobile.png'), fullPage: true });
});
test('code examples are present and copyable', async ({ page }) => {
await page.goto(articlePath);
const blocks = page.locator('pre code');
await expect(blocks.first()).toBeVisible();
expect(await blocks.count()).toBeGreaterThanOrEqual(3);
await expect(blocks.nth(0)).toContainText(/playwright|defineConfig|test/i);
});
});
Der Screenshot hilft im Review, die numerische Overflow-Prüfung im CI-Gate.
Umsatz- und Lern-CTAs schützen
// tests/e2e/revenue-flows.spec.ts
import { test, expect } from '@playwright/test';
const articlePath = process.env.ARTICLE_PATH ?? '/de/blog/claude-code-playwright-testing/';
test.describe('revenue and learning flows', () => {
test('reader can move from article to products', async ({ page }) => {
await page.goto(articlePath);
await page.locator('a[href="/products/"], a[href="/products"]').first().click();
await expect(page).toHaveURL(/\/products\/?$/);
await expect(page.locator('main').first()).toBeVisible();
});
test('training CTA is reachable on mobile', async ({ page }) => {
await page.setViewportSize({ width: 390, height: 844 });
await page.goto(articlePath);
await page.locator('a[href="/training/"], a[href="/training"]').first().click();
await expect(page).toHaveURL(/\/training\/?$/);
await expect(page.locator('main').first()).toBeVisible();
});
test('main navigation can open the blog index', async ({ page }) => {
await page.goto('/');
await expect(page.getByRole('navigation').first()).toBeVisible();
await page.getByRole('link', { name: /blog|記事|articles/i }).first().click();
await expect(page).toHaveURL(/blog/);
});
});
Auf mehrsprachigen Sites ändern sich CTA-Texte. Für kritische Aktionen sind stabile hrefs oder fachliche data-testids sinnvoll.
Stabilere Selektoren
| Priorität | Selektor | Beispiel | Warum |
|---|---|---|---|
| Hoch | Role und Name | page.getByRole('button', { name: /save/i }) | Nah an Nutzer- und Accessibility-Sicht |
| Hoch | Label | page.getByLabel(/email/i) | Prüft Formularsemantik |
| Mittel | Text | page.getByText(/Start trial/) | Verständlich, aber copy-abhängig |
| Mittel | Test-ID | page.getByTestId('checkout-submit') | Stabil für Business-Aktionen |
| Niedrig | CSS-Struktur | .card:nth-child(3) | Layoutänderungen brechen den Test |
Vermeide page.waitForTimeout(). Nutze toBeVisible(), toHaveURL() und toContainText(), damit Playwright echte Bedingungen abwartet.
Fehler mit Trace Viewer verstehen
npx playwright test --trace on
npx playwright show-report
npx playwright show-trace test-results/path-to-trace/trace.zip
Gib Claude Code bei Fehlern den Testnamen, den sichtbaren Trace-Zustand und das erwartete Nutzerverhalten. Das führt eher zu besseren Selektoren oder Daten-Setup als zu blind erhöhten Timeouts.
CI mit Retries und Artefakten
# .github/workflows/playwright.yml
name: Playwright E2E
on:
pull_request:
push:
branches: [main]
jobs:
e2e:
runs-on: ubuntu-latest
timeout-minutes: 15
defaults:
run:
working-directory: site
env:
BASE_URL: http://127.0.0.1:4321
PLAYWRIGHT_WEB_SERVER: "1"
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: site/package-lock.json
- run: npm ci
- run: npx playwright install --with-deps
- run: npm run build
- run: npx playwright test
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: site/playwright-report
retention-days: 7
Retries reparieren keine flaky Tests. Sie klassifizieren sie und erzeugen Belege, die geprüft werden müssen.
Häufige Fallen
Erstens: alles als E2E testen. Berechnungen, Validierungen und kleine Rechteprüfungen gehören meist in Unit- oder Integrationstests.
Zweitens: Auth State committen. Nutze begrenzte Testnutzer und schließe playwright/.auth aus.
Drittens: Instabilität mit Retries verstecken. Ein Test, der nur im Retry passt, bleibt ein Risiko.
Viertens: Claude Code ohne Änderungsgrenze arbeiten lassen. Besser ist: fehlschlagenden Test ergänzen, Trace ansehen, kleinste Produktkorrektur umsetzen.
Für Self-Service nutze die ClaudeCodeLab products Vorlagen. Für Teams helfen training und gemeinsame Regeln für Review, CI und Onboarding.
Ich habe diesen Ablauf an einer lokalen ClaudeCodeLab-artigen Artikelseite geprüft: 390px Screenshot, Codeblock-Overflow, Navigation zu /products/ und /training/, sowie CI-Retry-Konfiguration. Die ersten nützlichen Fehler lagen nicht in Playwright, sondern in zu langen Codezeilen und unklaren Linknamen. Nach der Korrektur wurde Trace Viewer zu einem brauchbaren Nachweis für den nächsten Claude-Code-Prompt.
Kostenloses PDF: Claude-Code-Cheatsheet
E-Mail eintragen und eine Seite mit Befehlen, Review-Gewohnheiten und sicheren Workflows herunterladen.
Wir schützen Ihre Daten und senden keinen Spam.
Über den Autor
Masa
Engineer für praktische Claude-Code-Workflows und Team-Einführung.
Ähnliche Artikel
Claude-Code-Permission-Receipt: Scope, Beweis und Rollback festhalten
Permission-Receipt für Claude Code: erlaubte Aktionen, Freigabegrenzen, Prüfbefehle, Rollback und Umsatz-CTA-Prüfung.
Sicheres Agent Harness fur Claude Code und Codex: Rechte, Prufung und Rollback
Ein praktisches Agent Harness fur Claude Code und Codex mit Policy, Plan, Verifikation und Recovery.
Claude Code Subagents: Praxisleitfaden für sichere Agent-Delegation
Claude Code Subagents praktisch nutzen: Artikel- und Codearbeit sicher aufteilen, Prompts einsetzen, Fehler vermeiden.