End-to-End тестирование с Cypress

End-to-End (E2E) тестирование в контексте веб-приложений позволяет проверять работу системы целиком, от пользовательского интерфейса до серверной логики. В Preact-приложениях, где интерфейс активно обновляется через виртуальный DOM, E2E тестирование обеспечивает уверенность в корректности взаимодействия компонентов и правильной работы приложения в реальном браузере. Cypress является одним из наиболее популярных инструментов для реализации E2E тестов благодаря своей простоте и интеграции с современными фреймворками.


Установка и настройка Cypress

Установка Cypress осуществляется через npm:

npm install cypress --save-dev

После установки можно открыть Cypress через команду:

npx cypress open

Это запускает графический интерфейс, где можно создавать и запускать тесты. Для интеграции с Preact рекомендуется структура проекта, где тесты располагаются в папке cypress/e2e. Основные конфигурации находятся в файле cypress.config.js, где можно настроить базовый URL приложения, таймауты и другие параметры:

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

module.exports = defineConfig({
  e2e: {
    baseUrl: 'http://localhost:3000',
    supportFile: 'cypress/support/e2e.js',
    viewportWidth: 1280,
    viewportHeight: 720,
  },
});

Структура E2E теста

Cypress использует синтаксис, близкий к Mocha, что делает тесты читаемыми и последовательными. Основные элементы теста:

  • describe — объединяет тесты в логические блоки.
  • it — отдельный тестовый кейс.
  • before, beforeEach, after, afterEach — хуки для подготовки и очистки состояния.

Пример базового теста для Preact-приложения:

describe('Главная страница', () => {
  beforeEach(() => {
    cy.visit('/');
  });

  it('Отображает заголовок приложения', () => {
    cy.get('h1').should('contain.text', 'Моё Preact-приложение');
  });

  it('Кнопка добавления элемента работает', () => {
    cy.get('button#add-item').click();
    cy.get('ul#items > li').should('have.length', 1);
  });
});

Работа с компонентами Preact

Для E2E тестов важно учитывать особенности Preact:

  • Виртуальный DOM обновляется асинхронно, поэтому необходимо использовать команды Cypress с ожиданиями (cy.get().should()).
  • Селекторы должны быть устойчивыми к изменениям. Предпочтительно использовать data-testid вместо классов или текста.

Пример использования data-testid:

<button data-testid="submit-btn">Отправить</button>
cy.get('[data-testid="submit-btn"]').click();

Асинхронные действия и ожидания

Cypress автоматически ждет появления элементов и завершения асинхронных действий. Для Preact-приложений это критично, так как обновление состояния может происходить после нескольких рендеров. Используются цепочки should и then:

cy.get('ul#items > li')
  .should('have.length', 3)
  .then(($items) => {
    expect($items.eq(0)).to.contain.text('Первый элемент');
  });

Для проверки сетевых запросов можно использовать перехват:

cy.intercept('POST', '/api/items').as('createItem');
cy.get('button#add-item').click();
cy.wait('@createItem').its('response.statusCode').should('eq', 201);

Работа с формами и событиями

Cypress позволяет имитировать ввод данных, выбор опций и другие действия пользователя:

cy.get('input[name="username"]').type('user123');
cy.get('input[name="password"]').type('securepass');
cy.get('form').submit();
cy.get('.alert-success').should('contain.text', 'Вход выполнен успешно');

Особенности Preact: при использовании управляемых компонентов важно, чтобы события onChange и onInput корректно вызывали обновление состояния. Cypress учитывает это автоматически, но при сложных кастомных компонентах может потребоваться дополнительная задержка или проверка состояния через should.


Сценарии тестирования

Типичные сценарии E2E для Preact-приложений:

  1. Навигация: проверка маршрутизации и корректного отображения страниц.
  2. Формы: ввод данных, валидация и отправка на сервер.
  3. Интерактивные компоненты: модальные окна, выпадающие списки, динамически обновляемые списки.
  4. Сетевые запросы: проверка работы API и обработки ошибок.
  5. Авторизация и права доступа: сценарии входа, выхода, редиректов.

Паттерны организации тестов

Для масштабируемых проектов важно придерживаться структуры:

  • cypress/e2e/pages — абстракция страниц и компонентов.
  • cypress/e2e/specs — отдельные тестовые сценарии.
  • cypress/support/commands.js — кастомные команды Cypress, например:
Cypress.Commands.add('login', (username, password) => {
  cy.get('input[name="username"]').type(username);
  cy.get('input[name="password"]').type(password);
  cy.get('form').submit();
});
  • cypress/fixtures — фикстуры данных для тестов.

Параллельный запуск и CI/CD

Cypress поддерживает интеграцию с CI/CD, позволяя запускать тесты в headless режиме:

npx cypress run --headless --browser chrome

Использование команд --record и --parallel позволяет хранить отчеты и ускорять проверку большого количества тестов. Для Preact-приложений это особенно полезно, так как E2E тесты могут быть ресурсоёмкими при множестве интерактивных компонентов.


Советы по стабильности тестов

  • Избегать использования динамических селекторов, полагаясь на data-testid.
  • Всегда ожидать состояние элементов перед проверкой.
  • Разбивать тесты на атомарные сценарии, чтобы ошибки было легко локализовать.
  • Использовать фикстуры и моки для сетевых запросов, чтобы тесты не зависели от внешнего API.

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