Перейти к содержимому
Интеграционное тестирование

Интеграционное тестирование

Интеграционное тестирование проверяет, как API работает с реальными зависимостями (БД, внешние сервисы), в отличие от модульных тестов (где всё заглушено). Проверяет контракт API (статусы, схемы), создание/чтение/обновление/удаление в БД, обработку ошибок внешних систем и авторизацию. Обычно запускается в Docker-контейнерах (чтобы поднять тестовую БД). Не проверяет производительность, безопасность (глубоко) и доступность. Контрактное тестирование (Pact) — клиент определяет контракт, сервер проверяет, чтобы изменение API не сломало клиента.

Введение: Когда детали собираются вместе

Представьте, что вы проверили каждую деталь механизма отдельно: шестерёнка крутится, пружина сжимается, винт закручивается. Но когда вы собрали механизм, он всё равно не работает. Шестерёнка не попадает в паз, пружина слишком слабая для веса.

Модульные тесты проверяют детали по отдельности. Интеграционное тестирование проверяет, как эти детали работают вместе.

В мире API интеграционное тестирование проверяет взаимодействие между компонентами: API → база данных, API → внешний сервис, сервис → сервис. Это тесты, которые запускают реальный API (или его часть) и проверяют, что он правильно общается с зависимостями.

Для системного аналитика интеграционное тестирование — это проверка того, что API соответствует контракту (спецификации). Модульные тесты проверяют код. Интеграционные тесты проверяют поведение системы. Если интеграционные тесты проходят, API делает то, что обещано.

Место интеграционного тестирования в пирамиде тестов

    graph TD
    A[E2E тесты<br>мало, медленные] --> B[Интеграционные тесты<br>средне, средние]
    B --> C[Модульные тесты<br>много, быстрые]
  
УровеньЧто проверяетЗависимостиСкорость
МодульныеОдин методИзолированы (mock)Миллисекунды
ИнтеграционныеСвязь компонентовРеальные (БД, API)Секунды
E2EВесь сценарийВсе зависимостиМинуты

Почему интеграционные тесты важны:

  • Модульные тесты не ловят проблемы интеграции (неправильные параметры, форматы данных, сетевые таймауты)
  • Без интеграционных тестов ошибки находят только на E2E (поздно и дорого)
  • Интеграционные тесты — компромисс между скоростью и реалистичностью

Что тестируют интеграционные тесты API

Контракт API

Что проверяетПример
Пути (paths)/users существует, /users/{id} существует
МетодыGET /users/{id} работает, POST /users работает
Статус-кодыУспех → 200, создано → 201, не найдено → 404
ЗаголовкиContent-Type: application/json, Location для создания
Тело ответаСтруктура JSON соответствует схеме

Взаимодействие с базой данных

Что проверяетПример
СозданиеPOST /users → запись появилась в БД
ЧтениеGET /users/{id} → данные из БД
ОбновлениеPUT /users/{id} → запись в БД изменилась
УдалениеDELETE /users/{id} → запись исчезла из БД
ТранзакцииПри ошибке данные не сохранились

Взаимодействие с внешними сервисами

Что проверяетПример
ВызовыAPI вызывает внешний платёжный шлюз
Обработка ответовШлюз вернул успех → заказ оформлен
Обработка ошибокШлюз вернул ошибку → заказ не оформлен
ТаймаутыШлюз не ответил → API вернул 504
ПовторыПри временной ошибке API повторяет запрос

Аутентификация и авторизация

Что проверяетПример
Отсутствие токена401 Unauthorized
Неверный токен401 Unauthorized
Просроченный токен401 Unauthorized
Недостаточно прав403 Forbidden
Достаточно прав200 OK

Интеграционные vs Модульные тесты

ХарактеристикаМодульныеИнтеграционные
ЗависимостиMock (заглушки)Реальные (БД, API)
СкоростьМиллисекундыСекунды
СредаЛокальная (без развёртывания)Требует БД, контейнеров
Что ловятОшибки в логикеОшибки в связях
КоличествоМного (сотни)Средне (десятки)
Типичная проблемаНе заметили пустой списокНе сходится формат даты с БД

