TL;DR

  • Selenium WebDriver автоматизирует реальные браузеры (Chrome, Firefox, Safari, Edge) для тестирования веб-приложений
  • Начни с Python — проще синтаксис, быстрее обратная связь для новичков
  • Освой локаторы (ID, CSS, XPath) и явные ожидания до написания сложных тестов
  • Используй Page Object Model с первого дня — рефакторить потом больно

Подходит для: QA-инженеров, начинающих автоматизацию браузеров, разработчиков, пишущих E2E-тесты Пропусти, если: Нужно только API-тестирование (используй Postman) или уже знаешь Playwright/Cypress Время чтения: 15 минут

Твой первый Selenium-тест скорее всего упадет. Не потому что Selenium сломан, а потому что веб-автоматизация имеет проблемы с таймингом, которые ты раньше не встречал. Элементы загружаются асинхронно. Кнопки становятся кликабельными после выполнения JavaScript. Формы валидируются на blur.

Этот туториал научит тебя Selenium правильно — с обработкой этих реальных проблем с самого начала.

Что такое Selenium WebDriver?

Selenium WebDriver — инструмент автоматизации браузеров, который программно управляет реальными браузерами. В отличие от инструментов, симулирующих браузеры, Selenium управляет настоящими экземплярами Chrome, Firefox, Safari и Edge.

Основные компоненты:

  • WebDriver API — языковые привязки (Python, Java, C#, JavaScript, Ruby)
  • Browser drivers — ChromeDriver, GeckoDriver, SafariDriver
  • Selenium Grid — распределенное выполнение тестов на нескольких машинах

Selenium бесплатный, open-source и поддерживается большим сообществом. Это фундамент, на котором строятся такие инструменты как Appium (мобильный) и Selenide (Java-обертка).

Настройка окружения

Настройка Python

# Установить Selenium
pip install selenium

# Установить WebDriver Manager (авто-загрузка драйверов)
pip install webdriver-manager
# test_first.py
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager

# Автоматическое управление драйверами
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))

driver.get("https://example.com")
print(f"Заголовок страницы: {driver.title}")

driver.quit()

Настройка Java

<!-- pom.xml -->
<dependencies>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>4.18.1</version>
    </dependency>
    <dependency>
        <groupId>io.github.bonigarcia</groupId>
        <artifactId>webdrivermanager</artifactId>
        <version>5.7.0</version>
    </dependency>
</dependencies>
// FirstTest.java
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import io.github.bonigarcia.wdm.WebDriverManager;

public class FirstTest {
    public static void main(String[] args) {
        WebDriverManager.chromedriver().setup();
        WebDriver driver = new ChromeDriver();

        driver.get("https://example.com");
        System.out.println("Заголовок: " + driver.getTitle());

        driver.quit();
    }
}

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

Локаторы находят элементы на странице. Выбери правильную стратегию для поддерживаемых тестов.

Приоритет (от лучшего к худшему)

СтратегияПримерКогда использовать
ID#login-buttonУникальные ID (лучший вариант)
Name[name="email"]Поля форм
CSS Selector.btn.primaryБольшинство элементов
Link TextSign InСсылки со стабильным текстом
XPath//div[@class='card']Сложные связи

Примеры Python

from selenium.webdriver.common.by import By

# По ID (быстрее всего, надежнее всего)
driver.find_element(By.ID, "username")

# По CSS Selector (гибко, читаемо)
driver.find_element(By.CSS_SELECTOR, "button.submit-btn")
driver.find_element(By.CSS_SELECTOR, "[data-testid='login']")

# По XPath (когда CSS не работает)
driver.find_element(By.XPATH, "//button[contains(text(), 'Submit')]")
driver.find_element(By.XPATH, "//div[@class='form']//input[@type='email']")

# По Link Text
driver.find_element(By.LINK_TEXT, "Forgot Password?")
driver.find_element(By.PARTIAL_LINK_TEXT, "Forgot")

Примеры Java

import org.openqa.selenium.By;

// По ID
driver.findElement(By.id("username"));

// По CSS Selector
driver.findElement(By.cssSelector("button.submit-btn"));
driver.findElement(By.cssSelector("[data-testid='login']"));

// По XPath
driver.findElement(By.xpath("//button[contains(text(), 'Submit')]"));

// По Link Text
driver.findElement(By.linkText("Forgot Password?"));

Ожидания: Самая важная концепция

