🐛 Типичные ошибки
⚡ Топ-5 ошибок урока
- NoAlertPresentException: не ждали появления alert — используйте
EC.alert_is_present() - Iframe-ловушка: забыли
switch_to.default_content()— все следующие поиски элементов будут внутри iframe - Вкладка не переключилась: вызвали
driver.close()без последующегоswitch_to.window() - Drag&drop не работает: HTML5 DnD API не реагирует на стандартный
drag_and_drop()— нужен JS-inject - Загрузка файла: передали относительный путь вместо абсолютного — файл не найден
1. NoAlertPresentException — не ждали Alert
Симптом
selenium.common.exceptions.NoAlertPresentException: Message: no such alert
Причина
Обращение к Alert до того, как он появился:
# НЕПРАВИЛЬНО — alert может ещё не появиться
browser.find_element(By.ID, "submit").click()
alert = browser.switch_to.alert # Ошибка: alert ещё не на экране
Исправление
# ПРАВИЛЬНО — ждём через EC
browser.find_element(By.ID, "submit").click()
wait = WebDriverWait(browser, 10)
alert = wait.until(EC.alert_is_present()) # Ждём до 10 секунд
alert.accept()
2. Iframe-ловушка — забыли вернуться в основной контекст
Симптом
selenium.common.exceptions.NoSuchElementException: no such element
# Элемент существует на странице, но Selenium его «не видит»
Причина
После работы с iframe контекст Selenium остался внутри фрейма:
# НЕПРАВИЛЬНО
driver.switch_to.frame(iframe)
content = driver.find_element(By.ID, "inside")
# Забыли default_content() — следующий поиск будет в iframe контексте!
header = driver.find_element(By.TAG_NAME, "h1") # NoSuchElementException
Исправление
# ПРАВИЛЬНО
driver.switch_to.frame(iframe)
content = driver.find_element(By.ID, "inside")
driver.switch_to.default_content() # Обязательно возвращаемся!
header = driver.find_element(By.TAG_NAME, "h1") # Работает
3. Вкладка закрыта — не переключились обратно
Симптом
selenium.common.exceptions.NoSuchWindowException: no such window: target window already closed
Причина
После driver.close() Selenium всё ещё «смотрит» на закрытое окно:
# НЕПРАВИЛЬНО
tabs = driver.window_handles
driver.switch_to.window(tabs[1])
driver.close()
# Забыли переключиться! Любое действие упадёт
driver.find_element(By.ID, "something") # NoSuchWindowException
Исправление
# ПРАВИЛЬНО
tabs = driver.window_handles
driver.switch_to.window(tabs[1])
driver.close()
driver.switch_to.window(tabs[0]) # Обязательно возвращаемся
driver.find_element(By.ID, "something") # Работает
4. Drag and Drop не работает с HTML5 DnD
Симптом
Метод выполняется без ошибки, но элемент визуально не перетаскивается. Тест падает при проверке результата.
Причина
Некоторые современные drag&drop реализации используют HTML5 Drag and Drop API, которая не обрабатывает синтетические события Selenium стандартным образом. Пример: globalsqa.com/demo-site/draganddrop/.
# РАБОТАЕТ на jQuery UI drag-and-drop (crossbrowsertesting.github.io)
ActionChains(browser).drag_and_drop(source, target).perform()
# НЕ РАБОТАЕТ на некоторых HTML5 DnD реализациях
Исправление (JS-inject)
# test_drag_drop_js.py
# Альтернативный подход через JavaScript для HTML5 DnD:
js_drag_drop = """
function simulateDragDrop(sourceNode, destinationNode) {
var EVENT_TYPES = ['dragstart','dragenter','dragover','drop','dragend'];
function createEvent(type) {
var event = new DragEvent(type, {bubbles: true, cancelable: true});
return event;
}
sourceNode.dispatchEvent(createEvent('dragstart'));
destinationNode.dispatchEvent(createEvent('dragenter'));
destinationNode.dispatchEvent(createEvent('dragover'));
destinationNode.dispatchEvent(createEvent('drop'));
sourceNode.dispatchEvent(createEvent('dragend'));
}
simulateDragDrop(arguments[0], arguments[1]);
"""
browser.execute_script(js_drag_drop, source, target)
5. Загрузка файла: относительный путь
Симптом
Файл не загружается, форма отправляется пустой или тест падает с ошибкой валидации.
Причина
# НЕПРАВИЛЬНО — относительный путь зависит от cwd при запуске pytest
file_input.send_keys("test.txt")
# НЕПРАВИЛЬНО на Windows — слэши без экранирования или raw-строки
file_input.send_keys("C:\Users\user\test.txt") # \U, \t — escape-последовательности Python!
Исправление
# ПРАВИЛЬНО — всегда абсолютный путь через os.path.abspath
import os
file_path = os.path.abspath("test.txt")
file_input.send_keys(file_path)
# Или через __file__ для независимости от cwd
base_dir = os.path.dirname(os.path.abspath(__file__))
file_path = os.path.join(base_dir, "test.txt")
file_input.send_keys(file_path)
6. StaleElementReferenceException после switch_to
Симптом
selenium.common.exceptions.StaleElementReferenceException: stale element reference
Причина
Элемент был найден до переключения контекста (в iframe или на другой вкладке). После switch_to контекст меняется — элемент устаревает:
# НЕПРАВИЛЬНО — нашли элемент до переключения во фрейм
element = driver.find_element(By.ID, "inside-iframe") # Находим до switch
driver.switch_to.frame(iframe)
element.click() # StaleElementReferenceException
Исправление
# ПРАВИЛЬНО — находим элементы ПОСЛЕ переключения контекста
driver.switch_to.frame(iframe)
element = driver.find_element(By.ID, "inside-iframe") # Находим после switch
element.click() # Работает
7. ActionChains: reset_actions не вызван — старые действия накапливаются
Симптом
Тест ведёт себя нестабильно: иногда выполняет лишние клики или hover.
Причина
# ПОТЕНЦИАЛЬНАЯ ОШИБКА — объект actions переиспользуется без сброса
actions = ActionChains(browser)
actions.move_to_element(menu1).perform()
# В следующем тесте/шаге:
actions.move_to_element(menu2).perform()
# Выполнится: move_to_element(menu1) + move_to_element(menu2)!
# Потому что actions накопил предыдущее действие
Исправление
# ПРАВИЛЬНО — создавайте новый объект или вызывайте reset_actions()
actions = ActionChains(browser) # Новый объект для каждого действия
actions.move_to_element(menu1).perform()
actions = ActionChains(browser) # Или: новый объект
actions.move_to_element(menu2).perform()