Playwright: авто-ожидание и тайм-аут
В этой главе подробно рассматривается механизм авто-ожидания Playwright, а также даются полные сведения о ручном ожидании и настройке тайм-аутов.
Зачем нужно авто-ожидание
Современные веб-приложения в значительной степени полагаются на асинхронный рендеринг, и содержимое страницы не загружается полностью мгновенно.
В традиционных фреймворках тестирования разработчикам приходится писатьsleepилиwaitForЭти операции ожидания недостаточно гибкие — они либо ждут слишком долго и замедляют тесты, либо ждут слишком мало и приводят к нестабильным тестам.
Playwright встраивает логику ожидания в каждый Locator и действие, что кардинально решает эту проблему.
Трёхуровневая система автоожидания
Уровень 1: Автоожидание Locator
Когда вы создаёте Locator, Playwright не ищет элемент сразу; вместо этого он начинает поиск и автоматически ожидает, когда вы выполняете действие или проверку.
Пример
const btn = page.getByRole('button', { name: 'Delayed button' });
// Автоматически ждать появления кнопки при клике (ожидает до тайм-аута действия)
await btn.click();
Уровень 2: Проверка возможности выполнения действия
Перед выполнением действия (click, fill и т. д.) Playwright проверяет, что элемент: Присоединён → Видим → Стабилен → Получает события → Включён.
Уровень 3: Автоматический повтор проверок
После неудачной проверки он не сообщает об ошибке сразу; вместо этого он продолжает повторять попытки, пока условие не будет выполнено или не истечёт тайм-аут.
Пример
await expect(page.getByText('Data loading complete')).toBeVisible();
Методы ручного ожидания
В особых сценариях, когда автоматического ожидания недостаточно, Playwright также предоставляет методы ручного ожидания.
page.waitForTimeout(ms) — Фиксированное ожидание
Пример
await page.waitForTimeout(2000);
Постарайтесь не использовать его.
waitForTimeoutФиксированное ожидание крайне нестабильно при различиях в производительности устройств. Отдавайте предпочтение следующимwaitForURL、waitForResponseожиданиям, управляемым событиями.
page.waitForURL() — Ожидание изменения URL
Пример
await page.waitForURL('https://www.example.com/dashboard');
// Дождаться, пока URL будет содержать определённый шаблон
await page.waitForURL(/dashboard/);
page.waitForLoadState() — Ожидание состояния загрузки
Пример
await page.waitForLoadState('load');
// Дождаться DOMContentLoaded
await page.waitForLoadState('domcontentloaded');
// Дождаться простоя сети
await page.waitForLoadState('networkidle');
page.waitForResponse() — Ожидание сетевого ответа
Пример
const response = await page.waitForResponse(
resp => resp.url().includes('/api/data') && resp.status() === 200
);
// Получить данные ответа
const data = await response.json();
page.waitForEvent() — Ожидание события
Пример
const dialogPromise = page.waitForEvent('dialog');
await page.getByRole('button', { name: 'Delete' }).click();
const dialog = await dialogPromise;
await dialog.accept();
// Дождаться открытия новой страницы
const pagePromise = page.context().waitForEvent('page');
await page.getByRole('link', { name: 'Open in new window' }).click();
const newPage = await pagePromise;
Объяснение настройки тайм-аутов
В Playwright есть 4 типа тайм-аутов, каждый действует на своём уровне:
| Тип тайм-аута | Расположение файла конфигурации | Значение по умолчанию | Применяется к |
|---|---|---|---|
| Тайм-аут теста | timeout | 30000ms | Весь тест-кейс |
| Тайм-аут expect | expect.timeout | 5000ms | Повторная попытка утверждения |
| Тайм-аут действия | use.actionTimeout | Нет (без ограничений) | Операции с элементами (click, fill и т. д.) |
| Тайм-аут навигации | use.navigationTimeout | Нет (без ограничений) | Навигация по странице (goto, goBack и т. д.) |
Глобальная конфигурация
Пример
import { defineConfig } from '@playwright/test';
export default defineConfig({
// Общий тайм-аут для каждого теста (milliseconds)
timeout: 60000,
// Тайм-аут для автоматического повторения утверждения
expect: {
timeout: 10000,
},
использовать: {
// Тайм-аут для каждого действия (click, fill и т. д.)
actionTimeout: 15000,
// Тайм-аут для каждой навигации
navigationTimeout: 30000,
},
});
Настройки для отдельного вызова (приоритет выше глобальной конфигурации)
Пример
test.setTimeout(120000);
// Установить тайм-аут для одного действия
await page.getByRole('button').click({ timeout: 30000 });
// Установить тайм-аут для одной навигации
await page.goto('https://www.example.com/', { timeout: 60000 });
Приоритет тайм-аутов
Настройки отдельного вызова > Настройки глобального конфигурационного файла > Значения по умолчанию.
Рекомендации по разумной настройке тайм-аутов
| Сценарий | Рекомендуемый тайм-аут | Описание |
|---|---|---|
| Локальная разработка | Значения по умолчанию | Локальные сервисы отвечают быстро; значений по умолчанию достаточно. |
| CI-окружение | В 2–3 раза больше значения по умолчанию | Производительность CI-машины значительно колеблется. |
| Медленные страницы | actionTimeout: 15000 | Большие формы, сложные страницы |
| Вызовы сторонних сервисов | test.setTimeout(120000) | Ответы внешних API медленны. |