Переиспользование логики

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


Команды (Cypress.Commands)

Cypress позволяет создавать собственные команды через объект Cypress.Commands. Пользовательские команды инкапсулируют последовательность действий, которые повторяются в нескольких тестах.

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

Cypress.Commands.add('login', (username, password) => {
    cy.get('#username').type(username)
    cy.get('#password').type(password)
    cy.get('button[type="submit"]').click()
})

Теперь авторизацию можно выполнять одной строкой:

cy.login('admin', '12345')

Преимущества пользовательских команд:

  • Возможность интеграции с цепочкой cy (chainable commands)
  • Повышение читаемости тестов
  • Централизованное изменение логики при необходимости

Можно создавать команды как с синхронной, так и с асинхронной логикой. Для асинхронных операций следует использовать .then() или async/await внутри Cypress команд с осторожностью, так как Cypress сам управляет очередью команд.


Функции и утилиты

Для повторяющихся операций, не зависящих напрямую от DOM, удобно использовать обычные JavaScript-функции. Это подходит для обработки данных, генерации тестовых значений, формирования URL и т.п.

Пример утилиты для генерации случайного email:

export function generateRandomEmail() {
    const timestamp = Date.now()
    return `user${timestamp}@example.com`
}

Использование:

const email = generateRandomEmail()
cy.get('#email').type(email)

Функции легко тестировать отдельно от Cypress и переиспользовать в разных проектах.


Фикстуры (fixtures)

Фикстуры позволяют хранить тестовые данные в виде JSON-файлов и загружать их перед выполнением тестов.

Пример структуры фикстуры user.json:

{
    "admin": {
        "username": "admin",
        "password": "12345"
    },
    "guest": {
        "username": "guest",
        "password": "guest"
    }
}

Загрузка фикстуры в тесте:

cy.fixture('user').then((users) => {
    cy.login(users.admin.username, users.admin.password)
})

Использование фикстур помогает:

  • Изолировать данные от тестовой логики
  • Легко обновлять тестовые сценарии при изменении требований
  • Обеспечивать повторяемость тестов

Хуки и повторяющаяся подготовка (before, beforeEach)

Cypress поддерживает хуки для выполнения повторяющихся действий перед тестами или группами тестов.

before(() => {
    cy.fixture('user').as('users')
})

beforeEach(function () {
    cy.visit('/login')
    cy.login(this.users.admin.username, this.users.admin.password)
})

Особенности:

  • before выполняется один раз перед всеми тестами блока
  • beforeEach выполняется перед каждым тестом
  • Использование контекста this позволяет сохранять данные фикстур

Хуки помогают сократить дублирование кода и поддерживать чистую структуру тестов.


Паттерн Page Object

Page Object — это подход, при котором каждый экран или компонент приложения представлен отдельным объектом с методами для взаимодействия.

Пример Page Object для страницы логина:

export class LoginPage {
    visit() {
        cy.visit('/login')
    }

    fillUsername(username) {
        cy.get('#username').type(username)
    }

    fillPassword(password) {
        cy.get('#password').type(password)
    }

    submit() {
        cy.get('button[type="submit"]').click()
    }

    login(username, password) {
        this.fillUsername(username)
        this.fillPassword(password)
        this.submit()
    }
}

Использование:

const loginPage = new LoginPage()
loginPage.visit()
loginPage.login('admin', '12345')

Преимущества Page Object:

  • Централизованное хранение селекторов и действий
  • Легкость переиспользования логики на разных страницах
  • Упрощение рефакторинга при изменении интерфейса

Параметризованные тесты (it.each, forEach)

Для выполнения одинаковых действий с разными входными данными используют массивы и циклы:

const users = [
    { username: 'admin', password: '12345' },
    { username: 'guest', password: 'guest' }
]

users.forEach((user) => {
    it(`логин пользователя ${user.username}`, () => {
        cy.login(user.username, user.password)
        cy.url().should('include', '/dashboard')
    })
})

Преимущества:

  • Уменьшение дублирования тестов
  • Легкая масштабируемость при добавлении новых данных

Выводы по переиспользованию логики

Эффективное переиспользование кода в Cypress строится на сочетании пользовательских команд, утилит, фикстур, хуков и Page Object. Это позволяет:

  • Поддерживать тесты читаемыми и компактными
  • Централизованно управлять изменениями в логике
  • Обеспечивать стабильность и повторяемость тестов
  • Снижать риск ошибок при расширении функциональности

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