Как лучше организовать и настроить процесс тестирования в проекте, использующем Symfony на бэкенде и Next.js на фронтенде?

Есть проект: бэкенд на Symfony и фронт на Next.js, всё запущено в Docker. Пишу e2e-тесты на Cypress. При локальном запуске Symfony работает в окружении dev (потому что проект поднят как dev), а мне нужно, чтобы тесты использовали окружение test, как это делает phpunit. Как это правильно организовать: поднимать отдельный бэкенд с env=test, если локально уже работает бэкенд с env=dev, или есть другой способ? И как через Cypress заставить Next.js запускаться в test-окружении?
  • 1 апреля 2026 г. 9:00
Ответы на вопрос 2
Коротко: для 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 и команд для локального запуска тестов.
у меня на похожем стеке (symfony + react, но суть та же) просто отдельный <code>docker-compose.test.yml</code> где бэк стартует с <code>APP_ENV=test</code> , а фронту кидаешь нужные env через <code>.env.test</code> . поднимаешь рядом на других портах и cypress бьёт туда. не пытайся переключать env у запущенного стека — проще поднять второй рядом
Похожие вопросы