📖 Теория: конспект ожиданий в 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 критически важно корректно обрабатывать ожидания загрузки элементов. Если этого не делать, тест будет нестабильным: иногда проходить, иногда падать — потому что элемент ещё не успел загрузиться.
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")
- Неэффективен: если страница загружается быстрее, тест просто теряет время
- Ненадёжен: если страница загружается медленнее таймаута — тест упадёт
- Замедляет весь тестовый набор
Таблица сравнения методов ожидания
| Метод | Применение | Плюсы | Минусы |
|---|---|---|---|
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 — это технология, позволяющая загружать данные с сервера без перезагрузки страницы. Примеры использования в реальных приложениях:
- Загрузка комментариев по кнопке
- Автодополнение полей поиска
- Обновление данных таблицы без полной перезагрузки
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(), если поле могло содержать предыдущее значение. Это особенно критично при повторном запуске теста.