Playwright: авто-ожидание и тайм-аут

В этой главе подробно рассматривается механизм авто-ожидания Playwright, а также даются полные сведения о ручном ожидании и настройке тайм-аутов.


Зачем нужно авто-ожидание

Современные веб-приложения в значительной степени полагаются на асинхронный рендеринг, и содержимое страницы не загружается полностью мгновенно.

В традиционных фреймворках тестирования разработчикам приходится писатьsleepилиwaitForЭти операции ожидания недостаточно гибкие — они либо ждут слишком долго и замедляют тесты, либо ждут слишком мало и приводят к нестабильным тестам.

Playwright встраивает логику ожидания в каждый Locator и действие, что кардинально решает эту проблему.


Трёхуровневая система автоожидания

Уровень 1: Автоожидание Locator

Когда вы создаёте Locator, Playwright не ищет элемент сразу; вместо этого он начинает поиск и автоматически ожидает, когда вы выполняете действие или проверку.

Пример

// Создание Locator (элемент не будет искаться на этом этапе)
const btn = page.getByRole('button', { name: 'Delayed button' });

// Автоматически ждать появления кнопки при клике (ожидает до тайм-аута действия)
await btn.click();

Уровень 2: Проверка возможности выполнения действия

Перед выполнением действия (click, fill и т. д.) Playwright проверяет, что элемент: Присоединён → Видим → Стабилен → Получает события → Включён.

Уровень 3: Автоматический повтор проверок

После неудачной проверки он не сообщает об ошибке сразу; вместо этого он продолжает повторять попытки, пока условие не будет выполнено или не истечёт тайм-аут.

Пример

// Эта проверка будет повторять попытки в течение 5 секунд, пока текст не появится или не истечёт время ожидания
await expect(page.getByText('Data loading complete')).toBeVisible();

Методы ручного ожидания

В особых сценариях, когда автоматического ожидания недостаточно, Playwright также предоставляет методы ручного ожидания.

page.waitForTimeout(ms) — Фиксированное ожидание

Пример

// Фиксированное ожидание в течение 2 секунд (обычно не рекомендуется)
await page.waitForTimeout(2000);

Постарайтесь не использовать его.waitForTimeoutФиксированное ожидание крайне нестабильно при различиях в производительности устройств. Отдавайте предпочтение следующимwaitForURL、waitForResponseожиданиям, управляемым событиями.

page.waitForURL() — Ожидание изменения URL

Пример

// Ожидание точного совпадения URL
await page.waitForURL('https://www.example.com/dashboard');

// Дождаться, пока URL будет содержать определённый шаблон
await page.waitForURL(/dashboard/);

page.waitForLoadState() — Ожидание состояния загрузки

Пример

// Дождаться события load
await page.waitForLoadState('load');

// Дождаться DOMContentLoaded
await page.waitForLoadState('domcontentloaded');

// Дождаться простоя сети
await page.waitForLoadState('networkidle');

page.waitForResponse() — Ожидание сетевого ответа

Пример

// Дождаться конкретного ответа API
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 типа тайм-аутов, каждый действует на своём уровне:

Тип тайм-аутаРасположение файла конфигурацииЗначение по умолчаниюПрименяется к
Тайм-аут тестаtimeout30000msВесь тест-кейс
Тайм-аут expectexpect.timeout5000msПовторная попытка утверждения
Тайм-аут действияuse.actionTimeoutНет (без ограничений)Операции с элементами (click, fill и т. д.)
Тайм-аут навигацииuse.navigationTimeoutНет (без ограничений)Навигация по странице (goto, goBack и т. д.)

Глобальная конфигурация

Пример

// Путь к файлу: playwright.config.ts
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 медленны.
Другие расширения