Одна из самых неприятных ситуаций при работе над сайтом или веб-приложением заключается в том, что отдельные куски кода работают правильно, но как только реальный пользователь пытается выполнить действие в настоящем браузере, всё ломается. Форма не отправляется, при нажатии на кнопку ничего не происходит или страница регистрации перенаправляет не туда. End-to-end (E2E) тестирование существует именно для решения этой проблемы: оно проверяет приложение целиком, не разбивая его на части, словно с ним работает живой человек.
E2E-тест открывает браузер, заходит на страницу, заполняет поля, нажимает кнопки и подтверждает, что на экране появился ожидаемый результат. Такой подход одновременно проверяет, что фронтенд, бэкенд, база данных и сетевые запросы работают согласованно и правильно. Именно поэтому E2E-тест ближе всего к реальному пользовательскому опыту и ловит настоящие сбои на самой ранней стадии, до того как с ними столкнётся клиент.
Чем E2E-тест отличается от модульного теста
Модульный тест проверяет самую маленькую часть программы — одну функцию или один компонент — в изоляции от остальных. Например, вы передаёте числа в функцию расчёта цены и смотрите, верный ли получился результат. Такие тесты работают очень быстро и точно указывают, где именно находится ошибка, но они не способны проверить, как отдельные части связываются друг с другом в едином потоке.
E2E-тест, наоборот, проверяет всю цепочку целиком. Он начинается со страницы, которую видит пользователь, и проходит через все слои вплоть до ответа сервера и изменений в базе данных. Из-за этого E2E-тесты работают медленнее, и определить точное место ошибки бывает сложнее, но они гарантируют самое важное: может ли пользователь действительно достичь своей цели. Лучшие проекты используют оба типа тестов вместе — множество быстрых модульных тестов и меньшее количество глубоких E2E-тестов.
Что такое Cypress и почему он удобен
Cypress — это современный инструмент E2E-тестирования, созданный для веб-приложений, который запускает тесты прямо внутри настоящего браузера. В этом его главное преимущество: во время выполнения теста вы своими глазами видите каждый шаг, наблюдаете, какая кнопка была нажата и как изменилась страница. Если тест падает с ошибкой, Cypress визуально показывает, в какой именно точке он остановился, что значительно упрощает поиск проблемы.
Ещё одна сильная сторона Cypress — его простой и легко читаемый синтаксис. Код теста пишется настолько естественно, что даже QA-инженер, только начинающий осваивать программирование, сразу понимает происходящее. Cypress работает на базе JavaScript, его установка завершается несколькими командами и не требует сложных дополнительных настроек. Именно благодаря этой простоте многие команды начинают своё знакомство с E2E-тестированием именно с Cypress.
Простой пример теста
Давайте рассмотрим самый распространённый сценарий — тест, проверяющий форму входа в систему. В следующем коде мы заходим на страницу, заполняем поля логина и пароля, нажимаем кнопку и в результате подтверждаем, что пользователь перешёл в личный кабинет. Обратите внимание, что код читается почти как обычные предложения на английском языке.
describe('Страница входа', () => {
it('пускает в кабинет с верными данными', () => {
cy.visit('https://sayt.uz/login')
cy.get('input[name="email"]').type('user@example.com')
cy.get('input[name="password"]').type('SecretPass123')
cy.get('button[type="submit"]').click()
cy.url().should('include', '/cabinet')
cy.contains('Добро пожаловать').should('be.visible')
})
})
В этом тесте cy.visit открывает браузер и заходит на страницу, cy.get находит нужное поле, а type вписывает в него текст. Команда click нажимает кнопку, а should проверяет результат. Если в адресе URL присутствует /cabinet и на экране виден текст «Добро пожаловать», значит тест прошёл успешно и процесс входа работает корректно.
Селекторы — как находить элементы
Для поиска элементов на странице Cypress использует CSS-селекторы: имя тега, класс, идентификатор или атрибуты. В примере выше мы написали input[name="email"] и выбрали поле ввода с именем «email». Однако опыт показывает, что при изменении дизайна страницы имена классов часто меняются, и из-за этого привязанные к ним тесты ломаются.
Чтобы предотвратить именно эту проблему, большинство команд рекомендует использовать специальные атрибуты data-cy. Этот атрибут предназначен исключительно для тестирования и не меняется даже при изменении дизайна. Например, в HTML вы помечаете элемент как <button data-cy="submit-login">, а в тесте обращаетесь к нему через cy.get('[data-cy=submit-login]'). Такой подход делает тесты гораздо более стабильными и облегчает их последующее обслуживание.
Auto-wait — автоматическое ожидание
Одна из главных болей при работе с веб-приложениями — это вопрос времени. Прежде чем данные на странице придут с сервера, проходит некоторое время, анимации должны завершиться, а запросы — вернуть ответ. В старых инструментах тестирования разработчик был вынужден вручную писать команды вроде «жди три секунды», что делало тесты медленными и ненадёжными.
Cypress решает эту проблему своим механизмом auto-wait. Перед каждой командой он автоматически ждёт, пока элемент появится, станет видимым и готовым к нажатию. То есть когда вы пишете cy.get, а элемент ещё не загрузился, Cypress немного подождёт его и только потом продолжит. Это упрощает ваш код и подстраивает тесты под скорость реального пользователя, в результате чего случайные ошибки значительно сокращаются.
Использование Cypress в CI
Чтобы получить максимальную пользу от тестов, они должны автоматически запускаться после каждого изменения кода. Это обеспечивают системы непрерывной интеграции (CI) — например GitHub Actions, GitLab CI или другие платформы. Как только разработчик отправляет новый код, система автоматически запускает тесты Cypress, и если какой-то тест сломался, она останавливает выкатку изменений на сайт.
Для запуска Cypress в CI существует специальная команда, которая использует браузер в режиме без экрана, то есть «headless». Следующий пример показывает простую конфигурацию для GitHub Actions.
name: E2E Tests
on: [push]
jobs:
cypress:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npx cypress run
Эта конфигурация после каждого push загружает проект, устанавливает необходимые пакеты и командой npx cypress run запускает все тесты. Если тест завершается неудачей, команда немедленно получает уведомление и исправляет проблему до того, как с ней столкнутся пользователи.
Cypress и Playwright — краткое сравнение
Главный конкурент Cypress — это Playwright, созданный компанией Microsoft и стремительно набирающий популярность в последние годы. Playwright одинаково хорошо поддерживает несколько браузеров (Chrome, Firefox, Safari) и считается более сильным в параллельном запуске множества тестов одновременно. Он также поддерживает разные языки программирования, включая Python и C#.
Cypress же выделяется удобным визуальным интерфейсом и простотой освоения, особенно для новичков. Если вы работаете над несложным проектом, который функционирует в одном браузере, и хотите быстро писать тесты и наблюдать за их выполнением, Cypress будет хорошим выбором. В сложных, многобраузерных и масштабных проектах преимущество может оказаться на стороне Playwright. Оба инструмента превосходны, и главное — вообще начать использовать E2E-тесты в своём проекте.