Концепция Page Object

Page Object — это паттерн проектирования автоматизированных тестов, который позволяет структурировать код тестов, отделяя логику взаимодействия с элементами страницы от самих тестов. Основная цель — повышение поддерживаемости, читаемости и повторного использования кода.


Принцип работы Page Object

Идея заключается в том, что каждая веб-страница или её значимая часть представляется отдельным классом или модулем, содержащим:

  1. Селекторы элементов страницы Все локаторы (CSS, XPath, data-атрибуты) централизованы, чтобы изменения интерфейса не требовали правки всех тестов.

  2. Методы взаимодействия с элементами Клики, ввод текста, выбор из списка, проверка видимости и состояния элементов инкапсулируются в методы, которые называются понятно и отражают бизнес-действия.

  3. Методы получения данных или состояния Методы, возвращающие значения из элементов страницы, например текст кнопки, значение поля формы, состояние чекбокса.

Пример структуры Page Object в Cypress:

class LoginPage {
    elements = {
        usernameInput: () => cy.get('#username'),
        passwordInput: () => cy.get('#password'),
        submitButton: () => cy.get('button[type="submit"]'),
        errorMessage: () => cy.get('.error-message')
    };

    enterUsername(username) {
        this.elements.usernameInput().clear().type(username);
    }

    enterPassword(password) {
        this.elements.passwordInput().clear().type(password);
    }

    submit() {
        this.elements.submitButton().click();
    }

    getErrorMessage() {
        return this.elements.errorMessage().invoke('text');
    }
}

export default LoginPage;

В тестах этот Page Object используется так:

import LoginPage from '../pages/LoginPage';

describe('Авторизация', () => {
    const loginPage = new LoginPage();

    it('не удается войти с неверными данными', () => {
        cy.visit('/login');
        loginPage.enterUsername('wrong_user');
        loginPage.enterPassword('wrong_pass');
        loginPage.submit();
        loginPage.getErrorMessage().should('contain', 'Неверный логин или пароль');
    });
});

Преимущества использования Page Object

  • Централизация локаторов: изменение CSS-селектора происходит только в одном месте.
  • Повторное использование кода: одни и те же методы можно вызывать в разных тестах.
  • Повышение читаемости тестов: тесты описывают бизнес-логику, а не технические детали взаимодействия с элементами.
  • Изоляция изменений интерфейса: изменения в DOM не влияют на логику тестов, пока остаются актуальными методы Page Object.

Организация проекта с Page Object

Рекомендуется структура каталогов:

cypress/
  ├─ e2e/
  │    └─ login.spec.js
  ├─ pages/
  │    ├─ LoginPage.js
  │    └─ DashboardPage.js
  ├─ support/
       └─ commands.js
  • pages/ содержит все Page Object классы.
  • e2e/ хранит тестовые сценарии, использующие эти классы.
  • support/ — дополнительные команды Cypress и глобальные хуки.

Продвинутые техники

  1. Методы высокого уровня (High-Level Actions) Вместо работы с отдельными элементами создаются методы, описывающие полноценные действия, например login(username, password).
login(username, password) {
    this.enterUsername(username);
    this.enterPassword(password);
    this.submit();
}
  1. Валидация состояния страницы Page Object может содержать методы проверки, например, isLoggedIn(), чтобы тесты оставались декларативными.

  2. Декомпозиция больших страниц Если страница сложная, её части можно вынести в отдельные классы-компоненты, например Header, Sidebar, Footer, а основной Page Object использует их как свойства.

class DashboardPage {
    header = new Header();
    sidebar = new Sidebar();

    visit() {
        cy.visit('/dashboard');
    }
}
  1. Использование Data Attributes В локаторах предпочтительно использовать data-* атрибуты для устойчивости тестов к изменениям стилей и классов:
cy.get('[data-test="login-button"]').click();

Best Practices

  • Каждый метод Page Object должен выполнять одну конкретную задачу.
  • Методы тестов должны использовать бизнес-термины, а не технические детали.
  • Избегать жесткой привязки к CSS-классам, которые часто меняются.
  • Разделять методы получения данных и методы действий (например, getUsername() vs enterUsername()).
  • Поддерживать единый стиль именования: enterX, clickX, getX, isXVisible.

Page Object в Cypress превращает тесты из набора низкоуровневых команд в структурированный, легко поддерживаемый и читаемый код, что критически важно для крупных проектов с множеством сценариев.