Что такое контрактные тесты
Что проверяют
Понимаете ли вы, какую дыру закрывают контрактные тесты между быстрыми модульными и дорогими сквозными. Вопрос про распределённые системы: умеете ли вы ловить рассогласование API до продакшена, не поднимая половину сервисов в общем окружении.
Как отвечать
Контрактный тест фиксирует соглашение между потребителем и поставщиком: какой запрос уйдёт и какой ответ ожидается. Дальше стороны проверяются порознь. Потребитель гоняет свои тесты против заглушки, собранной из контракта, поставщик гоняет сгенерированный из того же контракта тест против себя и доказывает, что отвечает как обещал.
Ключевое отличие от интеграционного теста: сервисы никогда не запускаются вместе. Поэтому такие тесты быстрые, стабильные и живут в обычном прогоне сборки, а не в отдельном ночном окружении.
Подход обычно потребительский: контракт рождается из ожиданий потребителя, публикуется в брокере и становится обязательством поставщика. В Java называют Pact с брокером и проверкой готовности к выкладке, а также Spring Cloud Contract, где контракт описан на Groovy или YAML и из него собираются и заглушка для потребителя, и тест для поставщика.
Полезно добавить, что контракт проверяет форму и семантику сообщения, а не бизнес-логику, и что для очередей он работает так же: там фиксируется схема события.
Где спотыкаются
Путают контракт со схемой API. Описание вроде OpenAPI перечисляет всё, что сервис умеет, а контракт только то, чем реально пользуется конкретный потребитель, и потому ломается лишь на значимых изменениях.
Пишут контракт со стороны поставщика и получают декларацию вместо соглашения. Такой тест зелёный всегда: поставщик проверяет сам себя, а ожидания вызывающей стороны в него не попали.
Не встраивают проверку в конвейер выкладки. Без брокера и без ответа на вопрос, совместима ли новая версия с тем, что уже работает в продакшене, контракты превращаются в устаревающие файлы в репозитории.