Тесты на контракт (contract testing)

Бесплатная консультация юриста

+7 (800) 301-07-30

Реклама jurik.ru

Тесты на контракт (contract testing) – это методика проверки взаимодействия между сервисами, когда одна сторона (поставщик) обязуется предоставить определённый API, а другая (потребитель) – использовать его согласно договорённостям. Правильный подход к сдаче таких тестов позволяет избежать дорогостоящих багов в продакшене и ускорить процесс интеграции.

Что такое тесты на контракт и зачем они нужны

Контрактный тест – это автоматизированный тест, который проверяет, что:

  • Поставщик API возвращает ответы, соответствующие описанному контракту.
  • Потребитель корректно формирует запросы, ожидая определённый формат ответа.

Основные преимущества:

  1. Раннее обнаружение несовместимостей между сервисами.
  2. Сокращение количества интеграционных тестов.
  3. Упрощение процесса CI/CD.

Подготовка к сдаче тестов

Выбор инструмента

Существует несколько популярных решений:

  • Pact – для микросервисов, поддерживает Java, JavaScript, Ruby, Go и др.
  • Spring Cloud Contract – интегрируется с Spring‑Boot.
  • Postman/Newman – удобно для простых HTTP‑контрактов.
  • OpenAPI (Swagger) + Dredd – проверка соответствия спецификации OpenAPI.

Описание контракта

Контракт обычно описывается в одном из форматов:

  • JSON‑Schema
  • YAML (OpenAPI)
  • Pact DSL (Domain Specific Language)

Важно, чтобы контракт был однозначным и полным – включал все обязательные поля, типы данных, диапазоны значений и возможные коды ошибок.

Настройка окружения

Для успешного прохождения тестов подготовьте:

  1. Локальный или тестовый сервер поставщика, где реализованы все эндпоинты.
  2. Тестовые данные (fixtures) – набор запросов и ожидаемых ответов.
  3. CI‑pipeline (GitHub Actions, GitLab CI, Jenkins) с шагом «Run contract tests».

Пошаговый процесс сдачи тестов

Сбор требований

Сначала уточните у заказчика (или команды разработки) какие именно API‑контракты необходимо покрыть. Запишите:

  • URL и HTTP‑метод.
  • Структуру запроса (заголовки, тело).
  • Ожидаемый ответ (статус‑код, тело, заголовки).

Создание контракта

Пример на Pact (JavaScript):

const { pactWith } = require('jest-pact');
pactWith({ consumer: 'MyApp', provider: 'UserService' }, provider => {
 describe('User API',  => {
 beforeEach( => provider.addInteraction({
 state: 'user exists',
 uponReceiving: 'a request for user data',
 withRequest: {
 method: 'GET',
 path: '/users/123',
 headers: { Accept: 'application/json' }
 },
 willRespondWith: {
 status: 200,
 headers: { 'Content-Type': 'application/json' },
 body: {
 id: 123,
 name: like('John Doe'),
 email: regex('.+@.+\..+', 'john@example.com')
 }
 }
 }));
 // Тест, который отправляет запрос к мок‑серверу
 it('returns user data', async  => {
 const response = await fetch('http://localhost:1234/users/123');
 const data = await response.json;
 expect(data.id).toBe(123);
 });
 });
});

Запуск тестов локально

Перед отправкой в репозиторий убедитесь, что все тесты проходят:

  1. Запустите мок‑сервер (Pact Mock Service).
  2. Выполните npm test или аналогичную команду.
  3. Проверьте, что сгенерированный pact-файл соответствует ожиданиям.

Интеграция в CI/CD

Пример шага в GitHub Actions:

name: Contract Tests
on: [push, pull_request]
jobs:
 contract-test:
 runs-on: ubuntu-latest
 steps:
 ⎯ uses: actions/checkout@v3
 ⸺ name: Set up Node
 uses: actions/setup-node@v3
 with:
 node-version: '20'
 ⎯ name: Install dependencies
 run: npm ci
 ⎯ name: Run Pact contract tests
 run: npm run test:contract
 ⎯ name: Publish pact to broker
 if: success
 run: npx pact-broker publish ./pacts --consumer-app-version ${{ github.sha }}

Валидация со стороны поставщика

После того как потребитель опубликовал контракт в Pact Broker (или аналог), поставщик должен выполнить verification:

  1. Скачать контракт из брокера.
  2. Запустить тесты валидации против реального сервера поставщика.
  3. Если проверка не прошла – исправить реализацию API.

Частые ошибки и как их избежать

  • Неполный контракт. Оставьте только «happy path» – тесты упадут, когда появятся новые поля.
  • Жёстко зашитые данные. Используйте генераторы (like, eachLike, term) вместо фиксированных значений.
  • Отсутствие версии контракта. Присваивайте каждому контракту семантическую версию (1.0.0).
  • Тесты работают только локально. Настройте CI, иначе команда не увидит падения.
  • Неправильный порядок публикации. Сначала публикуйте контракт, потом проверяйте поставщика.

Лучшие практики

  1. Контракт как код. Храните файлы .pact в репозитории рядом с тестами.
  2. Автоматическая публикация. При каждом успешном запуске CI публикуйте контракт в брокер.
  3. Версионирование. При изменении API создавайте новую версию контракта, а не перезаписывайте старую.
  4. Обратная совместимость. При добавлении новых полей делайте их опциональными, чтобы старые потребители не ломались.
  5. Документирование. Генерируйте README из контракта (pact‑doc, swagger‑ui) – это упрощает onboarding.

Пример полного рабочего цикла

Ниже схематично показан процесс от написания контракта до выпуска в продакшн:

Потребитель пишет контракт → commit → CI → публикация в Pact Broker
Поставщик получает уведомление (webhook) → скачивает контракт → запускает verification
Если verification прошёл → мерджит изменения → деплой новой версии API
Потребитель в следующем CI‑проекте снова проверяет, что его тесты проходят против новой версии

Сдача тестов на контракт – это не просто набор проверок, а целая культура взаимодействия между командами. Следуя описанному выше алгоритму, вы сможете:

  • Сократить время на поиск интеграционных багов.
  • Повысить доверие к микросервисной архитектуре.
  • Автоматизировать процесс выпуска новых версий без риска поломать чужие сервисы.

Помните, что ключ к успеху – это чётко описанный контракт, автоматизированные проверки и постоянная коммуникация между поставщиком и потребителем.


Дата публикации: