В тестировании на 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 для страницы логина:
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.