GH GambleHub

Unit vs Integration тесты

1) Зачем различать типы тестов

Правильная грануляция тестов делает разработку предсказуемой: Unit ловят дефекты логики быстро и дешево; Integration проверяют связки модулей, реальный транспорт и «клей». Вместе они уменьшают регресс и ускоряют релизы.

2) Определения и границы

Unit-тест

Проверяет малую единицу поведения (функцию, класс, use-case) в изоляции.
Внешние зависимости заменены (mock/stub/fake).
Быстрый (мс–десятки мс), детерминированный.

Integration-тест

Проверяет взаимодействие нескольких реальных компонентов: БД, брокер (Kafka/RabbitMQ), HTTP/gRPC, файловая система, кэш.
Минимум моков, реальные протоколы.
Медленнее (сотни мс–секунды), дороже по поддержке.

💡 Правило: как только «переходим процесс/сокет/БД» — мы уже в интеграционных водах.

3) Пирамида тестирования (а не ледяной рожок)

Основание: Unit (70–80% по количеству) — дешево, быстро.
Средний слой: Integration/Component (15–25%) — критичные пути и контракты.
Верх: E2E/UX/Exploratory (5–10%) — минимально достаточно.
По бокам: Static Analysis/Lint/Type check и Mutation testing как усилители качества.

4) Что отдавать Unit, а что — Integration

ЗадачаТипПочему
Чистая бизнес-логика (валидации, расчеты комиссий, идемпотентность ключей)UnitБыстро, детерминированно, много граничных значений
Маппинги DTO↔модель, сериализация, парсингUnitМного кейсов, легко изолировать
Репозитории/ORM-запросыIntegration (с test DB)«Поведение» ORM и SQL нюансы видны только на живой БД
HTTP-контракт (статусы, заголовки, схемы)Integration / ContractНужен живой стек HTTP + JSON Schema/OpenAPI
Saga/Outbox, ретраи, дедлайныIntegration / ComponentТайминги, транзакционность, брокер
Rate limit в gatewayIntegrationRedis/стейт/таймауты
Платежные вебхуки (HMAC, повтор)Integration / CDCПодписи, часы, сетевые особенности

5) Данные и фикстуры

Unit

Inline фикстуры/билдеры (factory methods).
Табличные тесты (table-driven) для граничных значений.
Property-based подход для инвариантов (например, «сумма дебетов = сумме кредитов»).

Integration

Hermetic окружение: Testcontainers/Docker Compose поднимают `postgres + redis + kafka + wiremock`.
Начальный seed в БД/кэше и очистка после (транзакция/rollback, truncate).
Часы/таймеры — фейковые (контролируемые), иначе флаки.

6) Инструменты и паттерны

Mocks/Stubs/Fakes/Spies:
  • Stub — фиксированный ответ (дешево).
  • Mock — проверка взаимодействий/количества вызовов.
  • Fake — упрощенная реализация (например, In-Memory Repo).
  • Contract testing (CDC): Pact/Swagger-based — фиксируем ожидания клиента и проверяем провайдера.
  • WireMock/MockServer — HTTP-заглушки для сторонних сервисов.
  • Testcontainers — живые БД/брокеры локально и в CI без «зоопарка».

7) Примеры

7.1 Unit: идемпотентность платежа (pseudocode)

python def test_idempotent_create_payment_returns_same_id():
repo = InMemoryPayments()
service = Payments(repo)

first = service. create(amount=100, key="abc")
second = service. create(amount=100, key="abc")

assert first. id == second. id assert repo. count() == 1

7.2 Integration: подпись вебхука (HMAC) + повтор

bash docker-compose: app + redis + wiremock (PSP)
docker compose -f docker-compose. test. yml up -d pytest -m "integration and webhook" -q
Тест:
  • WireMock отдает событие с `X-Timestamp` и подписью.
  • Приложение проверяет HMAC, дедуплицирует по `event_id`, повтор через 5 сек не создает дубль.
  • Проверяем `200` и, что запись одна.

7.3 CDC: контракт клиента к провайдеру

Клиент формирует Pact (ожидание: `POST /v1/payout` → `201` со схемой).
Провайдер в CI прогоняет верификацию контракта на своем стенде.

8) Скорость, параллельность, флейки

Unit должны работать <100 мс на тест; пакет — секунды.
Integration — параллелить по контейнерам/портам; использовать миграции на запуске.

Flaky-антидот:
  • контролируемое время (fake clock),
  • ожидания «по явному событию», а не `sleep`,
  • стабильные пороги (ретраи с джиттером тестировать детерминированно).

