Cypress: установка и основы

Cypress — E2E testing framework, работающий внутри браузера и предоставляющий удобный API для написания, запуска и отладки тестов пользовательских сценариев.

Зачем нужно

Cypress устраняет главные боли E2E тестирования: встроенный ретрай на каждый assertion, подробный time-travel debugger с скриншотами каждого шага, автоматическое ожидание элементов. В отличие от Selenium, Cypress работает в том же Event Loop что и приложение, что даёт точный контроль.

Где используется

  • E2E тесты пользовательских сценариев (логин, checkout, формы)
  • Component testing для React/Vue/Angular компонентов
  • API тестирование через cy.request
  • Visual regression в связке с Percy или Applitools

Основной контент

Установка

npm install --save-dev cypress

# Открыть интерактивный UI
npx cypress open

# Запуск в headless режиме
npx cypress run

Структура проекта

cypress/
  e2e/           ← E2E тест-файлы
  component/     ← Component тест-файлы
  fixtures/      ← тестовые данные (JSON)
  support/
    commands.js  ← кастомные команды
    e2e.js       ← глобальные настройки
cypress.config.js

Первый тест

// cypress/e2e/login.cy.js
describe('Страница входа', () => {
  beforeEach(() => {
    cy.visit('/login');
  });

  it('позволяет войти с валидными данными', () => {
    cy.get('[data-cy="email"]').type('user@example.com');
    cy.get('[data-cy="password"]').type('secret123');
    cy.get('[data-cy="submit"]').click();

    cy.url.should('include', '/dashboard');
    cy.get('[data-cy="welcome"]').should('contain', 'Привет, user');
  });

  it('показывает ошибку при неверном пароле', () => {
    cy.get('[data-cy="email"]').type('user@example.com');
    cy.get('[data-cy="password"]').type('wrong');
    cy.get('[data-cy="submit"]').click();

    cy.get('[data-cy="error-message"]').should('be.visible').and('contain', 'Неверный пароль');
  });
});

Мокирование API через cy.intercept

cy.intercept('GET', '/api/users', { fixture: 'users.json' }).as('getUsers');

cy.visit('/users');
cy.wait('@getUsers');

cy.get('[data-cy="user-list"]').should('have.length', 3);

Кастомные команды

// cypress/support/commands.js
Cypress.Commands.add('login', (email, password) => {
  cy.request('POST', '/api/auth/login', { email, password }).then(({ body }) => {
    window.localStorage.setItem('token', body.token);
  });
});

// В тесте
cy.login('user@example.com', 'secret123');
cy.visit('/dashboard');

cypress.config.js

const { defineConfig } = require('cypress');

module.exports = defineConfig({
  e2e: {
    baseUrl: 'http://localhost:3000',
    viewportWidth: 1280,
    viewportHeight: 800,
    video: false,
    screenshotOnRunFailure: true,
  },
});

Частые ошибки

  • Селектор по CSS-классуcy.get('.btn-primary') ломается при рефакторинге стилей; используй data-cy атрибуты
  • Отсутствие cy.wait('@alias') — тест продолжается до завершения запроса и падает с гонкой; всегда жди intercept
  • Жёсткие cy.wait(2000) вместо assertion — заменяй sleep на cy.get(selector).should('be.visible')
  • Тест зависит от данных из предыдущего теста — каждый тест должен создавать своё состояние; используй beforeEach для setup

Связанные темы

Ресурсы