сайт в бете
нашли баг? напишите
левин. записаться
весь блог
Автоматизация 2026-09-01

Интеграционные тесты руками агента: что я проверяю до мержа

Раннер Medusa поднимает приложение целиком, агент пишет сценарии, я проверяю, что эти сценарии вообще способны упасть. Разбираю свой чек-лист перед мержем и три места, где агенту нельзя верить на слово.

Л
Проект Левин
автор

Когда я собирал витрину на Astro поверх Medusa, почти каждый коммит трогал стык двух систем. Конфиг nginx с редиректами, YML-фид для маркетплейсов, CI/CD, потом Dockerfile для Medusa и calculated_price, который витрина упорно не получала. Ни одна из этих поломок не ловится юнит-тестом: функции по отдельности работают, разваливается склейка.

Поэтому перед каждым мержем я прошу агента прогнать интеграционные тесты. Ниже — что именно я проверяю и где агенту нельзя верить на слово.

Почему интеграционные

Medusa даёт для этого готовый раннер в medusa-test-utils. Он поднимает приложение целиком — с контейнером зависимостей и HTTP-клиентом, — так что тест ходит по настоящему роуту:

import { medusaIntegrationTestRunner } from "medusa-test-utils"

medusaIntegrationTestRunner({
  testSuite: ({ api, getContainer }) => {
    describe("GET /store/custom", () => {
      it("returns correct message", async () => {
        const response = await api.get(`/store/custom`)
        expect(response.status).toEqual(200)
      })
    })
  },
})

Ключевое здесь — api и getContainer. Первый бьёт по роуту как реальный клиент. Второй даёт доступ к сервисам: подготовить данные до запроса и проверить состояние базы после. Этого хватает, чтобы ловить большинство поломок на склейке.

Как я ставлю задачу агенту

Формулировка «напиши тесты для роута» даёт бесполезный результат: агент проверит статус 200 и успокоится. Работает другая постановка — я описываю сценарий словами клиента, и агент сам решает, что для этого нужно поднять.

  • «Покупатель открывает карточку товара и видит цену для своего региона» → тест на calculated_price в ответе /store/products
  • «Маркетплейс скачивает фид и видит все активные товары» → тест на структуру YML и состав позиций
  • «Старый URL со старого сайта ведёт на новую карточку» → проверка редиректа

Такая формулировка заставляет агента лезть в контейнер за реальными данными, вместо того чтобы подменять ответ заглушкой.

Чек-лист до мержа

Что я прогоняю перед каждым merge:

  1. Роуты витрины. Статус, форма ответа, обязательные поля. Для товаров — наличие calculated_price. Именно на нём я один раз обжёгся: цена приходит только при правильном контексте региона, и без него витрина показывает пустоту.
  2. Побочные эффекты. После POST идём через getContainer() в сервис и смотрим, что запись создалась с нужными полями. Ответ 201 сам по себе ничего не доказывает.
  3. Ошибки. Невалидный id, отсутствующий регион, пустая корзина. Агент по умолчанию пишет только happy path, эту часть приходится требовать явно.
  4. Внешние контракты. YML-фид парсится как валидный XML, обязательные элементы на месте. Фид ломается тихо: узнаёшь об этом от маркетплейса через неделю.
  5. Сборка. Зелёные тесты локально мало значат, если Dockerfile собирает другое окружение. Прогон идёт в том же образе, который уедет на прод.

Три места, где агент врёт

Тест, который не может упасть. Классика жанра: expect(response.status).toBeLessThan(500). Формально зелёный, смысла ноль. Лечится грубо: прошу агента специально сломать код и показать красный прогон. Если тест остался зелёным, он мусор.

Заглушка вместо интеграции. Когда тест долго не проходит, агент начинает упрощать себе жизнь: подменяет сервис моком, и тест начинает проверять мок. Признак — jest.mock внутри интеграционного теста. Это повод остановиться и разобраться, почему настоящий сервис не поднялся.

Отчёт без запуска. Самое неприятное. Агент пишет «все тесты проходят», а прогона не было. Я всегда требую вывод команды целиком: сколько тестов, сколько прошло, сколько времени заняло. Нет вывода — нет зелёного.

Что это в итоге даёт

Роль сместилась: теперь я приёмщик тестов. Агент пишет их быстрее, чем я успеваю сформулировать сценарий, и это честно экономит время. Взамен я держу дисциплину проверки — каждый новый тест обязан доказать, что умеет краснеть.

Финальный вопрос перед мержем всегда один: если я сейчас сломаю эту функцию, какой тест покраснеет? Когда внятного ответа нет, тестов недостаточно, сколько бы их ни было в отчёте.

теги #medusa#интеграционные тесты#ai-агент#ci/cd#astro
разберём вашу задачу

Исследовательская сессия автоматизации

Очно или в Zoom разбираю вашу работу изнутри, ставлю гипотезы и тут же применяю их на реальной задаче. Уходите с инструментом, который уже работает.

один разговор — и поймём, чем я могу помочь.

В эпоху ИИ человеку нужен человек. Сяду рядом и доведу до результата — встреча длится столько, сколько нужно. Без скрипта продаж и пакетов «за 999 000 ₽». Если пойму, что помочь не смогу, — скажу сразу.