🐛 Частые ошибки с ожиданиями
⚡ Топ-6 ошибок с ожиданиями
- TimeoutException — элемент не появился за отведённое время. Увеличить timeout или проверить локатор.
- Смешивание implicit + explicit — непредсказуемые задержки. Использовать только явное.
- time.sleep вместо EC — медленно и ненадёжно. Заменить на WebDriverWait.
- presence вместо visibility — элемент найден, но скрыт, клик выбрасывает исключение.
- StaleElementReferenceException — DOM обновился, элемент устарел. Перенайти элемент.
- TimeoutException с WebDriverWait — timeout меньше реальной задержки. Для slow calculator — не менее 50 сек.
Ошибка 1: TimeoutException — элемент не появился
selenium.common.exceptions.TimeoutException: Message: Элемент не удовлетворил условию EC за указанный timeout.
# Причина: слишком маленький timeout
wait = WebDriverWait(driver, 2) # Только 2 секунды
button = wait.until(
EC.presence_of_element_located((By.XPATH, "//button[text()='Button Appearing After Delay']"))
)
# Если кнопка появляется через 5 секунд — TimeoutException
# Решение: увеличить timeout
wait = WebDriverWait(driver, 15)
button = wait.until(
EC.presence_of_element_located((By.XPATH, "//button[text()='Button Appearing After Delay']"))
)
Диагностика: если тест стабильно падает с TimeoutException, откройте страницу вручную и замерьте реальное время появления элемента. Установите timeout с запасом 20–30%.
Ошибка 2: Смешивание implicitly_wait и WebDriverWait
Использование обоих методов в одном тесте: таймауты складываются, поведение становится непредсказуемым.
# ПЛОХО: оба ожидания вместе
@pytest.fixture
def driver():
driver = webdriver.Chrome()
driver.implicitly_wait(10) # Глобальное ожидание
yield driver
driver.quit()
def test_example(driver):
wait = WebDriverWait(driver, 5) # Явное ожидание
# Реальный timeout может быть 10+5 = 15 секунд или непредсказуемым
element = wait.until(EC.presence_of_element_located((By.ID, "btn")))
# ХОРОШО: только явное ожидание
@pytest.fixture
def driver():
driver = webdriver.Chrome()
# Без implicitly_wait
yield driver
driver.quit()
def test_example(driver):
wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.ID, "btn")))
Ошибка 3: time.sleep() для AJAX
Фиксированная задержка ненадёжна: медленнее нужного — потеря времени, быстрее — тест падает.
# ПЛОХО
ajax_button.click()
time.sleep(15) # Всегда ждём 15 секунд
text_element = driver.find_element(By.CLASS_NAME, "bg-success")
# ХОРОШО
ajax_button.click()
wait.until(
EC.text_to_be_present_in_element((By.CLASS_NAME, "bg-success"), "Data loaded")
) # Завершится сразу после появления текста
Ошибка 4: presence вместо visibility для клика
Элемент есть в DOM, но скрыт. Клик по скрытому элементу →
ElementNotInteractableException.
# ПЛОХО: presence_of_element_located находит скрытый элемент
button = wait.until(EC.presence_of_element_located((By.ID, "submit-btn")))
button.click() # ElementNotInteractableException, если кнопка скрыта!
# ХОРОШО: element_to_be_clickable проверяет видимость и активность
button = wait.until(EC.element_to_be_clickable((By.ID, "submit-btn")))
button.click()
Правило: если нужно кликнуть — используйте
element_to_be_clickable. presence_of_element_located подходит только для чтения атрибутов/текста скрытых элементов.
Ошибка 5: StaleElementReferenceException
После AJAX-обновления страницы старая ссылка на элемент устаревает. Selenium выбрасывает
StaleElementReferenceException.
# ПЛОХО: нашли элемент до AJAX-обновления, пытаемся использовать после
old_element = driver.find_element(By.ID, "content")
ajax_button.click() # Страница обновляется через AJAX
old_element.text # StaleElementReferenceException!
# ХОРОШО: найти элемент заново после обновления
ajax_button.click()
wait.until(EC.staleness_of(old_element)) # Ждём исчезновения старого элемента
new_element = wait.until(EC.visibility_of_element_located((By.ID, "content")))
print(new_element.text)
Ошибка 6: Неверный timeout для slow calculator
Для slow calculator с задержкой 45 секунд нельзя устанавливать timeout = 45 или меньше.
# ПЛОХО: timeout равен задержке — риск падения из-за задержек сети
wait = WebDriverWait(driver, 45)
result = wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR, ".screen"), "15"))
# ХОРОШО: запас сверху
wait = WebDriverWait(driver, 50) # 45 сек задержка + 5 сек запас
result = wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR, ".screen"), "15"))
Ошибка 7: Не вызывать clear() перед send_keys()
# ПЛОХО: поле может содержать старое значение
field = driver.find_element(By.NAME, "username")
field.send_keys("Admin") # Может получиться "OldValueAdmin"
# ХОРОШО
field = driver.find_element(By.NAME, "username")
field.clear()
field.send_keys("Admin")