Logo GH

Контрактное тестирование API

1) Зачем контрактное тестирование

Контракт фиксирует ожидания клиента и обещания провайдера: маршруты/методы, заголовки, схемы тел, статусы, семантика ошибок и ограничения. Цель — ловить несовместимые изменения до интеграции и выпускать версии безопасно, без тяжелых E2E.

2) Подходы

Consumer-Driven Contracts (CDC): клиент формирует ожидания (Pact и аналоги); провайдер регулярно их верифицирует.
Спецификационный: контракт как единый источник истины (OpenAPI/Protobuf/GraphQL SDL); тесты валидируют реализацию против спецификации.
Событийный: схемы сообщений (Avro/JSON Schema/Protobuf) + правила совместимости в брокере/реестре.

3) HTTP/REST: спецификационный поток

1. Контракт: OpenAPI 3.x (схемы, примеры, коды).
2. Линт и статанализ: стиль, обязательные поля, единые коды.
3. Валидация реализации: генератор тестов против OpenAPI (schemathesis/Dredd-подход) + ручные негативы.
4. Снапшоты: фиксируйте примеры ответов, ETag семантику, заголовки идемпотентности.

Пример negative-контракта (фрагмент OpenAPI):
yaml paths:
/v1/payments:
post:
responses:
"201": { $ref: "#/components/responses/PaymentCreated" }
"409": { description: Duplicate by Idempotency-Key }
"422": { description: Schema/Business validation failed }

4) CDC (Pact-подход)

Жизненный цикл:

1. Consumer пишет тест, формирует pact-файл (ожидания).

2. Публикация в брокер (артефакт).

3. Provider в CI поднимает сервис (или контракт-стойку), верифицирует pact’ы.

4. Брокер вычисляет can-i-deploy матрицу совместимости.

Пример consumer-теста (псевдо-JS):
js pact
.given("wallet exists")
.uponReceiving("get wallet")
.withRequest({ method:"GET", path:"/v1/wallets/w123", headers:{ "Authorization": term({generate:"Bearer x", matcher:/^Bearer\s.+/}) }})
.willRespondWith({
status: 200,
headers: { "Content-Type": "application/json" },
body: like({ id:"w123", currency: "EUR", balance: 0 })
});

5) gRPC/Protobuf контракты

Контракт — `.proto` с версионированием пакетов/служб.
Совместимость: не переиспользовать теги, только добавлять новые с optional, не удалять используемые поля; резервировать номера.
Тесты: генерация стаба сервера/клиента, прокат автосгенеренных кейсов + негативы (unknown fields, size-limits).

6) Событийные контракты (Kafka/NATS/…)

Схемы: Avro/JSON Schema/Protobuf в Schema Registry.
Политика совместимости: `BACKWARD` (часто достаточно) или `FULL`.
Тесты продьюсера: валидирует сообщение против схемы; тесты консьюмера: принимает старую и новую версию.
Инварианты: ключи идемпотентности, порядок/повторяемость, семантика дедупликации.

Пример Avro-схемы (фрагмент):
json
{"type":"record","name":"PayoutCreated","fields":[
{"name":"payoutId","type":"string"},
{"name":"amount","type":"double"},
{"name":"currency","type":{"type":"string","logicalType":"iso-4217"}}
]}

7) Совместимость и версии

Backward-compatible (рекомендуемый минимум): добавляйте необязательные поля, не ломайте существующие.
Forward-compatible: потребители игнорируют неизвестные поля.
Full: и то, и другое.
Версионирование: `path (/v1)`, `Accept: application/vnd.brand.v2+json`, `proto package v2`.
Deprecation-политика: окно вывода (например, 90 дней), предупреждающие заголовки/события.

8) Негативные и ошибки — это тоже контракт

Стандартизируйте коды: 400/401/403/404/409/422/429/5xx, обязательные поля `code`, `message`, `trace_id`.
Размеры/лимиты — часть контракта (413/414/431).
Идемпотентность: поведение при повторе (409 vs 201 same id).
Заголовки: `Retry-After` при 429/503, `Idempotency-Key`, `Content-Language` и т. п.

Шаблон ошибки:
json
{ "code":"validation_error", "message":"amount must be ≥ 1", "trace_id":"..." }