90% нестабильных Selenium-тестов падают из-за тайминга. Элементы не готовы, когда твой код пытается с ними взаимодействовать.

Типы ожиданий

ТипКак работаетКогда использовать
ImplicitОпрашивает DOM N секундНикогда (глобальный, скрывает проблемы)
ExplicitЖдет конкретное условиеВсегда (точный, читаемый)
FluentExplicit + кастомный pollingМедленно загружающиеся элементы

Явные ожидания (Python)

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

wait = WebDriverWait(driver, 10)  # Макс 10 секунд

# Ждать, пока элемент станет кликабельным
button = wait.until(EC.element_to_be_clickable((By.ID, "submit")))
button.click()

# Ждать, пока элемент станет видимым
message = wait.until(EC.visibility_of_element_located((By.CLASS_NAME, "success")))

# Ждать, пока элемент исчезнет
wait.until(EC.invisibility_of_element_located((By.ID, "loading")))

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

# Кастомное условие
wait.until(lambda d: len(d.find_elements(By.CLASS_NAME, "item")) > 5)

Явные ожидания (Java)

import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.support.ui.ExpectedConditions;
import java.time.Duration;

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));

// Ждать кликабельности
WebElement button = wait.until(
    ExpectedConditions.elementToBeClickable(By.id("submit"))
);
button.click();

// Ждать видимости
WebElement message = wait.until(
    ExpectedConditions.visibilityOfElementLocated(By.className("success"))
);

// Ждать исчезновения
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.id("loading")));

Полный пример теста

Тест логина (Python)

# tests/test_login.py
import pytest
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
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager

class TestLogin:
    def setup_method(self):
        self.driver = webdriver.Chrome(
            service=Service(ChromeDriverManager().install())
        )
        self.driver.implicitly_wait(0)  # Отключить implicit waits
        self.wait = WebDriverWait(self.driver, 10)

    def teardown_method(self):
        self.driver.quit()

    def test_successful_login(self):
        self.driver.get("https://example.com/login")

        # Заполнить форму
        email_input = self.wait.until(
            EC.visibility_of_element_located((By.ID, "email"))
        )
        email_input.send_keys("user@example.com")

        password_input = self.driver.find_element(By.ID, "password")
        password_input.send_keys("password123")

        # Отправить форму
        submit_btn = self.driver.find_element(By.CSS_SELECTOR, "[type='submit']")
        submit_btn.click()

        # Проверить редирект на dashboard
        self.wait.until(EC.url_contains("/dashboard"))

        welcome_message = self.wait.until(
            EC.visibility_of_element_located((By.CLASS_NAME, "welcome"))
        )
        assert "Welcome" in welcome_message.text

    def test_invalid_credentials(self):
        self.driver.get("https://example.com/login")

        self.wait.until(
            EC.visibility_of_element_located((By.ID, "email"))
        ).send_keys("invalid@example.com")

        self.driver.find_element(By.ID, "password").send_keys("wrongpass")
        self.driver.find_element(By.CSS_SELECTOR, "[type='submit']").click()

        error_message = self.wait.until(
            EC.visibility_of_element_located((By.CLASS_NAME, "error"))
        )
        assert "Invalid credentials" in error_message.text

Page Object Model

Page Object Model (POM) разделяет структуру страницы и логику тестов. Каждая страница становится классом с элементами и действиями.

Python Page Object

# pages/login_page.py
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class LoginPage:
    URL = "https://example.com/login"

    # Локаторы
    EMAIL_INPUT = (By.ID, "email")
    PASSWORD_INPUT = (By.ID, "password")
    SUBMIT_BUTTON = (By.CSS_SELECTOR, "[type='submit']")
    ERROR_MESSAGE = (By.CLASS_NAME, "error")

    def __init__(self, driver):
        self.driver = driver
        self.wait = WebDriverWait(driver, 10)

    def open(self):
        self.driver.get(self.URL)
        self.wait.until(EC.visibility_of_element_located(self.EMAIL_INPUT))
        return self

    def login(self, email: str, password: str):
        self.driver.find_element(*self.EMAIL_INPUT).send_keys(email)
        self.driver.find_element(*self.PASSWORD_INPUT).send_keys(password)
        self.driver.find_element(*self.SUBMIT_BUTTON).click()

    def get_error_message(self) -> str:
        error = self.wait.until(
            EC.visibility_of_element_located(self.ERROR_MESSAGE)
        )
        return error.text
