Авто-ожидания: почему не нужны sleep

Главное преимущество Playwright: он сам ждёт нужного момента, а ручные паузы — антипаттерн.

Авто-ожидание — встроенный механизм: перед каждым действием Playwright проверяет ряд условий готовности элемента и ждёт, пока они выполнятся, прежде чем выполнить действие.

Почему веб асинхронен

Современные сайты подгружают данные на лету: вы кликнули — пошёл запрос — через 300 мс появился результат. Если тест попытается кликнуть по кнопке, которой ещё нет на странице, он упадёт. Старый подход боролся с этим грубо — вставляли паузы.

// АНТИПАТТЕРН: фиксированная пауза
await page.waitForTimeout(3000);  // ждём «на всякий случай» 3 секунды
await page.getByRole('button', { name: 'Готово' }).click();

Это плохо по двум причинам. Если сеть быстрая — вы зря потеряли 3 секунды на каждом шаге, а в большом наборе такие потери складываются в минуты. Если медленная — 3 секунд не хватит, и тест всё равно упадёт. Фиксированные паузы делают тесты одновременно медленными и ненадёжными.

Как работают авто-ожидания

Playwright решает проблему иначе. Перед действием он автоматически ждёт, пока элемент пройдёт проверки готовности (actionability):

  • элемент прикреплён к DOM;
  • видим (не display:none, не нулевого размера);
  • стабилен — не анимируется, не двигается;
  • включён — не disabled;
  • не перекрыт другим элементом (например, всплывающим окном).

Поэтому код без всяких пауз просто работает:

// Playwright сам дождётся, пока кнопка появится и станет кликабельной
await page.getByRole('button', { name: 'Готово' }).click();

Если кнопка появится через 300 мс — клик произойдёт через 300 мс. Если через 2 секунды — через 2 секунды. Тест подстраивается под реальность, а не под угаданное число. Это и есть причина, по которой Playwright-тесты в среднем стабильнее: они не «угадывают» тайминги, а наблюдают за состоянием страницы.

Сравнение подходов

ПодходБыстрая сетьМедленная сеть
waitForTimeout(3000)теряем 3 с впустуюможет не хватить — падение
авто-ожиданиеждём ровно сколько нужнождём до таймаута, успеваем

Когда ожидание нужно явно

Иногда нужно дождаться не элемента, а события — навигации или сетевого ответа. Для этого есть явные ожидания вроде waitForURL или waitForResponse (разберём в отдельном уроке). А вот waitForTimeout в рабочих тестах — почти всегда признак проблемы. Если очень хочется его поставить, спросите себя: «чего именно я жду?» — и дождитесь именно этого условия.

// правильно: ждём конкретное событие, а не «время вообще»
await page.getByRole('button', { name: 'Сохранить' }).click();
await page.waitForURL('**/success');

Итог

  • Веб асинхронен: элементы появляются не сразу.
  • Фиксированные паузы (waitForTimeout) — антипаттерн: медленно и ненадёжно.
  • Playwright перед действием сам ждёт готовности элемента (видим, стабилен, включён, не перекрыт).
  • Если нужно явное ожидание — ждите события (URL, ответ), а не абстрактное время.
Проверьте себя
1. Почему waitForTimeout(3000) считается антипаттерном?
AЭта команда не существует в Playwright
BНа быстрой сети теряется время, на медленной 3 секунд может не хватить
CОна работает только в headless-режиме
DОна блокирует другие тесты
2. Что Playwright проверяет перед выполнением действия над элементом?
AТолько что элемент существует в HTML-исходнике
BЧто элемент прикреплён, видим, стабилен, включён и не перекрыт
CТолько цвет и размер шрифта
DНичего — действие выполняется мгновенно
3. Если нужно дождаться перехода на новую страницу, что лучше использовать?
AwaitForTimeout(5000)
BБесконечный цикл с проверкой URL
CЯвное ожидание события, например waitForURL
DНичего, переход происходит сам
Поддержать проект