Аналогия: Модульные тесты — проверка детали на станке. Интеграционные — сборка узла и проверка, что детали подходят друг другу.

Среда для интеграционного тестирования

Контейнеризация (Docker)

Самый популярный подход. Тесты поднимают контейнеры с зависимостями перед запуском.

ЗависимостьКонтейнер
База данныхPostgreSQL, MySQL, MongoDB
ОчередиKafka, RabbitMQ
КешRedis
Внешние APIWireMock (имитация)

Что видит аналитик: Тесты запускаются в CI, поднимают контейнеры, выполняются, контейнеры уничтожаются.

Тестовая база данных

Для интеграционных тестов используется отдельная БД (не production, не development).

Требования к тестовой БД:

ТребованиеПочему
Чистая перед каждым тестомТесты не должны влиять друг на друга
Сброс после тестовНе оставлять мусор
Схема как в productionИдентичные структуры

Внешние API (WireMock)

Для внешних API используют заглушки (mock-серверы). WireMock — популярный инструмент.

Что даёт WireMock:

ВозможностьПример
Симуляция ответовGET /payment/123 → 200 OK
Симуляция ошибокGET /payment/123 → 500 Internal Error
Проверка вызововУбедиться, что API вызвал внешний сервис
ЗадержкиСимуляция медленного ответа

Что аналитик должен знать об интеграционных тестах

Какие требования проверяются

Тип требованияПроверяется интеграционными тестами?
ФункциональныеДа
ВалидационныеДа
Контракт APIДа
Обработка ошибокДа
Аутентификация/авторизацияДа
ПроизводительностьНет (нагрузочное тестирование)
БезопасностьЧастично (не пентест)
ДоступностьНет (инфраструктурное)

Примеры требований, проверяемых интеграционными тестами

ТребованиеИнтеграционный тест
“При создании заказа отправляется событие в Kafka”Проверить, что сообщение появилось в топике
“Email пользователя должен быть уникален”Создать пользователя с email, попробовать создать второго — получить 409
“При удалении пользователя удаляются его заказы”Создать пользователя с заказами, удалить, проверить, что заказы исчезли

Как читать отчёт об интеграционных тестах

Integration Tests Report
=======================
Tests run: 45
Passed: 43
Failed: 2
Skipped: 0

Failed tests:
- testCreateOrder_PaymentGatewayTimeout
  ожидал: 503 Service Unavailable
  получил: 500 Internal Server Error
  причина: PaymentService не обрабатывает таймаут

- testGetUser_WithOrders
  ожидал: поле orders в ответе
  получил: поле order_list
  причина: Несовпадение имени поля в API и БД

Что видит аналитик:

  • Сколько тестов упало
  • Какие именно тесты
  • В чём расхождение между ожидаемым и фактическим

Контрактное тестирование (Consumer-Driven Contracts)

Что это

Специальный вид интеграционного тестирования, где клиент (consumer) определяет, какой контракт он ожидает от API (provider).

    graph LR
    A[Клиент<br>определяет контракт] --> B[Провайдер<br>проверяет контракт]
    B --> C[Уверенность, что клиент не сломается]
  

Инструменты

ИнструментЯзыкиОсобенность
PactМногиеСамый популярный
Spring Cloud ContractJavaИнтеграция со Spring
PactumJSJS/TSЛёгкий

Пример сценария (аналитик понимает)

Клиент (фронтенд) определяет:

При GET /users/123 ожидаю:
- Статус 200
- Тело содержит id (число) и name (строка)
- name не пустой

Провайдер (API) проверяет, что соответствует контракту.

Что даёт:

ПреимуществоОбъяснение
Раннее обнаружениеAPI узнает, что изменение сломает клиента
Независимость командКлиент и сервер могут развиваться отдельно
ДокументацияКонтракт = документация

Интеграционные тесты в CI/CD

