📖 Теория: конспект ожиданий в Selenium (Урок 07)

🎯 Итоговое повторение

← К оглавлению урока

⚡ Краткий конспект ожиданий

  • implicitly_wait(N) — глобальная задержка для всех find_element. Просто, но не гибко.
  • WebDriverWait + EC — явное ожидание конкретного состояния. Рекомендуется.
  • time.sleep(N) — жёсткая задержка. Антипаттерн: тест медленный и ненадёжный.
  • Ключевые EC: presence_of_element_located, visibility_of_element_located, element_to_be_clickable, text_to_be_present_in_element, url_contains.
  • AJAX — загрузка без перезагрузки страницы. Необходимы явные ожидания.
  • send_keys() — ввод текста; clear() — очистка; click() — клик.

Зачем нужны ожидания в Selenium

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

Аналогия: ожидание в Selenium — это как ожидание у двери лифта. time.sleep — стоять ровно 30 секунд вне зависимости от того, открылся ли лифт. WebDriverWait — ждать открытия дверей не дольше 30 секунд, но войти сразу, как только откроются.

Неявные ожидания (Implicit Wait)

Глобальная задержка, которая применяется ко всем методам find_element и find_elements. Устанавливается один раз для всего сеанса драйвера.

# test_implicit.py
from selenium import webdriver

driver = webdriver.Chrome()
driver.implicitly_wait(10)  # Ожидание до 10 секунд для каждого поиска элемента
driver.get("https://example.com")
element = driver.find_element("id", "some_id")  # Selenium ждёт появления до 10 секунд

Плюсы и минусы неявного ожидания

Плюсы Минусы
Простая настройка — одна строка Применяется ко всем элементам, даже если ждать не требуется
Подходит, если сайт загружается примерно одинаково Не позволяет ждать специфические условия (изменение текста, URL и т.д.)

Явные ожидания (Explicit Wait)

Позволяют ожидать конкретного состояния элемента или страницы. Используют WebDriverWait в связке с expected_conditions.

# test_explicit.py
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)  # Ожидание до 10 секунд

# Ждём появления элемента в DOM
element = wait.until(EC.presence_of_element_located((By.ID, "some_id")))

# Ждём, пока элемент станет кликабельным
clickable = wait.until(EC.element_to_be_clickable((By.ID, "button_id")))
clickable.click()

Плюсы и минусы явного ожидания

Плюсы Минусы
Можно ожидать конкретное состояние элемента Требует больше кода
Гибкость — можно использовать разные условия Нужно указывать условия вручную для каждого ожидания
Быстрее, чем неявные ожидания — не ждёт максимальное время

Жёсткие ожидания (time.sleep) — антипаттерн

time.sleep() останавливает выполнение кода на фиксированное время независимо от того, загрузился ли элемент.

# test_sleep_bad.py — АНТИПАТТЕРН
import time
from selenium import webdriver

driver = webdriver.Chrome()
driver.get("https://example.com")
time.sleep(5)  # Ожидание 5 секунд, даже если элемент появился раньше
element = driver.find_element("id", "some_id")
Почему time.sleep() — плохая практика:
  • Неэффективен: если страница загружается быстрее, тест просто теряет время
  • Ненадёжен: если страница загружается медленнее таймаута — тест упадёт
  • Замедляет весь тестовый набор

Таблица сравнения методов ожидания

Метод Применение Плюсы Минусы
implicitly_wait Глобальное ожидание элементов Упрощает код, минимальные настройки Не подходит для специфических состояний
WebDriverWait + EC Ожидание конкретных условий Гибкость, надёжность, быстрее неявного Требует больше кода
time.sleep Жёсткое ожидание Прост в использовании Медленные, нестабильные, ненадёжные тесты

Expected Conditions: все ключевые условия

presence_of_element_located

Ожидает, пока элемент появится в DOM, но не обязательно станет видимым.

wait.until(EC.presence_of_element_located((By.ID, "element_id")))

visibility_of_element_located

Ожидает, пока элемент появится в DOM и станет видимым пользователю.

wait.until(EC.visibility_of_element_located((By.CLASS_NAME, "visible-element")))

element_to_be_clickable

Ожидает, пока элемент станет кликабельным (видим и активен).

button = wait.until(EC.element_to_be_clickable((By.XPATH, "//button[text()='Submit']")))
button.click()

text_to_be_present_in_element

Ожидает, пока определённый текст появится внутри элемента.

wait.until(EC.text_to_be_present_in_element((By.TAG_NAME, "h1"), "Dashboard"))

url_contains

Ожидает, пока URL изменится и будет содержать определённую подстроку.

wait.until(EC.url_contains("dashboard"))

title_contains

Ожидает, пока заголовок страницы (title) будет содержать нужный текст. Используется для проверки загрузки нужной страницы.

wait.until(EC.title_contains("Dashboard"))

frame_to_be_available_and_switch_to_it

Ожидает, пока iframe станет доступен, и переключается на него. Используется, если тест взаимодействует с iframe.

wait.until(EC.frame_to_be_available_and_switch_to_it((By.TAG_NAME, "iframe")))

alert_is_present

Ожидает появления JavaScript-уведомления (alert). Полезно для обработки всплывающих окон.

alert = wait.until(EC.alert_is_present())
alert.accept()  # Закрыть alert

staleness_of

Ожидает, пока элемент будет удалён из DOM. Используется для проверки, что элемент исчез после выполнения действия.

wait.until(EC.staleness_of(driver.find_element(By.ID, "old-element")))

element_located_to_be_selected

Ожидает, пока чекбокс или radio-button будет выбран. Полезно при тестировании форм.

wait.until(EC.element_located_to_be_selected((By.NAME, "checkbox")))

Когда использовать каждое условие

Expected Condition Когда использовать?
presence_of_element_locatedЭлемент в DOM, но может быть скрыт
visibility_of_element_locatedЭлемент должен быть видимым
element_to_be_clickableНужно дождаться активного состояния для клика
text_to_be_present_in_elementНужно дождаться появления определённого текста
url_containsУбедиться, что произошёл переход на нужный URL
title_containsЗаголовок страницы должен содержать нужный текст
frame_to_be_available_and_switch_to_itНужно дождаться и переключиться в iframe
alert_is_presentПоявится всплывающее сообщение (JavaScript alert)
staleness_ofЭлемент должен исчезнуть из DOM
element_located_to_be_selectedЧекбокс или radio-button должен быть выбран

AJAX и явные ожидания

AJAX — это технология, позволяющая загружать данные с сервера без перезагрузки страницы. Примеры использования в реальных приложениях:

  • Загрузка комментариев по кнопке
  • Автодополнение полей поиска
  • Обновление данных таблицы без полной перезагрузки
При работе с AJAX-страницами implicitly_wait часто недостаточно — он ждёт только появления элемента, но не конкретного состояния (например, нужного текста внутри). Используйте WebDriverWait + EC.

Взаимодействие с элементами

Три базовых метода для работы с формами и кнопками:

# test_interactions.py
from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get("https://example.com")

# Поле ввода
field = driver.find_element(By.NAME, "username")
field.clear()            # Очистить поле перед вводом
field.send_keys("Admin") # Ввести текст

# Кнопка
button = driver.find_element(By.XPATH, "//button[@type='submit']")
button.click()           # Кликнуть

driver.quit()
Важно: перед send_keys() рекомендуется вызывать clear(), если поле могло содержать предыдущее значение. Это особенно критично при повторном запуске теста.