9) Данными управляет контракт

Примеры/примерочные ответы (examples) — живые, валидируются в CI.
Фикстуры для CDC — минимальные, детерминированные.
Генерация данных — property-based для чисел/дат; но не ломать стабильность снапшотов.

10) Пайплайн в CI/CD (референс)

1. Lint/validate: OpenAPI/Proto/Avro (`validate`, style-линер).
2. Publish: контракт как артефакт (брокер/реестр).
3. Verify: провайдер прогоняет CDC-пакеты/спецификационные тесты.
4. can-i-deploy gate: без зеленой матрицы релиз запрещен.
5. Diff: проверка, что изменения совместимы (semantic diff).
6. Report: JUnit/HTML, список нарушений/дефиниций.

Псевдо-матрица:
yaml jobs:
lint:...
publish-contract: needs: [lint]
verify-provider: needs: [publish-contract]
can-i-deploy:
if: always()
steps: [run: pact-broker can-i-deploy...]

11) Инструменты (по классам задач)

Линт/валидаторы: openapi-linters, protobuf-lint, avro-tools.
CDC: Pact-семейство/брокер, Spring Cloud Contract, Hoverfly (HTTP записи/реплеи).
Спецификационные раннеры: schemathesis/Dredd-подобный подход, Postman test + JSON Schema.
Diff: semantic-diff OpenAPI/Proto/Avro (выявляет breaking-изменения).
Контейнеры: Testcontainers для поднятия провайдера/стойки контрактов.

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

«Спец-док» отдельно от кода → рассинхронизация. Храните контракт рядом с сервисом.
Моки стороннего сервиса вместо контракта → хрупкость при апдейтах.
Случайные ответы/генерация без привязки к схеме → флейки.
Изменение типов/обязательности полей без версии.
Silent-расширения без уведомлений/депрекации.
Отсутствие негативных контрактов и кодов ошибок.

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

Формализуйте денежные поля: `amount` — decimal с масштабом, валюта — ISO-4217, инварианты сумм.
Контракты платежей/вебхуков: HMAC/mTLS, anti-replay (`X-Timestamp` окно), идемпотентность, `Retry-After`.
Региональность/тенанты: обязательные заголовки `X-Tenant/X-Region`, локализация сообщений.
События: неизменяемые журналы (audit), ключи дедупликации, гарантии доставки (at least once + идемпотентные хендлеры).

14) Примеры «скелетов» тестов

14.1 Schemathesis-стиль (псевдо)

bash schemathesis run openapi. yaml --checks all --hypothesis-deadline=200

14.2 Postman как спецификационный раннер

js pm. test ("Scheme/v1/wallets/{ id} is valid," () => {
const schema = pm. collectionVariables. get("wallet_get_schema");
pm. expect(ajv. validate(JSON. parse(schema), pm. response. json())). to. be. true;
});

14.3 Provider-верификация CDC (псевдо)

bash pact-broker can-i-deploy --pacticipant wallets --version $SHA --to-environment staging

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

  • Контракты в репозитории, CI валидирует и публикует артефакты.
  • CDC включен для критичных интеграций; работает broker/matrix «can-i-deploy».
  • Политика совместимости (HTTP/gRPC/Events) задокументирована; автоматический semantic-diff.
  • Негативные контракты: ошибки, лимиты размеров, идемпотентность, `Retry-After`.
  • Тест-данные детерминированы; снапшоты примеров поддерживаются.
  • Версионирование и deprecation: сроки, уведомления, заголовки.
  • Для событий — Schema Registry и режим совместимости; продьюсер/консьюмер тестируют обе версии.
  • Артефакты: JUnit/HTML, отчеты diff/verify, матрица совместимости.
  • Инцидент-процедура: быстрый rollback контракта/фича-флаг, уведомление интеграторам.

16) TL;DR

Фиксируйте ожидания в контрактах и прогоняйте их автоматически: CDC для клиентских ожиданий, спецификационные тесты для соответствия реализации, реестр схем для событий. Держите строгую политику совместимости и негативные контракты (ошибки, лимиты, идемпотентность). Нельзя релизить без зеленой can-i-deploy матрицы и semantic-diff без breaking-изменений.

Contact

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

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

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

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

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

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