TL;DR
- WebdriverIO оборачивает Selenium WebDriver с современным async/await синтаксисом
- Конфигурация через
wdio.conf.js— поддерживает Mocha, Jasmine, Cucumber из коробки- Селекторы:
$('selector')для одного,$$('selector')для множества элементов- Встроенные ожидания, повторы и мощная библиотека assertions
- Первоклассная поддержка TypeScript и отличная интеграция с VS Code
Идеально для: Node.js команд, желающих Selenium-тестирование с современным JavaScript Пропусти, если: Предпочитаешь скорость Playwright или отладку Cypress Время чтения: 15 минут
Твои Selenium тесты на Java работают, но выглядят устаревшими. Команда знает JavaScript. Ты хочешь современный async/await, а не callback hell. Тебе нужна поддержка TypeScript без борьбы с фреймворком.
WebdriverIO приносит Selenium в экосистему Node.js правильно. Реальная автоматизация браузера, современный синтаксис, архитектура плагинов, которая реально работает.
Этот туториал охватывает WebdriverIO от установки до CI/CD — всё для построения поддерживаемых браузерных тестов на JavaScript.
Что такое WebdriverIO?
WebdriverIO (WDIO) — фреймворк автоматизации тестов для Node.js. Он реализует протокол WebDriver, как и Selenium, но с нативным JavaScript-дизайном.
Почему WebdriverIO:
- Современный JavaScript — async/await везде, никаких callback-пирамид
- Гибкость протокола — WebDriver для кросс-браузерности, DevTools для Chrome
- Богатая экосистема — репортеры, сервисы, плагины для всего
- Мультиплатформенность — браузеры, мобильные (Appium), десктоп (Electron)
- TypeScript first — полные определения типов, автодополнение работает
Установка и настройка
Быстрый старт
# Создать проект
mkdir wdio-tests && cd wdio-tests
npm init -y
# Установить WebdriverIO CLI
npm install @wdio/cli --save-dev
# Запустить мастер конфигурации
npx wdio config
Файл конфигурации
// wdio.conf.js
export const config = {
runner: 'local',
specs: ['./test/specs/**/*.js'],
exclude: [],
maxInstances: 5,
capabilities: [{
browserName: 'chrome',
'goog:chromeOptions': {
args: ['--headless', '--disable-gpu']
}
}],
logLevel: 'info',
bail: 0,
baseUrl: 'https://example.com',
waitforTimeout: 10000,
framework: 'mocha',
reporters: ['spec'],
mochaOpts: {
ui: 'bdd',
timeout: 60000
}
}
Написание первого теста
// test/specs/login.spec.js
describe('Страница логина', () => {
beforeEach(async () => {
await browser.url('/login')
})
it('должен войти с валидными credentials', async () => {
await $('#username').setValue('testuser')
await $('#password').setValue('password123')
await $('button[type="submit"]').click()
await expect($('.welcome-message')).toBeDisplayed()
await expect($('.welcome-message')).toHaveTextContaining('Welcome')
})
it('должен показать ошибку для неверных credentials', async () => {
await $('#username').setValue('wrong')
await $('#password').setValue('wrong')
await $('button[type="submit"]').click()
await expect($('.error-message')).toBeDisplayed()
})
})
Селекторы и элементы
// CSS селекторы (самые частые)
const button = await $('button.submit')
const input = await $('#email')
const items = await $$('.list-item') // Возвращает массив
// XPath
const cell = await $('//table//tr[2]/td[3]')
// Текст ссылки
const link = await $('=Click Here') // Точное совпадение
const partialLink = await $('*=Click') // Частичное
// Работа с элементами
await $('#input').setValue('text')
await $('button').click()
const text = await $('p').getText()
const isDisplayed = await $('element').isDisplayed()
Ожидания и синхронизация
// Ждать появления элемента
await $('button').waitForExist({ timeout: 5000 })
// Ждать отображения
await $('modal').waitForDisplayed({ timeout: 10000 })
// Ждать кликабельности
await $('button').waitForClickable({ timeout: 5000 })
// Кастомное условие
await browser.waitUntil(
async () => (await $('counter').getText()) === '10',
{
timeout: 10000,
timeoutMsg: 'Счётчик не достиг 10'
}
)
Page Object Model
// test/pageobjects/login.page.js
class LoginPage {
get inputUsername() { return $('#username') }
get inputPassword() { return $('#password') }
get btnSubmit() { return $('button[type="submit"]') }
async open() {
await browser.url('/login')
}
async login(username, password) {
await this.inputUsername.setValue(username)
await this.inputPassword.setValue(password)
await this.btnSubmit.click()
}
}
export default new LoginPage()
// Использование в тестах
import LoginPage from '../pageobjects/login.page.js'
describe('Login', () => {
it('должен войти успешно', async () => {
await LoginPage.open()
await LoginPage.login('user@example.com', 'password123')
await expect($('.dashboard')).toBeDisplayed()
})
})
Assertions с expect-webdriverio
// Assertions элементов
await expect($('button')).toBeDisplayed()
await expect($('button')).toBeClickable()
await expect($('input')).toHaveValue('expected')
await expect($('p')).toHaveText('точный текст')
await expect($('p')).toHaveTextContaining('частичный')
await expect($$('li')).toBeElementsArrayOfSize(5)
// Browser assertions
await expect(browser).toHaveUrl('https://example.com/')
await expect(browser).toHaveTitle('Page Title')
// Отрицание
await expect($('modal')).not.toBeDisplayed()
Параллельное выполнение
// wdio.conf.js
export const config = {
maxInstances: 5, // Макс параллельных браузеров
capabilities: [{
maxInstances: 3,
browserName: 'chrome'
}, {
maxInstances: 2,
browserName: 'firefox'
}]
}
Интеграция с CI/CD
# .github/workflows/e2e.yml
name: E2E Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npx wdio run wdio.conf.js
- name: Upload results
if: always()
uses: actions/upload-artifact@v4
with:
name: allure-results
path: allure-results
WebdriverIO с помощью ИИ
ИИ-инструменты могут помочь писать и поддерживать тесты WebdriverIO.
Что ИИ делает хорошо:
- Генерировать page objects из HTML-структуры
- Конвертировать ручные тест-кейсы в код автоматизации
- Предлагать селекторы для сложных элементов
- Создавать data-driven вариации тестов
Что всё ещё требует людей:
- Выбор что тестировать, а что пропустить
- Отладка нестабильных тестов
- Понимание бизнес-логики
- Решения по оптимизации производительности
FAQ
Что такое WebdriverIO?
WebdriverIO — прогрессивный фреймворк автоматизации для Node.js. Он реализует протоколы WebDriver и DevTools для управления браузерами и мобильными устройствами. В отличие от сырых Selenium-привязок, WebdriverIO предоставляет современный async/await синтаксис, встроенные assertions, автоматические ожидания и богатую экосистему плагинов.
WebdriverIO лучше Selenium?
WebdriverIO построен на протоколе Selenium WebDriver, так что это скорее улучшение, чем замена. Он добавляет современные JavaScript-паттерны (async/await), лучшие сообщения об ошибках, автоматические ожидания и обширную поддержку плагинов. Для Node.js разработчиков WebdriverIO обычно проще, чем использование пакета selenium-webdriver напрямую.
Можно ли тестировать мобильные приложения?
Да. WebdriverIO бесшовно интегрируется с Appium для мобильного тестирования. Установи @wdio/appium-service и настрой capabilities для iOS или Android. Тот же синтаксис селекторов и команд работает для мобильных приложений.
WebdriverIO vs Playwright vs Cypress?
WebdriverIO использует протокол WebDriver (реальное поведение браузера, все браузеры поддерживаются, мобильные через Appium). Playwright использует Chrome DevTools Protocol (быстрее, но изменённые браузеры). Cypress работает внутри браузера (отличная отладка, но только same-origin, нет мобильных). Выбирай WebdriverIO для кросс-браузерных/мобильных нужд.
Официальные ресурсы
Смотрите также
- Selenium Tutorial - Основы WebDriver
- Playwright Tutorial - Современная альтернатива
- Cypress Tutorial - In-browser тестирование
- GitHub Actions для QA - CI/CD интеграция
