E2E‑тестирование React‑приложения с Cypress

Frontend‑разработка — это не только визуальная часть и логика на клиенте. Главное — дать пользователю предсказуемый и бесшовный опыт. Unit‑ и integration‑тесты проверяют логику и модули, но они не всегда имитируют реальные пользовательские сценарии. E2E‑тесты воспроизводят путь пользователя от начала до конца: ввод, навигация, запросы к API и отображение результата. Именно они обнаруживают проблемы, которые можно упустить при тестировании на уровне модулей.
Зачем использовать E2E‑тесты с Cypress
Коротко о мотивации:
- E2E проверяет результат и опыт пользователя, а не внутреннюю реализацию.
- Cypress запускается в браузере, даёт доступ к реальному DOM и сетевым запросам. Это упрощает отладку и делает тесты ближе к реальности.
- Поддерживает стабы сетевых ответов, ожидания, работы с тайммерами и многое другое.
К примеру, для формы входа важен не код в контроллере, а то, что пользователь видит и может выполнить вход. E2E‑тесты имитируют именно такой сценарий.
Cypress работает с популярными JS‑фреймворками и поддерживает следующие подходы:
- Unit‑тесты
- End‑to‑End (E2E)
- Integration‑тесты
Ниже мы пройдём весь путь: от создания проекта до написания стабильных e2e‑тестов, подачи тестов в CI, стратегий отладки и примеров приёмки.
Пример пользовательских историй
Простые user stories для учебного приложения поиска товаров:
- Пользователь видит поле ввода и кнопку отправки.
- Пользователь вводит поисковый запрос.
- После отправки под полем отображается список товаров.
По этим историям мы создаём React‑приложение, которое подтягивает товары с DummyJSON API и рендерит их.
Код проекта опубликован в репозитории на GitHub (ссылка в исходном тексте проекта).
Настройка React‑проекта
Создайте проект на Vite или с помощью create‑react‑app. После установки добавьте Cypress как dev‑зависимость:
npm install cypress --save-devДобавьте в package.json скрипт для запуска клиента Cypress:
"test": "npx cypress open"Создание функционального компонента
В папке src/components создайте файл products.jsx со следующим кодом:
import React, { useState, useEffect } from 'react';
import "./style.component.css"
export default function Products(prop) {
const [products, setProducts] = useState([]);
const [error, setError] = useState(null);
const { searchInput } = prop;
return (
{error ? (
Product not found
) : (
{products.slice(0, 6).map((product) => (
Title: {product.title}
Price: ${product.price}
))}
)}
);
}Внутри компонента добавьте useEffect, который при изменении searchInput вызывает API и сохраняет полученные товары:
useEffect(() => {
const fetchProducts = async () => {
if (searchInput) {
const apiUrl = `https://dummyjson.com/products/category/${searchInput}`;
try {
const response = await fetch(apiUrl);
if (!response.ok) {
throw new Error('Error fetching products');
}
const json = await response.json();
setProducts(json.products);
setError(null);
} catch (error) {
setError(error.message);
}
}
};
fetchProducts();
}, [searchInput]);Обновление App.jsx
Пример простого App.jsx для запуска приложения и тестирования:
import React, { useState,useRef } from 'react'
import './App.css'
import Products from './components/Products'
function App() {
const [searchInput, setSearchInput] = useState('')
const searchInputRef = useRef('');
const handleSubmit = (e) => {
setSearchInput(searchInputRef.current.value);
}
return (
Cypress Testing Library tutorial
)
}
export default AppЗапустите дев‑сервер:
npm run devПосле этого приложение должно уметь подтягивать товары из DummyJSON по указанной категории.
Настройка тестовой среды Cypress
Запустите Cypress:
npm run testОткроется клиент Cypress. Нажмите “E2E Testing” и далее “Continue” для добавления конфигурационных файлов. После этого в проекте появится папка cypress и файл cypress.config.js.
Файл cypress.config.js можно адаптировать под ваш проект: базовый URL, таймауты, интеграцию с CI и т. д.
Написание E2E‑тестов в Cypress
Выберите браузер в клиенте Cypress. Cypress запускает облегчённую версию браузера, создавая контролируемую среду для тестов.
Создайте новый spec‑файл через интерфейс или вручную. Откройте cypress/e2e/App.spec.cy.js и вставьте:
describe('App Tests', () => {
beforeEach(() => {
cy.visit('http://127.0.0.1:5173/');
});
it('Renders input field and submit button', () => {
cy.get('#text').should('exist').should('be.visible');
cy.get('#btn').should('exist').should('be.visible').contains('Submit');
});
it('Enters a search query', () => {
const searchQuery = 'laptops';
cy.get('#text').type(searchQuery);
});
});Этот набор тестов проверяет:
- Отрисовку поля ввода и кнопки.
- Возможность ввести поисковый запрос.
Cypress использует декларативную синтаксу, похожую на Jest и другие инструменты, но работает в браузере и предоставляет богатые возможности для управления сетью и DOM.
Запуск и результаты
Выберите файл в Cypress и запустите тесты. В интерфейсе вы увидите лог выполнения, снимки состояния и видео (если включено) — это облегчает отладку.
Симуляция полного пользовательского процесса
Чтобы проверить полный сценарий — ввод, отправка, загрузка и отображение — создайте файл cypress/e2e/Products.spec.cy.js:
describe('Products Tests', () => {
it(' fetches and displays the data', () => {
const searchQuery = 'laptops';
cy.visit('http://127.0.0.1:5173');
cy.get('#text').type(searchQuery);
cy.get('#btn').contains('Submit').click();
cy.get('.product').should('have.length.greaterThan', 0);
cy.get('.product').first().should('contain', 'Title');
cy.get('.product').first().should('contain', 'Price: $');
});
});Тест имитирует пользовательский путь: ввод запроса, клик по кнопке, ожидание загрузки и проверку карточек товара. Это проверяет взаимодействие UI с сетью и корректный рендер.
Симуляция ошибок и сетевых ответов
Cypress умеет перехватывать сетевые запросы и возвращать стабы. Это позволяет тестировать обработку ошибок без изменения сервера. Пример в cypress/e2e/Error.spec.cy.js:
describe('Error Handling Tests', () => {
it('Displays error message for incorrect search query', () => {
cy.intercept('GET', /https:\/\/dummyjson\.com\/products\/category\/.*/, {
statusCode: 404, // Not Found
body: 'Product not found'
}).as('fetchProducts');
cy.visit('http://127.0.0.1:5173');
const incorrectSearchQuery = 'rocket';
cy.get('#text').type(incorrectSearchQuery);
cy.get('#btn').click();
cy.wait('@fetchProducts');
cy.contains('Product not found').should('be.visible');
});
});Этот тест подтверждает, что при ошибке запроса приложение показывает понятное сообщение об ошибке.
Практические рекомендации и лучшие практики
Важно не просто писать тесты, а делать их устойчивыми, быстрыми и понятными. Ниже — подборка рекомендаций и чек‑листов для команд.
Правила написания стабильных тестов
- Используйте семантические селекторы: data-* атрибуты (например, data-testid=”products-component”) вместо привязки к классу или тексту, который может меняться.
- Держите тесты атомарными: проверяйте одну вещь за раз.
- Избегайте жёстких таймаутов и sleep; опирайтесь на ожидания (cy.get/.should/.wait с алиасами).
- Стабы сети используйте для проверки UI‑логики, а интеграционные тесты — для проверки конечной точки.
- Пишите описательные имена для спецификаций и тестов.
Отладка тестов
- Воспользуйтесь визуальной панелью Cypress: снимки и видео помогают увидеть состояние DOM.
- Включите debug‑логи: cy.pause(), cy.debug(), или console.log в приложении.
- Локально запустите проблемный тест в «headed» режиме в том же браузере, что и CI.
Работа с флейками и нестабильностью
- Локализуйте причину нестабильности: сеть, асинхронность, порядок выполнения.
- Временно используйте перехват запросов (cy.intercept) и мокированные ответы.
- Разделяйте длинные сценарии на более короткие, чтобы легче было отлавливать сбои.
Интеграция в CI/CD
Стратегия простая:
- На этапе сборки приложения запускайте unit/integration‑тесты.
- На отдельном шаге запускайте Cypress E2E в headless режиме (cypress run).
- Для стабильности используйте мок‑сценарии для основных happy‑path тестов и отдельные сопоставления для интеграционных прогонов.
- Сохраняйте артефакты: видеозаписи и скриншоты упавших тестов.
Совет: разбивайте E2E‑тесты на теги/файлы и запускайте параллельно, если CI поддерживает параллелизацию.
Критерии приёмки для E2E‑тестов
- Поле ввода и кнопка отображаются и доступны для взаимодействия.
- При вводе и отправке корректного запроса под полем появляется список товаров (минимум 1 элемент).
- Первое отображённое поле товара содержит Title и Price.
- При некорректном запросе показывается понятное сообщение об ошибке.
- Логи ошибок не содержат исключений уровня uncaughtException в тестовом прогоне.
Чек‑лист для запуска и поддержки тестов (роль‑ориентированный)
- Разработчик:
- Добавил data‑атрибуты для стабильных селекторов.
- Написал unit‑тесты для критичных функций.
- Прописал обработку ошибок и отображение сообщений.
- QA инженер:
- Создал сценарии E2E по ключевым user story.
- Настроил перехват сетевых ответов для негативных сценариев.
- Запустил тесты локально и проверил скриншоты/видео.
- DevOps:
- Интегрировал cypress run в CI‑пайплайн.
- Настроил параллелизацию и сохранение артефактов.
Мини‑методология: как построить устойчивую E2E‑стратегию за 6 шагов
- Выделите 10–15 критичных пользовательских сценариев.
- Реализуйте их в виде атомарных тестов в Cypress.
- Добавьте стабильные селекторы (data‑атрибуты).
- Настройте стабы для негативных и редких сценариев.
- Интегрируйте прогон в CI c артефактами (скриншоты, видео).
- Периодически (например, при релизе) прогоняйте тесты против реального API.
Когда E2E‑тесты не помогут (контрпример)
- Неэффективно использовать E2E для проверки мелких утилит или сложных моделей данных — это замедлит прогон и даст мало пользы.
- Для тестирования алгоритмов и бизнес‑логики лучше использовать unit‑тесты.
- E2E не заменят нагрузочное тестирование и безопасность (проводите отдельные виды тестирования).
Сценарии тестирования и критерии приёмки (примеры)
Сценарий: Поиск существующей категории
- Шаги: Открыть страницу -> Ввести “laptops” -> Нажать Submit
- Ожидание: Появляется хотя бы одна карточка товара; карточка содержит Title и Price.
- Критерий приёмки: cy.get(‘.product’).should(‘have.length.greaterThan’, 0)
Сценарий: Негативный поиск
- Шаги: Мокнуть 404 для соответствующего эндпоинта -> Ввести “rocket” -> Нажать Submit
- Ожидание: Появляется сообщение “Product not found”.
Практический чек‑лист для использования сети и моков
- Для happy‑path тестов можно использовать реальные API в изолированном окружении.
- Для негативных сценариев стабы обязательны (годятся cy.intercept).
- Зафиксируйте ожидания на основе алиасов: cy.wait(‘@fetchProducts’) вместо произвольных пауз.
Безопасность и приватность
- В тестах избегайте использования реальных пользовательских данных. Генерируйте или используйте тестовые учётные записи.
- Если тесты логируют чувствительную информацию, храните лог‑артефакты в защищённом хранилище и очищайте их при необходимости.
- Для приложений, работающих с персональными данными, добавьте проверку соответствия требованиям конфиденциальности (GDPR): используйте маскировку и тестовые данные.
Советы по производительности тестового набора
- Исполняйте быстрые smoke‑тесты при каждом push в ветку.
- Полный E2E‑набор оставляйте для nightly‑прогона или pre‑release сборок.
- Параллелите тесты и уменьшайте время ожидания, заменив ожидания загрузки на ожидания конкретных элементов.
Частые ошибки и способы их избегать
- Жёсткое связывание теста с текстом кнопок. Лучше — data‑атрибуты.
- Использование cy.wait(2000) вместо ожиданий по событию или алиасу.
- Смешение unit/integration logic в e2e тестах, из‑за чего тесты становятся хрупкими.
Шаблон cypress.config.js — отправная точка
Пример простого файла конфигурации (адаптируйте под проект):
const { defineConfig } = require('cypress')
module.exports = defineConfig({
e2e: {
baseUrl: 'http://127.0.0.1:5173',
supportFile: 'cypress/support/e2e.js',
setupNodeEvents(on, config) {
// здесь можно подключить плагин для параллели, отчётов и т.д.
},
defaultCommandTimeout: 8000,
},
})Краткое руководство по отладке упавших тестов
- Откройте видео/скриншот из артефактов CI.
- Запустите проблемный тест локально в headed режиме.
- Используйте cy.pause() или devtools для детального просмотра.
- Проверьте, не изменилась ли реализация селекторов или тексты.
Рекомендации по поддержке тестовой базы
- Регулярно рефакторьте селекторы и удаляйте устаревшие тесты.
- Добавляйте тесты при добавлении фич — так база останется актуальной.
- Документируйте тестовые сценарии и правила запуска в README проекта.
Заключение
E2E‑тесты с Cypress помогают убедиться, что приложение работает так, как ожидает пользователь. Они дополняют unit и integration тесты и позволяют обнаруживать проблемы на стыках компонентов, сети и UI. Главное — писать понятные, атомарные и стабильные тесты, интегрировать их в CI и регулярно поддерживать тестовую базу.
Важно: начинайте с критичных пользовательских сценариев и постепенно расширяйте покрытие. Используйте стабы там, где это оправдано, и запускайте полные прогоны в контролируемой среде перед релизом.
Краткое резюме и действия:
- Настройте Cypress и напишите базовые тесты (рендер, ввод, отправка).
- Добавьте тесты на позитивные и негативные сценарии с cy.intercept.
- Интегрируйте прогоны в CI и сохраняйте артефакты для отладки.
- Поддерживайте тестовую базу: селекторы, документация, периодические прогоны.
— Конец инструкции —
Похожие материалы
Отключить звук запуска Windows
Как удалить профиль пользователя в Windows 11
Писк и щелчки в Sony WH-1000XM4 — исправление
Не запускается служба WLAN AutoConfig — решение
Исправить ошибку .NET Framework 4: 0x800c0006