Зачем нужны E2E-тесты и где их место

End-to-end (E2E) тест запускает всё приложение в настоящем браузере и делает то, что делает пользователь: открывает страницу, вводит текст, кликает, читает результат. Он ловит проблемы, которых не видят unit-тесты: неверный путь к скрипту, форма без обработчика, кнопка, перекрытая другим элементом.

Пирамида тестов: много unit-тестов, часть integration, мало E2E
Пирамида тестов: много unit-тестов, часть integration, мало E2E
ВидЧто проверяетСкоростьТипичный инструмент
UnitОдну функцию или классмиллисекундыvitest
IntegrationНесколько модулей или БД вместесотни миллисекундvitest, supertest
E2EВсё приложение в браузересекунды@playwright/test

Чем выше уровень, тем реалистичнее тест и тем он дороже: медленнее, сложнее отлаживать и чаще падает по причинам, не связанным с вашим кодом. Поэтому форма и напоминает пирамиду. Каждую ветку логики проверяйте unit-тестами (см. Unit-тесты с Vitest), а E2E оставьте для нескольких критичных путей: регистрация, добавление в корзину, оплата.

💡 Хороший кандидат для E2E — сценарий, который приносит или теряет деньги, или поломка которого будет заметной. Цвет подсказки — нет.


Установка Playwright и конфигурация

Playwright — это раннер тестов (@playwright/test), который управляет Chromium, Firefox и WebKit. Установите его как dev-зависимость и скачайте браузер:

bash
npm init -y
npm i -D @playwright/test http-server
npx playwright install chromium

Конфигурация лежит в playwright.config.js:

javascript
import { defineConfig } from '@playwright/test';

export default defineConfig({
  testDir: './e2e',
  retries: process.env.CI ? 2 : 0,
  forbidOnly: !!process.env.CI,
  use: {
    baseURL: 'http://localhost:4173',
    trace: 'on-first-retry',
  },
  webServer: {
    command: 'npx http-server ./public -p 4173 -s',
    url: 'http://localhost:4173',
    reuseExistingServer: !process.env.CI,
  },
});
  • testDir — папка с файлами *.spec.js.
  • webServer запускает приложение перед тестами и ждёт ответа по url; reuseExistingServer позволяет локально использовать уже запущенный dev-сервер.
  • baseURL позволяет писать в тестах page.goto('/').
  • retries перезапускает упавший тест, но только в CI. forbidOnly роняет сборку, если кто-то оставил в коде test.only.