На странице кнопка становится доступной после асинхронного запроса, поэтому тест иногда не успевает нажать её. Какой механизм ожидания следует применить вместо фиксированной задержки?
import time
def test_submit(page):
page.open('/checkout')
time.sleep(5)
page.click('#submit')
assert page.text('#status') == 'accepted'
Следует заменить фиксированную задержку на явное ожидание условия: тест должен периодически проверять, что кнопка стала доступной, и продолжать выполнение сразу после этого. Ожидание должно иметь ограничение по времени и завершаться понятной ошибкой при истечении тайм-аута.
Фиксированные задержки появились как простой способ синхронизировать тест с асинхронным интерфейсом. Однако скорость выполнения запроса зависит от нагрузки, окружения, сети и состояния приложения, поэтому одно и то же число секунд не гарантирует корректную синхронизацию.
Условные ожидания решают эту проблему: тест ожидает не время само по себе, а наблюдаемое состояние системы. Такой подход особенно важен для UI-тестов, где браузер и приложение выполняют операции независимо от сценария теста.
В примере тест всегда бездействует пять секунд. Если запрос завершился за 500 миллисекунд, тест теряет время; если он занял больше пяти секунд, клик выполняется слишком рано и тест становится нестабильным.
Повторный запуск может временно скрыть проблему, но не устраняет неверную синхронизацию. Без ограничения времени ожидание также опасно: при ошибке приложения тест может зависнуть вместо того, чтобы быстро сообщить о причине сбоя.
Механизм должен проверять конкретное условие, например доступность кнопки, видимость элемента или появление ожидаемого состояния. Проверки выполняются с небольшим интервалом до успешного результата или до истечения тайм-аута.
В реальном фреймворке обычно используют его встроенный механизм явных ожиданий, чтобы корректно обрабатывать особенности DOM, повторные проверки и диагностические сообщения. Важно ожидать именно бизнес-релевантное состояние, а не произвольное исчезновение индикатора загрузки, если это не гарантирует готовность нужного элемента.
Тайм-аут должен быть достаточно большим для допустимого времени операции, но не настолько большим, чтобы скрывать проблемы приложения. Интервал опроса выбирают как компромисс между быстротой реакции и нагрузкой на браузер или тестируемую систему.
Следует избегать ожидания только по факту наличия элемента в DOM: элемент может быть невидимым, заблокированным перекрывающим слоем или ещё не готовым к взаимодействию. Также важно учитывать исчезающие элементы и изменение DOM: сохранённая ссылка на элемент может стать недействительной, поэтому некоторые инструменты находят элемент заново при каждой проверке.
В checkout-тестах кнопка оплаты появлялась сразу, но становилась доступной только после валидации адреса и пересчёта доставки. Команда сначала добавила задержку в восемь секунд: локально это работало, но CI стал медленным, а при перегруженном стенде тесты всё равно падали.
Рассматривались три варианта. Увеличить задержку было проще всего, но это не устраняло зависимость от скорости среды. Повторять весь тест при сбое повышало вероятность зелёного результата, но маскировало проблему синхронизации. Ожидать состояние кнопки с ограничением времени оказалось точнее: тест завершался сразу после готовности элемента, а при настоящей проблеме фиксировал диагностический тайм-аут.
В качестве дополнительной проверки команда оставила утверждение результата после клика. Это важно: готовность кнопки подтверждает возможность действия, но не доказывает успешность операции оплаты.
Нет. Наличие элемента в DOM не означает, что он видим, доступен для взаимодействия или отражает завершённое состояние приложения. Нужно выбирать условие, непосредственно связанное с действием: например, видимость и доступность кнопки либо появление подтверждённого результата.
Нет. Большой тайм-аут лишь уменьшает вероятность раннего продолжения, но увеличивает длительность сбоя и всё равно не гарантирует синхронизацию. Условное ожидание использует время эффективнее и позволяет связать ошибку с конкретным невыполненным условием.
Завершение запроса не всегда означает, что интерфейс обработал ответ. После получения данных приложение может обновить состояние, перерисовать DOM или выполнить дополнительную валидацию. Поэтому надёжнее ожидать наблюдаемое состояние, необходимое следующему шагу теста, а сетевую активность использовать только как дополнительный диагностический сигнал.