⚖️ Старый 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 в одном тесте. Явное ожидание всегда в приоритете.