Playwright Auto-wait und Timeout
Dieses Kapitel bietet eine ausführliche Einführung in den Auto-wait-Mechanismus von Playwright sowie umfassendes Wissen zu manuellem Warten und Timeout-Konfiguration.
Warum brauchen wir Auto-wait
Moderne Webanwendungen setzen stark auf asynchrones Rendering, und Seiteninhalte werden nicht sofort vollständig geladen.
In traditionellen Test-Frameworks müssen Entwickler schreibensleepoderwaitForDiese Warteoperationen sind nicht flexibel genug – entweder warten sie zu lange und verlangsamen die Tests, oder sie warten zu kurz und verursachen flaky Tests.
Playwright integriert Wartelogik in jeden Locator und jede Action und löst dieses Problem grundlegend.
Dreischichtiges Auto-Wait-System
Ebene 1: Locator-Auto-Wait
Wenn Sie einen Locator erstellen, sucht Playwright nicht sofort nach dem Element; stattdessen beginnt es zu suchen und wartet automatisch, wenn Sie eine Aktion oder Assertion ausführen.
Beispiel
const btn = page.getByRole('button', { name: 'Delayed button' });
// Automatisch auf das Erscheinen der Schaltfläche beim Klicken warten (wartet bis zum Action-Timeout)
await btn.click();
Ebene 2: Prüfung der Aktionsausführbarkeit
Bevor eine Aktion ausgeführt wird (click, fill usw.), stellt Playwright sicher, dass das Element: Angehängt → Sichtbar → Stabil → Empfängt Ereignisse → Aktiviert ist.
Ebene 3: Automatische Wiederholung von Assertions
Wenn eine Assertion fehlschlägt, wird nicht sofort ein Fehler gemeldet; stattdessen wird weiter wiederholt, bis die Bedingung erfüllt ist oder ein Timeout auftritt.
Beispiel
await expect(page.getByText('Data loading complete')).toBeVisible();
Manuelle Wartemethoden
In speziellen Szenarien, in denen das automatische Warten nicht ausreicht, bietet Playwright auch manuelle Wartemethoden.
page.waitForTimeout(ms) — Feste Wartezeit
Beispiel
await page.waitForTimeout(2000);
Versuchen Sie, es zu vermeiden.
waitForTimeoutFestes Warten ist bei Unterschieden in der Geräteleistung extrem instabil. Bevorzugen Sie die folgendenwaitForURL、waitForResponseereignisgesteuerten Wartezeiten.
page.waitForURL() — Auf URL-Änderung warten
Beispiel
await page.waitForURL('https://www.example.com/dashboard');
// Warten, bis die URL ein bestimmtes Muster enthält
await page.waitForURL(/dashboard/);
page.waitForLoadState() — Auf Ladezustand warten
Beispiel
await page.waitForLoadState('load');
// Auf DOMContentLoaded warten
await page.waitForLoadState('domcontentloaded');
// Auf Netzwerk-Leerlauf warten
await page.waitForLoadState('networkidle');
page.waitForResponse() — Auf Netzwerkantwort warten
Beispiel
const response = await page.waitForResponse(
resp => resp.url().includes('/api/data') && resp.status() === 200
);
// Antwortdaten abrufen
const data = await response.json();
page.waitForEvent() — Auf Ereignis warten
Beispiel
const dialogPromise = page.waitForEvent('dialog');
await page.getByRole('button', { name: 'Delete' }).click();
const dialog = await dialogPromise;
await dialog.accept();
// Warten, bis eine neue Seite geöffnet wird
const pagePromise = page.context().waitForEvent('page');
await page.getByRole('link', { name: 'Open in new window' }).click();
const newPage = await pagePromise;
Timeout-Konfiguration erklärt
Playwright hat 4 Arten von Timeouts, die jeweils auf einer anderen Ebene wirken:
| Timeout-Typ | Speicherort der Konfigurationsdatei | Standardwert | Gilt für |
|---|---|---|---|
| Test-Timeout | timeout | 30000ms | Gesamter Testfall |
| Expect-Timeout | expect.timeout | 5000ms | Assertion-Wiederholung |
| Aktions-Timeout | use.actionTimeout | Keine (unbegrenzt) | Elementoperationen (click, fill usw.) |
| Navigations-Timeout | use.navigationTimeout | Keine (unbegrenzt) | Seitennavigation (goto, goBack usw.) |
Globale Konfiguration
Beispiel
import { defineConfig } from '@playwright/test';
export default defineConfig({
// Gesamt-Timeout für jeden Test (Millisekunden)
timeout: 60000,
// Timeout für automatische Wiederholung der Assertion
expect: {
timeout: 10000,
},
Verwenden Sie: {
// Timeout für jede Aktion (click, fill usw.)
actionTimeout: 15000,
// Timeout für jede Navigation
navigationTimeout: 30000,
},
});
Einstellungen pro Aufruf (höhere Priorität als globale Konfiguration)
Beispiel
test.setTimeout(120000);
// Timeout für eine einzelne Aktion festlegen
await page.getByRole('button').click({ timeout: 30000 });
// Timeout für eine einzelne Navigation festlegen
await page.goto('https://www.example.com/', { timeout: 60000 });
Timeout-Priorität
Einstellungen pro Aufruf > Einstellungen der globalen Konfigurationsdatei > Standardwerte.
Vorschläge für eine sinnvolle Einstellung von Timeouts
| Szenario | Empfohlener Timeout | Beschreibung |
|---|---|---|
| Lokale Entwicklung | Standardwerte | Lokale Dienste reagieren schnell; Standardwerte sind ausreichend. |
| CI-Umgebung | 2–3-Fache des Standardwerts | Die Leistung von CI-Maschinen schwankt erheblich. |
| Langsame Seiten | actionTimeout: 15000 | Große Formulare, komplexe Seiten |
| Aufrufe von Drittanbieter-Diensten | test.setTimeout(120000) | Externe API-Antworten sind langsam. |