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 Text | Sign 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 | Ждет конкретное условие | Всегда (точный, читаемый) |
| Fluent | Explicit + кастомный 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)
Официальные ресурсы
Смотрите также
- Playwright: Полное Руководство - Современная альтернатива с лучшим developer experience
- Cypress Tutorial - E2E-тестирование с фокусом на JavaScript
- Selenium WebDriver 2025 - Глубокое погружение в продвинутые возможности Selenium
- TestNG vs JUnit5 - Сравнение тестовых фреймворков для Java Selenium проектов
