Коротко: для e2e лучше поднимать отдельный набор сервисов в тест‑окружении (отдельный бэкенд с APP_ENV=test, отдельная БД и отдельный фронтенд с переменными для теста), и запускать Cypress против них. Это надёжно, изолированно и повторяемо (локально и в CI). Ниже — почему и как это реализовать + полезные примеры.
Почему отдельный стек предпочтителен
- Symfony в одном контейнере/процессе не может одновременно обслуживать dev и test окружения на одном порту. Т.е. чтобы реально использовать APP_ENV=test, нужен отдельный процесс/контейнер (или запуск встроенного сервера `symfony server:start --env=test` на другом порту).
- Нужна отдельная БД/кеш/redis, чтобы тесты не портили данные разработческого окружения.
- Фронтенд (Next.js) тоже должен запускаться с нужными переменными (API URL и т. п.). Легче иметь отдельный контейнер/инстанс с нужными env vars и (опционально) собранным билдом.
- Такой же подход удобно применять в CI: один docker‑compose (или docker-compose.override) для тестов, который запускается и потом прогоняет Cypress.
Как организовать — шаги и примеры
1) Создайте docker-compose.test.yml (или docker-compose.e2e.yml)
Пример (упрощённо):
- backend: образ Symfony с APP_ENV=test, отдельные volume/без монтирования исходников (или с, в зависимости от подхода).
- db_test: отдельная БД (имя/пользователь/порт отличные от dev).
- frontend_test: Next.js запущенный с переменными для теста (NEXT_PUBLIC_API_URL указывает на backend_test).
- cypress: образ, который запускает тесты после поднятия остальных сервисов.
Пример фрагмента docker-compose.test.yml:
```
version: '3.8'
services:
backend_test:
build:
context: ./backend
dockerfile: Dockerfile
environment:
- APP_ENV=test
- APP_DEBUG=0
- DATABASE_URL=mysql://test:test@db_test:3306/test_db
ports:
- "8001:8000" # порт для тестов
depends_on:
- db_test
command: ["/entrypoint-test.sh"]
db_test:
image: mysql:8
environment:
- MYSQL_DATABASE=test_db
- MYSQL_USER=test
- MYSQL_PASSWORD=test
- MYSQL_ROOT_PASSWORD=root
ports:
- "3307:3306"
frontend_test:
build:
context: ./frontend
dockerfile: Dockerfile
args:
- NEXT_PUBLIC_API_URL=http://backend_test:8000
environment:
- NEXT_PUBLIC_API_URL=http://backend_test:8000
ports:
- "3001:3000"
depends_on:
- backend_test
cypress:
image: cypress/included:12.0.0
depends_on:
- frontend_test
working_dir: /e2e
volumes:
- ./e2e:/e2e
entrypoint: /bin/sh -c "npx wait-on http://frontend_test:3000 && npx cypress run --config baseUrl=http://frontend_test:3000"
```
(подправьте порты/имена под свой стек)
2) Настройка Symfony для тестов
- Установите переменную окружения APP_ENV=test в контейнере.
- При старте контейнера запускайте подготовку тестовой БД: создать, миграции, загрузка фикстур:
/entrypoint-test.sh например:
```
#!/bin/sh
set -e
php bin/console doctrine:database:create --env=test --no-interaction || true
php bin/console doctrine:migrations:migrate --env=test --no-interaction
php bin/console doctrine:fixtures:load --env=test --no-interaction
php -S 0.0.0.0:8000 -t public
```
- В коде используйте параметр kernel.environment или getenv('APP_ENV') при необходимости; консольные команды должны запускаться с --env=test (или контейнеру уже задан APP_ENV).
3) Настройка Next.js для тестов
- Next поддерживает .env файлы (например .env.test), и переменные с префиксом NEXT_PUBLIC_ будут доступны в браузере.
- При запуске dev-сервера можно использовать NEXT_PUBLIC_API_URL=http://backend_test:8000 npm run dev (или в docker-compose задать environment).
- В продакшен‑сценарии переменные, нужные клиенту, должны быть заданы при сборке (build time) — т.е. если вы собираете образ для теста, передайте build‑аргументы или env для формирования NEXT_PUBLIC_API_URL:
Dockerfile build stage:
```
ARG NEXT_PUBLIC_API_URL
ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL
RUN npm run build
```
- Для e2e обычно удобнее запускать preview/production‑like (npm run start) чтобы поведение было близким к проду, но при этом передать тестовые API URL.
4) Конфигурация Cypress
- В cypress.config.js (или cypress.json) задайте базовый URL для фронтенда:
e2e: { baseUrl: process.env.FRONTEND_BASE_URL || 'http://localhost:3001' }
- Перед запуском cypress в docker-compose передавайте переменные (или используйте wait-on для ожидания запуска frontend).
- Для API‑url внутри тестов используйте Cypress.env('apiUrl') и задавайте это значение через переменные окружения, либо берите из NEXT_PUBLIC_API_URL, если фронтенд сам подставляет адреса в UI.
5) Команда запуска локально
- Docker-compose способ:
docker-compose -f docker-compose.yml -f docker-compose.test.yml up --build
(файл test оверрайдит / добавит сервисы)
- Или отдельная команда: docker-compose -f docker-compose.test.yml up --build --abort-on-container-exit (чтобы тест контейнер завершил весь стек).
6) Очистка/изолирование данных
- Убедитесь, что test DB имеет отдельное имя/порт и не монтирует production data.
- Механизм подготовки: при старте контейнера запускать миграции + фикстуры. Можно также предусмотреть скрипт для отката/очистки после тестов.
Альтернативы / дополнительные варианты
- Запуск test backend локально без Docker: можно локально стартовать Symfony в test окружении на другом порту (symfony server:start --port=8001 --env=test) — удобно на локальной машине, но менее воспроизводимо в CI.
- Мокировать backend через Cypress network stubs (cy.intercept) — быстрее, но это уже не полноценные интеграционные e2e.
- Можно запускать Next.js в dev режиме и указывать NEXT_PUBLIC_API_URL для теста — это допустимо, но поведение dev≠prod, поэтому для более реалистичного теста лучше preview/prod build.
Резюме / рекомендуемая практика
- Для e2e создайте отдельный docker-compose (или override) для тестов, в котором backend запускается с APP_ENV=test и отдельной БД, frontend — с переменными для тестового API (NEXT_PUBLIC_API_URL), и cypress запускается после поднятия всех сервисов.
- На старте backend выполняйте миграции и загрузку фикстур в тестовую БД.
- В CI используйте ту же конфигурацию — reproducible и изолировано от dev.
Если нужно, могу:
- Привести полный пример docker-compose.test.yml под ваш конкретный стек (покажите текущие docker-compose.yml).
- Написать пример entrypoint скрипта для Symfony с миграциями и фикстурами.
- Показать пример cypress.config.js и команд для локального запуска тестов.