WebdriverIO предоставляет гибкий подход к организации автоматизированных тестов в JavaScript, поддерживая различные тестовые фреймворки: Mocha, Jasmine, Cucumber. Структура тестов напрямую зависит от выбранного фреймворка и подхода к организации файлов, что влияет на читаемость, повторное использование кода и масштабируемость проектов.
Для крупных проектов рекомендуется делить структуру на логические уровни:
tests/ — основной каталог с тестовыми
сценариями.pageobjects/ — паттерн Page Object,
где хранится логика взаимодействия с элементами страницы.services/ — кастомные сервисы или
интеграции, например для работы с API.data/ — фикстуры и тестовые
данные.config/ — конфигурационные файлы
WebdriverIO, параметры браузеров, окружений.Пример структуры:
project/
│
├─ tests/
│ ├─ login.test.js
│ └─ dashboard.test.js
│
├─ pageobjects/
│ ├─ login.page.js
│ └─ dashboard.page.js
│
├─ data/
│ └─ users.json
│
├─ services/
│ └─ apiService.js
│
└─ wdio.conf.js
Такой подход обеспечивает разделение ответственности: тесты концентрируются на проверках, Page Objects — на взаимодействии с элементами, сервисы — на вспомогательных функциях.
Mocha — один из самых популярных фреймворков для WebdriverIO,
поддерживает BDD (Behavior Driven Development) через
describe и it.
Пример базовой структуры:
const LoginPage = require('../pageobjects/login.page');
describe('Авторизация на сайте', () => {
before(() => {
LoginPage.open();
});
it('должна успешно входить с корректными данными', async () => {
await LoginPage.login('user@example.com', 'password123');
await expect(LoginPage.userProfile).toBeDisplayed();
});
it('не должна входить с некорректными данными', async () => {
await LoginPage.login('wrong@example.com', 'wrongpass');
await expect(LoginPage.errorMessage).toBeDisplayed();
});
});
Особенности структуры с Mocha:
describe группирует сценарии по функционалу или
модулю.it описывает конкретный сценарий.before, beforeEach,
after, afterEach управляют подготовкой и
очисткой состояния.Jasmine имеет синтаксис, похожий на Mocha, но интегрирован с ассертами без дополнительных библиотек:
const DashboardPage = require('../pageobjects/dashboard.page');
describe('Проверка дашборда', () => {
beforeAll(async () => {
await DashboardPage.open();
});
it('должен отображать ключевые виджеты', async () => {
expect(await DashboardPage.widgetList.length).toBeGreaterThan(0);
});
it('должен корректно фильтровать данные', async () => {
await DashboardPage.applyFilter('active');
expect(await DashboardPage.filteredItems()).not.toContain('inactive');
});
});
Ключевые моменты Jasmine:
beforeAll и afterAll работают на
уровне describe, а beforeEach и
afterEach — на уровне сценариев.expect), не требуется подключение
Chai.async/await.Cucumber применяет BDD-подход с Gherkin. Структура разделяется на три уровня:
features/ — файлы
.feature, содержащие сценарии на естественном языке.step-definitions/ — обработчики шагов,
связывающие текст сценария с кодом.support/ — вспомогательные функции,
хуки, конфигурация.Пример .feature:
Функция: Авторизация
Сценарий: Успешный вход
Допустим пользователь на странице логина
Когда он вводит корректные данные
Тогда он видит свой профиль
Соответствующий step definition:
const { Given, When, Then } = require('@cucumber/cucumber');
const LoginPage = require('../pageobjects/login.page');
Given('пользователь на странице логина', async () => {
await LoginPage.open();
});
When('он вводит корректные данные', async () => {
await LoginPage.login('user@example.com', 'password123');
});
Then('он видит свой профиль', async () => {
await expect(LoginPage.userProfile).toBeDisplayed();
});
Особенности Cucumber:
Page Object — центральная концепция для крупных проектов. Классическая реализация:
class LoginPage {
get inputEmail() { return $('#email'); }
get inputPassword() { return $('#password'); }
get loginButton() { return $('#login'); }
get userProfile() { return $('#user-profile'); }
get errorMessage() { return $('#error-msg'); }
async open() {
await browser.url('/login');
}
async login(email, password) {
await this.inputEmail.setValue(email);
await this.inputPassword.setValue(password);
await this.loginButton.click();
}
}
module.exports = new LoginPage();
Page Object позволяет сокращать дублирование кода, инкапсулировать локаторы и методы взаимодействия, делая тесты лаконичными и читабельными.
Для повторного использования данных применяются JSON-файлы или JS-объекты:
const users = require('../data/users.json');
users.forEach(user => {
it(`должна входить под ${user.name}`, async () => {
await LoginPage.login(user.email, user.password);
await expect(LoginPage.userProfile).toBeDisplayed();
});
});
Это повышает масштабируемость тестов и упрощает поддержку.
Конфигурация wdio.conf.js поддерживает глобальные
хуки:
beforeSuite — выполняется перед
набором тестов.afterSuite — очистка после набора
тестов.beforeTest / afterTest —
подготовка и постобработка для каждого теста.Пример использования:
beforeTest: async (test) => {
console.log(`Начало теста: ${test.title}`);
},
afterTest: async (test, context, { error, result, duration, passed }) => {
if (!passed) {
await browser.saveScreenshot(`./screenshots/${test.title}.png`);
}
}
Хуки позволяют централизованно управлять состоянием браузера, логами и скриншотами.
Структура тестов в WebdriverIO с различными фреймворками обеспечивает гибкость, масштабируемость и поддерживаемость проектов, а комбинирование Page Objects, фикстур и хуков позволяет создавать надежные автоматизированные тесты для сложных веб-приложений.