Создание страниц классов

В тестировании с использованием WebdriverIO одной из ключевых практик является применение Page Object Model (POM). Эта модель позволяет изолировать логику работы с элементами интерфейса от самих тестов, что упрощает поддержку и масштабирование тестовой базы. Центральным элементом POM являются страницы классов, каждая из которых отражает отдельную страницу или компонент приложения.

Определение класса страницы

Каждая страница представляется отдельным классом JavaScript, где описываются селекторы элементов и методы взаимодействия с ними. Структура класса обычно включает три блока:

  1. Селекторы элементов — свойства класса, содержащие локаторы.
  2. Методы действий — функции, выполняющие операции над элементами.
  3. Методы навигации и проверки состояния — функции для перехода между страницами или валидации состояния элементов.

Пример базового класса страницы:

class LoginPage {
    // Селекторы
    get inputUsername() { return $('#username'); }
    get inputPassword() { return $('#password'); }
    get btnSubmit() { return $('button[type="submit"]'); }
    get errorMessage() { return $('.error-message'); }

    // Методы действий
    async login(username, password) {
        await this.inputUsername.setValue(username);
        await this.inputPassword.setValue(password);
        await this.btnSubmit.click();
    }

    async getErrorMessage() {
        return this.errorMessage.getText();
    }
}

module.exports = new LoginPage();

Организация селекторов

Селекторы должны быть однозначными и стабильными, чтобы минимизировать вероятность поломки тестов при изменениях интерфейса. Основные подходы:

  • Использование id и data-* атрибутов, так как они менее подвержены изменениям.
  • Избегать локаторов на основе порядковых индексов или стилей.
  • Составные селекторы для вложенных элементов, если простых идентификаторов недостаточно.

Методы действий и абстракция

Методы классов страниц должны представлять логические действия, а не отдельные клики. Например, метод login() объединяет ввод логина, пароля и нажатие кнопки, а не предоставляет отдельные методы для каждого поля. Такой подход позволяет:

  • Сократить дублирование кода в тестах.
  • Повысить читаемость тестов.
  • Упрощает поддержку при изменении интерфейса.

Методы проверки состояния страницы

Для валидации состояния страницы применяются методы, возвращающие данные или выполняющие проверки. Они могут быть двух типов:

  1. Возвращающие значения: текст ошибки, статус элемента, наличие видимости.
  2. Выполняющие утверждения: проверка наличия элементов, активного состояния кнопок.

Пример метода для проверки видимости кнопки:

async isSubmitButtonEnabled() {
    return this.btnSubmit.isEnabled();
}

Наследование и переиспользование

В крупных проектах удобно создавать базовый класс страницы, содержащий общие методы и свойства, такие как навигация, ожидание элементов, скриншоты. Конкретные страницы наследуют этот класс.

class BasePage {
    async open(path) {
        await browser.url(path);
    }

    async waitForElement(element, timeout = 5000) {
        await element.waitForDisplayed({ timeout });
    }
}

class DashboardPage extends BasePage {
    get userAvatar() { return $('.user-avatar'); }

    async isUserLoggedIn() {
        return this.userAvatar.isDisplayed();
    }
}

module.exports = new DashboardPage();

Асинхронная работа с элементами

WebdriverIO использует асинхронные операции при работе с браузером. Все методы взаимодействия с элементами должны использовать await, чтобы гарантировать корректное выполнение действий. Без await тест может завершиться до того, как элемент будет доступен.

Рекомендации по организации файлов

  • Каждый класс страницы располагается в отдельном файле.
  • Названия файлов соответствуют имени страницы, например, login.page.js, dashboard.page.js.
  • Центральная папка pages/ содержит все классы, что облегчает импорт и поддержку тестов.

Интеграция с тестами

Классы страниц импортируются в тесты и используются для описания сценариев. Например:

const loginPage = require('../pages/login.page');

describe('Login tests', () => {
    it('should login with valid credentials', async () => {
        await loginPage.open('/login');
        await loginPage.login('user', 'password123');
        // Дополнительные проверки после логина
    });
});

Принципы масштабируемости

  • Минимизация повторений: повторяющиеся действия выносятся в методы класса.
  • Изоляция логики: тесты используют только публичные методы классов страниц.
  • Гибкость селекторов: при изменении интерфейса достаточно обновить локаторы в классе страницы, тесты остаются без изменений.

Страницы классов в WebdriverIO являются фундаментальной частью архитектуры автоматизированного тестирования. Четкая организация селекторов, методов действий и проверок позволяет создавать масштабируемые, надежные и поддерживаемые тесты, обеспечивая долговременное качество автоматизации.