Cypress, как инструмент для end-to-end тестирования на JavaScript, ориентирован на изолированное выполнение тестов. Каждое тестовое событие должно быть независимым, чтобы гарантировать воспроизводимость и стабильность тестовой среды. Тем не менее, на практике часто возникает необходимость в организации зависимостей между тестами для более сложных сценариев, особенно при работе с последовательными действиями или данными, которые формируются на предыдущих шагах.
Основной принцип Cypress заключается в том, что каждый
it блок должен быть самостоятельным. Это
означает:
Пример структуры независимого теста:
describe('Проверка авторизации', () => {
beforeEach(() => {
cy.visit('/login');
});
it('успешный вход с корректными данными', () => {
cy.get('#username').type('user');
cy.get('#password').type('password');
cy.get('#loginButton').click();
cy.url().should('include', '/dashboard');
});
it('неуспешный вход с некорректным паролем', () => {
cy.get('#username').type('user');
cy.get('#password').type('wrongpass');
cy.get('#loginButton').click();
cy.get('.error-message').should('be.visible');
});
});
Каждый тест сам создаёт необходимое состояние и проверяет результат независимо.
Иногда появляется необходимость передавать состояние или данные между тестами. Типичные случаи:
В таких случаях важно понимать, что Cypress не хранит
состояние между it блоками, кроме как через
глобальные переменные или внешние источники.
before и beforeEachБлоки before и beforeEach позволяют
подготовить тестовую среду до выполнения тестов.
describe('Работа с ресурсами', () => {
let resourceId;
before(() => {
cy.request('POST', '/api/resource', { name: 'Тестовый ресурс' })
.then((response) => {
resourceId = response.body.id;
});
});
it('должен получить созданный ресурс', () => {
cy.request(`/api/resource/${resourceId}`).its('status').should('eq', 200);
});
it('должен обновить ресурс', () => {
cy.request('PUT', `/api/resource/${resourceId}`, { name: 'Обновлённый ресурс' })
.its('status').should('eq', 200);
});
});
Ключевой момент: использование глобальной переменной
(resourceId) для передачи состояния между тестами позволяет
избежать полного дублирования логики создания ресурса.
Cypress.envCypress.env используется для хранения данных между
тестами без обращения к глобальным переменным. Пример:
describe('Авторизация и работа с токеном', () => {
before(() => {
cy.request('POST', '/api/login', { user: 'user', pass: 'pass' })
.then((response) => {
Cypress.env('authToken', response.body.token);
});
});
it('доступ к защищённому ресурсу', () => {
cy.request({
url: '/api/protected',
headers: { Authorization: `Bearer ${Cypress.env('authToken')}` }
}).its('status').should('eq', 200);
});
});
Использование Cypress.env делает тесты более
управляемыми и уменьшает риск появления скрытых зависимостей.
it.only или
объединение шаговИногда зависимость требует, чтобы несколько шагов выполнялись последовательно. В таких случаях можно объединить их в один тест:
it('создаёт ресурс, редактирует и проверяет результат', () => {
cy.request('POST', '/api/resource', { name: 'Ресурс' })
.then((res) => {
cy.request('PUT', `/api/resource/${res.body.id}`, { name: 'Новый ресурс' });
})
.then(() => {
cy.get(`/resource-page`).should('contain', 'Новый ресурс');
});
});
Это гарантирует, что нет внешней зависимости между отдельными
it блоками.
Эти риски подчёркивают, что любые зависимости должны быть
осознанными и минимальными, предпочтительно
реализуемыми через подготовительные шаги (before,
beforeEach) или внешние API.
it
блоками.after или afterEach.Для сложных бизнес-процессов рекомендуется применять цепочку команд внутри одного теста или использовать страничные объекты (Page Object Pattern) для управления состоянием, что позволяет:
class LoginPage {
login(user, pass) {
cy.get('#username').type(user);
cy.get('#password').type(pass);
cy.get('#loginButton').click();
}
}
describe('Бизнес-процесс', () => {
const loginPage = new LoginPage();
it('полный сценарий заказа', () => {
loginPage.login('user', 'pass');
cy.visit('/order');
cy.get('#addItem').click();
cy.get('#checkout').click();
cy.get('.confirmation').should('contain', 'Спасибо за заказ');
});
});
Такой подход сохраняет структурную целостность сценариев без создания скрытых зависимостей между тестами.