62 подписчика
Что такое интеграционное тестирование, и как мы дошли до жизни такой
Если бы QA-процессы были сериалом, то юнит-тесты были бы первой серией: короткие, местами скучные, но дают понять, кто есть кто. А вот интеграционные тесты — это середина сезона. Вроде бы уже разобрались с персонажами, но именно сейчас начинает закручиваться сюжет.
Интеграционное тестирование — это проверка взаимодействия между модулями, сервисами, компонентами, библиотеками и всем тем, что разработчики уверенно называют «инкапсулированным» и «изолированным». Суть в том, чтобы понять: не только работает ли каждый из них по отдельности, но и работают ли они вместе.
Допустим, у нас есть три модуля:
- фронт: форма логина;
- бэк: сервис авторизации;
- база: хранит пользователей и токены.
Каждый из них отдельно может быть идеально покрыт юнитами. Но когда фронт отправляет логин и пароль, бэк должен это распарсить, сходить в базу, получить токен и отдать его обратно. И вот тут начинается реальность. Не «идеальная модель мира», а тот самый момент, где JSON окажется в другом регистре, токен в другом формате, а база внезапно не вернёт ничего — потому что в миграции забыли поле is_active.
Вот для этого и нужно интеграционное тестирование.
Юнит — это проверка логики одного блока. Например, функция validate_email() работает как задумано. Интеграция — это когда validate_email() используется внутри register_user(), который потом вызывает send_confirmation_email(), и ты проверяешь, что всё вместе работает.
Интеграция:
- проверяет цепочку действий,
- тестирует коммуникацию между сервисами и компонентами,
- выявляет ошибки «на стыке» (а именно они и валятся на проде чаще всего).
В интеграционном тестировании мы тестируем:
1. Связь между модулями
- API вызывает нужные ручки
- фронт корректно обрабатывает ответ
2. Обмен данными
- правильно ли сериализуются и десериализуются объекты
- нет ли багов при маппинге данных между слоями
3. Логика между сервисами
- пользователь зарегался → письмо отправилось → запись появилась в БД
4. Обработка ошибок
- если зависимый сервис упал, система не развалилась
Как писать интеграционные тесты?
Как и всё хорошее в жизни — с пониманием, зачем ты это делаешь.
1. Окружение
Нужна среда, максимально приближённая к боевой. Обычно это:
docker-compose со всеми зависимостями (БД, кэш, сторонние сервисы);
настроенная CI-сборка, в которой можно гонять интеграционные тесты отдельно от юнитов (они дольше и сложнее в поддержке);
фейковые сервисы или моки, если реальных нет.
2. Инструменты
- На Python — pytest, requests, docker-compose, testcontainers
- На JS — Jest, Supertest, msw
- На Java — SpringBootTest, Testcontainers, WireMock
Главное — не пытаться всё мокать. Интеграция — это как раз чтобы проверить, как настоящие сервисы взаимодействуют.
3. Сценарии
Пиши не от интерфейса, а от процессов. Не «открываю страницу», а «пользователь логинится», «оплачивает подписку», «смотрит видео». Нам нужно проверить именно интеграцию, а не нажатие конкретной кнопки.
Каждый сценарий — это:
- начальные данные (юзер, товар, токен);
- действия (запросы, симуляции);
- ожидания (ответ, запись в БД, письмо ушло, пуш отправлен).
Проблемы, с которыми придется столкнуться:
Сложно дебажить. Если тест падает, не всегда понятно, где именно сломалось: в логике, в окружении или в данных. Нужно писать хорошие логи и уметь воспроизводить руками.
Хрупкие тесты. Если структура ответа поменялась — тест падает. Нужно отдельно изучать JSON-hell.
Время выполнения. Интеграционные тесты всегда медленнее. Поэтому в CI/CD лучше отделять их от юнитов.
Чем интеграционный тест отличается от е2е теста? Интеграция — это внутри одной системы: API + БД, или два сервиса между собой; e2e — это когда мы симулируем действия конечного пользователя: от клика по кнопке до оплаты.
Например: запрос POST /payment и проверка, что платёж создан и запись попала в базу — это интеграция. А вот открыть браузер, зайти в профиль, нажать «оплатить» и получить письмо — это e2e.
3 минуты
6 июня