# tests/test_login_pom.py
import pytest
from pages.login_page import LoginPage
from pages.dashboard_page import DashboardPage

class TestLoginPOM:
    def test_successful_login(self, driver):
        login_page = LoginPage(driver)
        login_page.open()
        login_page.login("user@example.com", "password123")

        dashboard = DashboardPage(driver)
        assert dashboard.is_loaded()
        assert "Welcome" in dashboard.get_welcome_text()

    def test_invalid_login(self, driver):
        login_page = LoginPage(driver)
        login_page.open()
        login_page.login("invalid@example.com", "wrongpass")

        assert "Invalid credentials" in login_page.get_error_message()

Headless режим и CI/CD

Headless браузер

from selenium.webdriver.chrome.options import Options

options = Options()
options.add_argument("--headless=new")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
options.add_argument("--window-size=1920,1080")

driver = webdriver.Chrome(options=options)

Интеграция с GitHub Actions

# .github/workflows/selenium-tests.yml
name: Selenium Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install dependencies
        run: |
          pip install selenium pytest webdriver-manager

      - name: Run tests
        run: pytest tests/ -v --tb=short

      - name: Upload screenshots
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: screenshots
          path: screenshots/

AI-Assisted разработка Selenium

AI-инструменты могут ускорить разработку Selenium-тестов при правильном использовании.

Что AI делает хорошо:

  • Генерация локаторов из HTML-сниппетов
  • Конвертация ручных тест-кейсов в код Selenium
  • Написание шаблонов Page Object
  • Объяснение непонятных сообщений об ошибках
  • Предложение стратегий ожидания для конкретных сценариев

Что всё ещё требует людей:

  • Решение, какие тесты автоматизировать
  • Отладка нестабильности связанной с таймингом
  • Выбор между стратегиями локаторов для неоднозначных элементов
  • Понимание специфического поведения приложения

Полезный промпт:

У меня есть эта HTML форма:
<form id="login">
  <input type="email" name="email" placeholder="Email">
  <input type="password" name="password">
  <button type="submit">Sign In</button>
</form>

Напиши Selenium Python тест, который:
1. Заполняет email и password
2. Отправляет форму
3. Ждет редиректа на /dashboard
4. Проверяет появление welcome-сообщения

Используй явные ожидания и правильные локаторы.

FAQ

Сложно ли изучить Selenium?

Основы Selenium изучаются за 2-4 недели. WebDriver API простой — find_element(), click(), send_keys(). Сложность в освоении ожиданий, выборе стабильных локаторов и структурировании тестов с Page Object Model. Практикуйся на реальном приложении, а не только на туториалах.

Какой язык лучше для Selenium?

Python для начинающих — простой синтаксис, быстрая обратная связь, отличная документация. Java для enterprise-проектов с существующей Java-инфраструктурой и CI/CD. JavaScript, если команда уже использует Node.js. Все языки имеют зрелую поддержку Selenium.

Актуален ли Selenium в 2026?

Да. Selenium остается индустриальным стандартом с крупнейшим сообществом, большинством туториалов и широчайшей поддержкой браузеров. Хотя Playwright и Cypress предлагают лучший developer experience, Selenium интегрируется с большим количеством инструментов и имеет больше enterprise-adoption.

В чем разница между Selenium и Playwright?

Selenium управляет браузерами через протокол WebDriver (стандарт W3C). Playwright использует Chrome DevTools Protocol для Chromium-браузеров. Playwright имеет лучшее авто-ожидание, встроенные assertions, trace viewer и параллельное выполнение. Selenium имеет более широкую поддержку браузеров и больше ресурсов для обучения. Для новых проектов с фокусом на Chromium, Playwright часто лучший выбор. Для существующих проектов или нужд Safari/legacy — Selenium остается надежным.

Когда выбирать Selenium

Выбирай Selenium когда:

  • Команда имеет существующую экспертизу в Selenium
  • Нужна поддержка Safari или legacy-браузеров
  • Корпоративная среда с Selenium-инфраструктурой
  • Хочешь максимальную поддержку сообщества
  • Используешь Appium для мобильных (тот же API)

Рассмотри альтернативы когда:

  • Начинаешь с нуля с фокусом на Chromium (Playwright)
  • Компонентное тестирование с JavaScript-фреймворком (Cypress)
  • Предпочитаешь авто-ожидание и проще API (Playwright)
  • Нужна запись видео и trace debugging (Playwright)

Официальные ресурсы

Смотрите также