Что такое Selenium WebDriver?

Selenium WebDriver — самый устоявшийся инструмент автоматизации браузеров, используемый миллионами тестировщиков. Он предоставляет программный интерфейс для управления браузерами через протокол W3C WebDriver.

Архитектура Selenium

Тест-код (Java/Python/JS/C#)
        ↓
   API WebDriver
        ↓
   Драйвер браузера (ChromeDriver, GeckoDriver)
        ↓
   Браузер (Chrome, Firefox, Safari, Edge)

Тест-код вызывает API WebDriver, который отправляет команды драйверу конкретного браузера, управляющему реальным браузером.

Настройка Selenium

Python

pip install selenium pytest

JavaScript (WebdriverIO)

npm init -y
npm install webdriverio @wdio/cli @wdio/mocha-framework
npx wdio config

Написание первого теста

Python

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

def test_valid_login():
    driver = webdriver.Chrome()
    driver.get("https://app.example.com/login")

    driver.find_element(By.ID, "email").send_keys("admin@test.com")
    driver.find_element(By.ID, "password").send_keys("secret123")
    driver.find_element(By.CSS_SELECTOR, "button[type='submit']").click()

    wait = WebDriverWait(driver, 10)
    wait.until(EC.url_contains("/dashboard"))

    welcome = driver.find_element(By.CLASS_NAME, "welcome").text
    assert welcome == "Welcome, Admin"
    driver.quit()

Java

public class LoginTest {
  WebDriver driver;

  @BeforeMethod
  public void setup() {
    driver = new ChromeDriver();
    driver.manage().window().maximize();
  }

  @Test
  public void testValidLogin() {
    driver.get("https://app.example.com/login");
    driver.findElement(By.id("email")).sendKeys("admin@test.com");
    driver.findElement(By.id("password")).sendKeys("secret123");
    driver.findElement(By.cssSelector("button[type='submit']")).click();

    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    wait.until(ExpectedConditions.urlContains("/dashboard"));

    String welcome = driver.findElement(By.className("welcome")).getText();
    assertEquals(welcome, "Welcome, Admin");
  }

  @AfterMethod
  public void teardown() { driver.quit(); }
}

Стратегии локаторов

СтратегияПримерНадёжность
By.idBy.id("email")Высокая (если уникален)
By.cssBy.css("[data-testid='email']")Высокая
By.xpathBy.xpath("//input[@name='email']")Средняя
By.nameBy.name("email")Средняя
By.classNameBy.className("input-email")Низкая

Лучшие практики локаторов

  1. Предпочитайте data-testid: [data-testid="login-submit"]
  2. CSS-селекторы вместо XPath — они быстрее
  3. Избегайте абсолютного XPath: /html/body/div[3]/form/input[2] легко ломается
  4. Избегайте стилевых классов: .btn-primary может измениться при редизайне
  5. Относительный XPath при необходимости: //button[contains(text(), 'Submit')]

Ожидания

Неявное ожидание

driver.implicitly_wait(10)

Глобальный таймаут для поиска элементов. Просто, но может маскировать проблемы синхронизации.

Явное ожидание (Рекомендуется)

wait = WebDriverWait(driver, 10)

# Ожидание видимости элемента
element = wait.until(EC.visibility_of_element_located((By.ID, "dashboard")))

# Ожидание кликабельности
wait.until(EC.element_to_be_clickable((By.ID, "submit")))

# Ожидание появления текста
wait.until(EC.text_to_be_present_in_element((By.CLASS_NAME, "status"), "Complete"))

# Ожидание смены URL
wait.until(EC.url_contains("/dashboard"))

Продвинутые взаимодействия

API Actions

from selenium.webdriver import ActionChains

actions = ActionChains(driver)

# Наведение на элемент
actions.move_to_element(menu_item).perform()

# Перетаскивание
actions.drag_and_drop(source, target).perform()

# Правый клик
actions.context_click(element).perform()

# Двойной клик
actions.double_click(element).perform()

Работа с выпадающими списками

from selenium.webdriver.support.ui import Select

dropdown = Select(driver.find_element(By.ID, "country"))
dropdown.select_by_visible_text("Россия")
dropdown.select_by_value("RU")
dropdown.select_by_index(5)

Работа с алертами

alert = driver.switch_to.alert
alert_text = alert.text
alert.accept()    # Нажать OK
alert.dismiss()   # Нажать Отмена
alert.send_keys("текст ввода")

Работа с фреймами и окнами

# Переключение на iframe
driver.switch_to.frame("frame-name")
driver.switch_to.default_content()  # Возврат на основную страницу

# Работа с новым окном/вкладкой
original_window = driver.current_window_handle
for handle in driver.window_handles:
    if handle != original_window:
        driver.switch_to.window(handle)
        break

Скриншоты

driver.save_screenshot("screenshots/test-failure.png")

Выполнение JavaScript

driver.execute_script("window.scrollTo(0, document.body.scrollHeight)")
driver.execute_script("arguments[0].click()", hidden_button)
title = driver.execute_script("return document.title")

Лучшие практики Selenium

  1. Всегда явные ожидания — никогда Thread.sleep()
  2. Закрывайте driver в teardown — предотвращайте зомби-процессы браузера
  3. Используйте Page Object Model — отделяйте логику от деталей страниц
  4. Предпочитайте CSS-селекторы — быстрее и читаемее XPath
  5. Headless-режим для CIoptions.add_argument("--headless")
  6. Разумные таймауты — 10-30 секунд для явных ожиданий
  7. Обрабатывайте StaleElementReferenceException — перенаходите элементы при изменении DOM

Упражнение: Постройте suite тестов на Selenium

Создайте набор тестов Selenium:

  1. Настройте проект с Selenium + предпочитаемый язык
  2. Напишите класс BasePage с общими методами
  3. Создайте page objects для Login, Dashboard и Settings
  4. Напишите 5 тест-кейсов: логин, навигация, отправка формы, выбор из списка, выход
  5. Добавьте явные ожидания для всех динамических элементов
  6. Запустите тесты в режиме с интерфейсом и headless

Ключевые выводы

  • Selenium WebDriver управляет браузерами через протокол W3C WebDriver
  • Используйте явные ожидания (WebDriverWait) вместо Thread.sleep()
  • CSS-селекторы и data-testid — лучшие стратегии локаторов
  • Actions API обрабатывает сложные взаимодействия (наведение, перетаскивание, клавиатура)
  • Всегда используйте Page Object Model для поддерживаемого кода
  • Selenium поддерживает Java, Python, JavaScript, C#, Ruby и Kotlin