Где запускаются

    graph LR
    A[Модульные тесты] --> B[Интеграционные тесты]
    B -->|Прошли| C[Деплой в staging]
    B -->|Упали| D[Остановка]
  

Что нужно для запуска

КомпонентПочему
Docker / Docker ComposeПоднять БД, Kafka и т.д.
Ресурсы (CPU, RAM)БД требует памяти
СетьДоступ к внешним API (или их заглушкам)
ВремяСекунды или минуты

Время выполнения

Тип тестовТипичное время
Модульные1-10 секунд
Интеграционные10-60 секунд
E2E1-10 минут

Проблемы интеграционного тестирования

Проблема 1: Нестабильные тесты (Flaky)

Тест то проходит, то падает без изменения кода.

Причины:

ПричинаРешение
Гонка данных (race condition)Синхронизация
Зависимость от порядка тестовИзоляция тестов
ТаймаутыУвеличить таймауты
Внешние APIИспользовать WireMock

Проблема 2: Долгое время выполнения

Слишком много интеграционных тестов → CI идёт долго → разработка замедляется.

Решение:

СтратегияКак
Параллельный запускРазделить тесты на группы
Выборочный запускТолько тесты, связанные с изменениями
Пирамида тестовБольше модульных, меньше интеграционных

Проблема 3: Окружение

Тесты падают в CI, но работают локально.

Причины:

ПричинаРешение
Разные версии БДОдинаковые контейнеры
Разные переменные окруженияКонфигурация через env
Сетевые ограниченияWireMock вместо реальных API

Проблема 4: Чистота данных

Тесты влияют друг на друга (один создал пользователя, другой не может его создать).

Решение:

СтратегияКак
Откат транзакцийКаждый тест в транзакции → откат после теста
Уникальные данныеtimestamp в именах
Чистая БД перед каждым тестомTRUNCATE всех таблиц

Сравнение с другими уровнями тестирования

ХарактеристикаМодульныеИнтеграционныеE2E
ЗависимостиMockРеальные + mockВсе реальные
СредаЛокальнаяКонтейнерыStaging/Prod
Времямссмин
КоличествоСотниДесяткиЕдиницы
Что ловятЛогикуСвязиВесь сценарий
Стоимость починкиДешёвоСреднеДорого

Что аналитик должен требовать от команды

ТребованиеПочему
“Есть ли тесты на все эндпоинты?”Без тестов эндпоинт может сломаться
“Есть ли тесты на ошибки (400, 401, 403, 404)?”Пользователи ошибаются, API должен отвечать корректно
“Тесты запускаются в CI при каждом коммите?”Чем раньше найдём ошибку, тем дешевле
“Могу ли я посмотреть отчёт о тестах?”Прозрачность качества
“Сколько времени идут интеграционные тесты?”Влияет на скорость разработки

Резюме

  1. Интеграционное тестирование — проверка взаимодействия между компонентами. API → БД, API → внешний сервис, сервис → сервис.

  2. Что проверяет: контракт API (пути, методы, статусы, схемы), взаимодействие с БД, внешние вызовы, аутентификацию/авторизацию.

  3. В отличие от модульных: использует реальные зависимости (БД, API), медленнее, но реалистичнее.

  4. Среда: контейнеры (Docker), тестовая БД, WireMock для внешних API.

  5. Контрактное тестирование (Pact) — клиент определяет контракт, сервер проверяет. Уверенность, что изменение API не сломает клиента.

  6. Проблемы: нестабильные тесты (flaky), долгое время выполнения, чистота данных между тестами.

  7. В CI/CD: интеграционные тесты запускаются после модульных, перед деплоем. Если падают — деплой останавливается.

Проверка знаний

Вопрос 1 из 4
Что из перечисленного прямо относится к интеграционным тестам API?
Какое место интеграционные тесты занимают в пирамиде тестов?
Зачем в интеграционных тестах часто используют Docker и WireMock?
Что обычно происходит в CI/CD, если интеграционные тесты падают?

Вопросы, где были ошибки