⚖️ Старый vs Новый — Антипаттерны ожиданий
⚡ Правило
time.sleep и implicitly_wait — из лекции как "как не надо". Современный стандарт: WebDriverWait + EC.
Откуда взялись антипаттерны? В лекции показаны три подхода к ожиданиям, включая time.sleep и implicitly_wait, чтобы объяснить, почему они не рекомендуются. Реальные проекты используют явные ожидания (WebDriverWait + EC).
Антипаттерн 1: time.sleep() — жёсткое ожидание
Из лекции (устаревший подход)
# test_sleep_bad.py ← АНТИПАТТЕРН из лекции
import time
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://example.com")
# Жёстко ждём 5 секунд — плохая практика
time.sleep(5)
element = driver.find_element("id", "some_id")
Современный подход
# test_explicit_good.py ← ПРАВИЛЬНО: Selenium 4 + явное ожидание
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get("https://example.com")
# Ждём ровно столько, сколько нужно — не больше, не меньше
wait = WebDriverWait(driver, 10)
element = wait.until(EC.presence_of_element_located((By.ID, "some_id")))
| Аспект | time.sleep (старое) | WebDriverWait + EC (новое) |
|---|---|---|
| Скорость | Всегда ждёт максимум | Завершается сразу после выполнения условия |
| Надёжность | Ненадёжен: может не хватить времени | Надёжен: бросает TimeoutException если не дождался |
| Условия | Нет условий — просто таймер | 10+ предопределённых условий на выбор |
| Code review | Обычно отклоняется | Стандарт индустрии |
Антипаттерн 2: implicitly_wait — неявное ожидание
Из лекции (показан как "нерекомендуемый" вариант)
# test_implicit_bad.py ← Из лекции как пример для сравнения
import pytest
from selenium import webdriver
from selenium.webdriver.common.by import By
@pytest.fixture
def driver():
driver = webdriver.Chrome()
driver.implicitly_wait(15) # Глобальное неявное ожидание до 15 секунд
driver.get("http://www.uitestingplayground.com/ajax")
yield driver
driver.quit()
def test_ajax_request_implicit(driver):
# Нажимаем на кнопку AJAX-запроса
ajax_button = driver.find_element(By.ID, "ajaxButton")
ajax_button.click()
# Selenium ждёт до 15 сек, пока элемент появится в DOM
ajax_text_element = driver.find_element(By.CLASS_NAME, "bg-success")
# НО: мы не ждём конкретного текста — только появления элемента!
assert "Data loaded with AJAX get request." in ajax_text_element.text, \
"Текст не загрузился!"
# Проблема: если текст появляется после элемента, тест упадёт
Современный подход (из лекции как «правильный»)
# test_ajax_explicit_good.py ← ПРАВИЛЬНО: ждём конкретного текста
import pytest
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
@pytest.fixture
def driver():
driver = webdriver.Chrome()
driver.get("http://www.uitestingplayground.com/ajax")
yield driver
driver.quit()
def test_ajax_request(driver):
wait = WebDriverWait(driver, 15)
ajax_button = driver.find_element(By.ID, "ajaxButton")
ajax_button.click()
# Ждём именно текст в элементе — не просто наличие элемента
ajax_text = wait.until(
EC.text_to_be_present_in_element(
(By.CLASS_NAME, "bg-success"), "Data loaded with AJAX get request."
)
)
assert ajax_text, "Текст 'Data loaded with AJAX get request.' не появился!"
| Аспект | implicitly_wait (ограниченно) | WebDriverWait + EC (рекомендуется) |
|---|---|---|
| Область действия | Глобально — все find_element | Точечно — конкретный вызов |
| Что ждёт | Только появление элемента в DOM | Любое условие: текст, видимость, кликабельность |
| AJAX | Ждёт элемент, не текст → может не сработать | Ждёт конкретный текст → надёжно |
| Смешивание | При смешивании с WebDriverWait — хаос | Безопасно использовать отдельно |
Сводка: из лекции (старое) → современное
| Из лекции (показано для сравнения) | Современный стандарт (Selenium 4) | Причина |
|---|---|---|
time.sleep(5) |
wait.until(EC.presence_of_element_located(...)) |
Динамическое ожидание быстрее и надёжнее |
driver.implicitly_wait(10) для AJAX |
wait.until(EC.text_to_be_present_in_element(...)) |
Явное ожидание текста, а не только DOM |
find_element(...).click() |
wait.until(EC.element_to_be_clickable(...)).click() |
Гарантирует, что кнопка готова к нажатию |
| Смешивать implicitly_wait + WebDriverWait | Использовать только WebDriverWait + EC | Смешивание даёт непредсказуемые задержки |
Когда implicitly_wait всё же применяют: в некоторых командах его ставят один раз в фикстуре как "страховку" от ElementNotFound на очень медленных CI-серверах, но при этом никогда не смешивают с WebDriverWait в одном тесте. Явное ожидание всегда в приоритете.