Какие способы организации ожиданий (waits) существуют в Selenium WebDriver?

Ответ

В Selenium WebDriver для синхронизации тестов с состоянием веб-страницы используются три основных типа ожиданий. Использование явных ожиданий считается best practice.

1. Явные ожидания (Explicit Waits)

Наиболее гибкий и рекомендуемый способ. Ожидание определенного условия для конкретного элемента с заданным таймаутом.

import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.support.ui.ExpectedConditions;
import java.time.Duration;

// Создание объекта ожидания (таймаут 10 секунд, опрос каждые 500ms по умолчанию)
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));

// Ожидание появления элемента и клик по нему
WebElement button = wait.until(
    ExpectedConditions.elementToBeClickable(By.id("submit-button"))
);
button.click();

// Другие полезные условия:
// - visibilityOfElementLocated
// - presenceOfElementLocated
// - textToBePresentInElement
// - invisibilityOfElementLocated

2. Неявные ожидания (Implicit Waits)

Глобальная настройка для драйвера. При поиске любого элемента драйвер будет ждать его появления в течение заданного времени.

// Устанавливается один раз для драйвера
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));

// Последующий поиск будет ждать до 5 секунд
driver.findElement(By.name("q")).sendKeys("Selenium");

Недостаток: Применяется ко всем findElement вызовам, может замедлять тесты, если элемент отсутствует. Не рекомендуется смешивать с явными ожиданиями.

3. Жесткая пауза (Thread.sleep) - НЕ РЕКОМЕНДУЕТСЯ

Приостанавливает выполнение потока на фиксированное время независимо от состояния приложения.

// АНТИПАТТЕРН. Избегайте этого в продакшн-тестах.
try {
    Thread.sleep(3000); // Ждет ровно 3 секунды
} catch (InterruptedException e) {
    e.printStackTrace();
}

Почему это плохо:

  • Делает тесты медленными и нестабильными.
  • Не адаптируется к реальной скорости загрузки страницы.
  • Маскирует реальные проблемы с производительностью.

Рекомендация

Всегда отдавайте предпочтение явным ожиданиям (Explicit Waits). Они делают тесты:

  • Более стабильными: Ждут именно того состояния, которое нужно.
  • Более быстрыми: Завершаются, как только условие выполнено.
  • Более читаемыми: Явно показывают, какое состояние ожидается.

Ответ 18+ 🔞

О, смотри-ка, какой умный пришёл про ожидания в Sелиниуме рассказывать. Ну ладно, раз уж начал, давай я тебе это всё на человеческом, блядь, языке переведу, а то читаешь — глаза в кучу съезжаются.

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

1. Явные ожидания (Explicit Waits) — это наш царь и бог

Вот это, сука, правильный путь. Ты не просто тупо спишь, а говоришь драйверу: «Слушай, падла, жди вот этот конкретный элемент, пока он не станет кликабельным (или видимым, или ещё каким), но больше десяти секунд я тебе не даю — у меня терпения, блядь, ноль».

Это гибко, это точно, это красиво. Делается вот так:

import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.support.ui.ExpectedConditions;
import java.time.Duration;

// Создаём сторожа, который будет ждать, но не больше 10 секунд
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));

// И говорим ему: «Кабанчик, сиди и смотри на этот локатор, пока кнопка не станет кликабельной»
WebElement button = wait.until(
    ExpectedConditions.elementToBeClickable(By.id("submit-button"))
);
// Как только стала — тут же в неё вьебываем!
button.click();

Тут ещё куча других умных условий: жди видимости, жди исчезновения, жди пока текст появится... В общем, полный комплект для адекватного человека.

2. Неявные ожидания (Implicit Waits) — это как глобальный таймаут для ленивых

Ты один раз настраиваешь драйверу: «Братан, ищи все элементы не сразу, а подожди, блядь, секунд пять, вдруг они всплывут».

// Сказали один раз — и пошло-поехало
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));

// Теперь каждый findElement будет тихо материться и ждать эти 5 секунд, если элемента нет
driver.findElement(By.name("q")).sendKeys("Selenium");

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

3. Жёсткая пауза (Thread.sleep) — АНТИПАТТЕРН, ПИЗДЕЦ И ПОЗОР

Вот это, блядь, высшая лига распиздяйства. Ты просто вырубаешь весь тест нахуй на фиксированное время.

// Делать так — это всё равно что ебать гвоздём микроскоп
try {
    Thread.sleep(3000); // Конкретно три секунды, ни больше ни меньше, как будто ты Бог времени
} catch (InterruptedException e) {
    e.printStackTrace(); // А если что — просто поплачем в консоль
}

Почему это говно?

  • Тесты ползут, как черепахи в сиропе. Страница уже давно прогрузилась, а ты всё спишь, сука.
  • Ноль стабильности. Сегодня страница грузится 1 секунду, завтра — 4. Твой sleep(3000) то проёбывается, то зря тратит время.
  • Маскирует реальные проблемы. Вместо того чтобы найти причину тормозов, ты их просто просыпаешь. Гениально, блядь!

Итог, ёпта

Запоминай раз и навсегда, как «Отче наш»: используй только явные ожидания (Explicit Waits). Они делают тесты:

  • Стабильными — ждут именно того, что нужно.
  • Быстрыми — не тупят лишнего.
  • Понятными — даже через полгода видно, чего ты там ждал, а не гадаешь, нахуя этот Thread.sleep(5000) посреди кода вставлен.

Всё, вопрос закрыт. Иди, делай как умные люди, а не как мартышлюшка с молотком.