⚖️ Старый vs Новый: антипаттерны и современный подход

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

Этот раздел показывает устаревшие паттерны из лекции и их современную замену на Selenium 4.x. Старый код показан только для понимания — не копируйте его в продакшн.

1. Alert: time.sleep → EC.alert_is_present()

Из лекции (старое — антипаттерн)

# test_alert_old.py — из лекции (старое)
import time
from selenium import webdriver

driver = webdriver.Chrome()
driver.get("URL_СТРАНИЦЫ")

# Жёсткое ожидание перед обращением к alert
time.sleep(2)
alert = driver.switch_to.alert
print(alert.text)
alert.accept()
Проблема: time.sleep(2) — фиксированная задержка. Если Alert появился раньше, тест теряет время. Если позже — тест упадёт с NoAlertPresentException.

Современный подход (Selenium 4.x)

# test_alert_new.py — современный подход
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
driver.get("URL_СТРАНИЦЫ")

# Ждём Alert надёжно
wait = WebDriverWait(driver, 10)
alert = wait.until(EC.alert_is_present())
print(alert.text)
alert.accept()

2. Drag and Drop: time.sleep → явное ожидание состояния

Из лекции (старое — содержит time.sleep)

# Из лекции (старое) — использование time.sleep для ожидания анимации
import time
from selenium.webdriver.common.action_chains import ActionChains

actions = ActionChains(driver)
actions.drag_and_drop(photo, trash).perform()
time.sleep(2)  # Ожидание завершения анимации

# Проверка
photos_in_trash = len(driver.find_elements(...))
Проблема: time.sleep(2) после drag&drop — ненадёжно. При медленной сети анимация занимает больше. При быстрой — тест лишние 2 секунды ждёт впустую.

Современный подход (Selenium 4.x)

# test_dnd_new.py — современный подход
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

actions = ActionChains(driver)
actions.drag_and_drop(source, target).perform()

# Ждать конкретного состояния — появления элемента в зоне drop
wait = WebDriverWait(driver, 10)
wait.until(EC.text_to_be_present_in_element((By.ID, "droppable"), "Dropped"))

3. iframe: поиск без переключения → switch_to.frame()

Типичная ошибка (неправильно)

# НЕПРАВИЛЬНО — попытка найти элемент внутри iframe без переключения
driver.get("https://example.com/page-with-iframe.html")
element = driver.find_element(By.ID, "element-inside-iframe")
# Выбросит: NoSuchElementException
Проблема: Selenium ищет элементы только в текущем контексте. iframe — это отдельный документ. Без switch_to.frame() элементы внутри iframe невидимы.

Правильный подход

# ПРАВИЛЬНО — переключиться в iframe сначала
from selenium.webdriver.common.by import By

iframe = driver.find_element(By.ID, "my-iframe")
driver.switch_to.frame(iframe)

# Теперь найдём элемент
element = driver.find_element(By.ID, "element-inside-iframe")

# Не забыть вернуться!
driver.switch_to.default_content()

4. Загрузка файла: относительный путь → абсолютный путь

Типичная ошибка (из лекции)

# Из лекции — использование относительного пути (ненадёжно)
file_path = "/path/to/your/file.txt"  # Прямой путь
file_input.send_keys(file_path)
Проблема: при запуске из разных рабочих директорий относительный путь не найдёт файл. На Windows слэши тоже могут быть проблемой.

Правильный подход (Selenium 4.x)

# ПРАВИЛЬНО — абсолютный путь через os или pathlib
import os
from pathlib import Path

# Вариант 1: os.path.abspath
file_path = os.path.abspath("test_data/file.txt")
file_input.send_keys(file_path)

# Вариант 2: pathlib (рекомендуется для Python 3.4+)
file_path = str(Path("test_data/file.txt").resolve())
file_input.send_keys(file_path)

5. Переключение вкладок: без явного switch_to → надёжная навигация

Типичная ошибка

# НЕПРАВИЛЬНО — попытка работать с новой вкладкой без переключения
driver.execute_script("window.open('https://google.com', '_blank');")
# Selenium всё ещё работает на первой вкладке!
title = driver.title  # Вернёт заголовок ПЕРВОЙ вкладки, не Google

Правильный подход

# ПРАВИЛЬНО — явно переключаться после открытия
driver.execute_script("window.open('https://google.com', '_blank');")

tabs = driver.window_handles
driver.switch_to.window(tabs[-1])  # Переключиться на последнюю открытую вкладку

title = driver.title  # Теперь заголовок Google