9) Метрики качества

Coverage (строчки/ветви): полезно для наблюдения тренда, но не цель.
Mutation testing (PIT/Mutmut): показывает, «убивают ли» тесты ложные изменения — реальная сила ассуренса.
Test duration и flaky rate: алерты при росте.
Defect containment: доля багов, перехваченных до продакшена.

10) Встраивание в CI/CD

Джобы: unit → integration → e2e (fan-out по сервисам).
Кэш зависимостей, параллельные матрицы по БД/языкам/версиям.
Отчеты: JUnit/Allure + артефакты логов контейнеров (при падениях).
Gate: «зеленые unit + критические integration» — условие мержа; e2e — на nightly.

Пример матрицы (GitHub Actions, фрагмент):
yaml strategy:
matrix:
db: [postgres14, postgres16]
steps:
- run: docker run -d --name db -e POSTGRES_PASSWORD=pw postgres:${{ matrix. db }}
- run: pytest -m "unit" -q
- run: pytest -m "integration" -q

11) Микросервисы и события

Сервисные контракты: OpenAPI/Protobuf версионируются; тесты на совместимость (backward).

Event-driven:
  • Unit: маппинг доменных событий и инварианты.
  • Integration: публикация/подписка в реальном брокере (Kafka), outbox/inbox семантика, exactly-once имитация (по крайней мере — idempotent).
  • Тесты ретраев/дубликатов/переупорядочивания (out-of-order).

12) Данные и изоляция в Integration

Каждый тест → уникальная схема/БД (Testcontainers JDBC URL `?TC_TMPFS=/var/lib/postgresql/data:rw`).
Транзакционные фикстуры (begin→run→rollback) ускоряют чистку.
Для Redis/кэша — ключевой префикс `test:${RUN_ID}:` и `FLUSHDB` в teardown.

13) Специфика iGaming/финансов

Деньги и лимиты: property-based тесты на инварианты (баланс ≥ 0, суммарные ограничения).
Регуляторика: проверка журналирования (аудит-лог пишется), неизменяемые события.
Платежи/PSP: интеграционные тесты HMAC/mTLS, `Retry-After`, идемпотентность, дедуп `jti`.
Ответственная игра: тесты правил порогов/кулдаунов; «вчера→сегодня» на fake clock.

14) Антипаттерны

«Unit», которые поднимают БД/HTTP — это уже integration (путают слои и замедляют CI).
Высокий coverage за счет пустых утверждений («покрыли, но не проверили»).
Моки логики сторонних сервисов там, где нужен контракт (ломается при обновлении).
Тесты с `sleep(5)` вместо ожиданий события/условия.
Общая тестовая БД для параллельных тестов → гонки и флейки.

15) Чек-лист prod-готовности

  • Пирамида определена: % долей Unit/Integration/E2E и цели по времени прогона.
  • Unit изолированы, быстрые, покрывают граничные значения и инварианты.
  • Integration используют hermetic-окружение (Testcontainers/Compose), без общих стейтов.
  • Контрактные тесты (OpenAPI/Pact) верифицируются в CI.
  • Данные тестов — управляемые: seed/rollback/префиксы, fake clock.
  • Параллельный прогон, отчеты JUnit/Allure, артефакты логов контейнеров.
  • Метрики: duration, flaky rate, mutation score; алерты на деградацию.
  • Платежные/вебхук-сценарии: HMAC/mTLS, ретраи, идемпотентность, дедуп.
  • Документация стратегии и примеры шаблонов тестов.

16) TL;DR

Unit — максимум логики, минимум окружения; Integration — минимум моков, максимум реализма. Держите пирамиду: быстрые Unit ловят 80% дефектов, Integration подтверждают связки и контракты. Используйте hermetic-контейнеры, контрактные тесты, fake clock и параллельность. Мерьте не только coverage, но и mutation score и flaky rate. Особо проверьте платежные/вебхук-пути: подписи, ретраи и идемпотентность.

Contact

Свяжитесь с нами

Обращайтесь по любым вопросам или за поддержкой.Мы всегда готовы помочь!

Начать интеграцию

Email — обязателен. Telegram или WhatsApp — по желанию.

Ваше имя необязательно
Email необязательно
Тема необязательно
Сообщение необязательно
Telegram необязательно
@
Если укажете Telegram — мы ответим и там, в дополнение к Email.
WhatsApp необязательно
Формат: +код страны и номер (например, +380XXXXXXXXX).

Нажимая кнопку, вы соглашаетесь на обработку данных.