Структура тестов с разными фреймворками

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

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 управляют подготовкой и очисткой состояния.
  • Page Objects и вспомогательные функции повышают повторное использование кода.

Структура тестов с Jasmine

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

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 Pattern

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();
    });
});

Это повышает масштабируемость тестов и упрощает поддержку.


Интеграция с хуками WebdriverIO

Конфигурация 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, фикстур и хуков позволяет создавать надежные автоматизированные тесты для сложных веб-приложений.