Разделы портала

Онлайн-тренинги

.
Контрактное тестирование API – визуальное руководство
10.07.2025 00:00

Автор: Питер Томас (Peter Thomas)
Оригинал статьи
Перевод: Ольга Алифанова


В последнее время интерес к контрактному тестированию растет – появляется все больше и больше инструментов, постов и статей. Но мне всегда казалось, что этот термин несколько недопонят. Такие термины, как «контрактное тестирование, управляемое потребителем», могут сбить с толку новичков тест-автоматизации. К тому же многие материалы, продвигающие контрактное тестирование, упускают ряд важных деталей. Эта статья нацелена на то, чтобы помочь командам понимать и обсуждать ключевые концепции – а также прояснить, что же это такое, и чем оно не является.

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


Иерархия потребностей

Одно из заблуждений, касающихся контрактного тестирования, заключается в том, что это единственное необходимое вам тестирование. Все ровным счетом наоборот – это одна из последних стадий, которую я бы прицепил к стратегии тест-автоматизации! Эта диаграмма объяснит, почему.


По сути на это может опираться любая команда, занимающаяся тестированием API, если ей нужно оценить здоровье тест-автоматизации. Вы вообще проверяете, что значения данных, возвращаемые сервером, соответствуют ожиданиям? Если нет – все бросьте и сделайте с этим что-нибудь!

Порядок и приоритет различных уровней, конечно, могут отличаться у разных команд – скажем, можно поспорить, не стоит ли отправить негативные тесты пониже, сделать их фундаментальнее.

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

Нужны ли вам вообще имитаторы?

Для начала признаю, что в зависимости от респондентов есть разница между терминами «заглушка» и «имитатор», но я буду здесь и далее использовать термины «имитатор» и «тест-дублёр» или просто дублёр.

Очевидно, что имитаторы вам не нужны, если вы не зависите от каких-то внешних сервисов. Имитаторы, скорее всего, не нужны, если сервисы, от которых вы зависите:

  • Целиком вам принадлежат,
  • Никогда не меняются,
  • Имеют легко доступные тест-окружения.

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

Имитаторы необходимы, если сервис нельзя развернуть на тест-стенде, или он настолько ненадежен, что только мешает вам жить. Отсутствие достаточно стабильного для тестирования производительности тест-окружения – это распространенная проблема. Другой граничный случай – вы зависите от сервиса, разработка которого идет одновременно с вашим, и у вас только два варианта – или ждать появления и деплоя новой версии, или использовать какой-то имитатор.

Определение контрактного тестирования

Прежде чем ударяться в детали, попробую описать контрактное тестирование в двух предложениях:

  • Контрактные тесты должны сообщать вам, если API, от которого вы зависите, ведет себя не так, как ожидалось;
  • Контрактные тесты должны сообщать вам, если тест-двойник этого API не может симулировать все необходимые поведения.

Ключевой термин тут – поведение. Тут множество дискуссий, с которыми я сталкивался, скатываются в допущения и серые области. Итак, что же мы конкретно имеем в виду под «ведет себя не так»?

В идеальном мире имитатор будет вести себя в точности так же, как и «оригинал». Это предполагает, что вам нужно приложить усилия, эквивалентные усилиям команды, которая разрабатывала реальный сервис.

Очевидно, что это непрактично. Поэтому в реальности вам надо срезать углы. Имитатор всегда будет неточной версией реального сервиса.

Срезаем углы

Вот в чем разница между неточным и точным имитатором.

Неточный имитатор

Имитатор средней/высокой точности

Реальный сервис

Безопасность

Не поддерживается

Как правило, не поддерживается, но если приложить усилия, можно закодировать ряд сценариев

Имеет дело с авторизацией и аутентификацией

Производительность

Не поддерживает параллельные запросы

Поддерживает параллельные запросы

Поддерживает параллельные запросы

Валидация содержимого запроса

Ограниченная валидация схемы (или отсутствует)

Валидацию схемы и бизнес-логики можно заложить, приложив дополнительные усилия

Схема и бизнес-логика на месте

Состояния

Не поддерживаются, всегда возвращаются шаблонные ответы

Использует структуру данных в памяти для управления предыдущими запросами или их поиска. Может выявить дубликаты и возвращать ошибки.

Использует хранилище длительного хранения данных

Суть в том, что вам нужно определиться, какой уровень точности нужен вашему имитатору. На самом низком уровне вы получите «тупой» имитатор, который может возвращать только жестко закодированные ответы вне зависимости от сути запросов.

Или же можно потратить время на крайне умный имитатор, способный справляться со всеми граничными случаями и бизнес-правилами, встроенными в реальный сервис. Тут нужен компромисс.

Как правило, безопасность – это сквозная функциональность, часть архитектуры и деплоя. Этот уголок можно срезать. Иными словами, в имитатор не надо встраивать нечто вроде авторизационного фильтра HTTP-запросов. Мы, однако, не совсем уж игнорируем безопасность – это можно покрыть контрактными или интеграционными end-to-end тестами, и позднее мы к этому вернемся.

То, может ли имитатор работать с параллельными запросами, обычно зависит от выбранной для него технологии или способа реализации. Если ваш имитатор не справляется с параллельными запросами, то это просто означает, что вы не можете параллельно запускать ваши тесты. Если у реального поставщика сервиса нет тест-окружения для проверки производительности, это серьезно ограничит ваши возможности в плане нагрузочного тестирования.

Это оставляет нам важный аспект Состояний – а также Валидации содержимого.

Состояния правят миром

Я считаю состояния «концом света» - именно тут, конечно, кроется большинство проблем и граничных случаев, в нашем-то безжалостном мире распределенных систем и микросервисов. Можно поспорить, что имитатор, не умеющий работать с состояниями, не очень-то полезен. Этот аргумент только усилится, если вы согласитесь, что многие команды, практикующие разработку на основе первичного определения контракта, или генерирующие код на основании какой-либо схемы, без проблем управятся с валидацией содержимого или соответствия схеме – она встроена в их код. То же верно для большинства фреймворков, при помощи автоматической магии превращающих аннотации или объекты домена в JSON или XML/

Ранее я заявил, что точность имитатора – это компромиссное решение. Оценивая фреймворк для создания имитатора API (или тест-двойника), очень важно спросить:

  • Насколько легко имитировать ответ API?
  • Насколько легко применить состояние для формулировки ответа?

Итак, в чем же заключается тот компромисс, о котором я все время твержу? Как я рад, что вы спросили!

Представьте вот что

Представьте, что вы работаете в команде, разрабатывающей синий (потребительский) сервис, и вы зависите от сервиса поставщика. Одна из ваших целей – возможность протестировать Потребителя, не нуждаясь в полноценной работоспособности Провайдера. Единственный способ сделать это – создать имитатор. Но подвох тут в том, что это должен быть имитатор высокой точности.

Помните, у вас две основных задачи:

  1. Убедиться, что Поставщик ведет себя так, как вы ожидаете. Это первый пункт определения контрактного тестирования, который я привел выше. Это представлено на второй строчке диаграммы ниже. У вас уже будут интеграционные тесты (IT) – но помимо них вам понадобится отдельный набор тестов – контрактные тесты (СТ).
  2. Получить возможность проводить разработку и интеграционное тестирование, не нуждаясь в полноценной работоспособности Поставщика. Это отражено на последней «строчке» диаграммы.


Я считаю, что контрактный тест должен суметь валидировать любое поведение Поставщика, включая сложные сценарии, зависящие от состояния (или предыдущих запросов). Конечно, любой API поставщика, который вы не вызываете, не рассматривается. Но я хочу подчеркнуть, что если вы концентрируетесь только на валидации схемы, ваш контрактный тест будет не очень-то полезен, и мы сейчас разберем, почему.

Контрактные тесты – это функциональные тесты?

Перефразирую вышесказанное – ваш контрактный тест должен быть настоящим функциональным тестом поставщика и не срезать никакие углы. На самом деле ему может даже понадобиться покрыть такие аспекты, как безопасность и авторизационные сценарии, которые я выше назвал «не нужными» имитатору. И тут-то и кроется проблема инструментов и фреймворков контрактного тестирования, подталкивающих вас НЕ писать настоящие функциональные тесты, приступая к контрактным. Я считаю это дезертирством.

У вашего контрактного теста есть еще одна важная роль – убедиться, что имитатор симулирует поставщика максимально тщательно. Что тут имеется в виду?

Краткий ответ: до такой степени, чтобы суметь заменить поставщика в интеграционном тесте – последней строчке диаграммы. Это – ключевой момент. Если ваш имитатор недостаточно хорош для тестирования всех граничных случаев, вы всегда будете критически зависимы от реального сервиса. Это понижает вашу производительность. А также вашу уверенность.

Частота запуска набора контрактных тестов реального сервиса зависит от частоты ожидаемых изменений у поставщика. Если ваш контрактный тест прошел, он всеобъемлющ, и ваш имитатор способен пройти этот тест – вы достигли вершины зрелости автоматизации API-тестирования! Теперь можно просто использовать имитатор – поставщик вам не нужен. В некоторых случаях это может длиться неделями.

Добро пожаловать в неидеальный мир

Еще одно, финальное замечание – конечно, создать «идеальный имитатор» может быть непростой задачей, и начать можно с имитатора «низкой точности» (третья строчка диаграммы). Это значит, что если вы действительно хотите прогнать свои интеграционные тесты, то можете это сделать – но вам придется «исключить» некоторые тесты, зависящие от сложных граничных случаев или состояний, не поддерживаемых имитатором.

Заключение

Надеюсь, статья поможет вам определиться, подходит ли вам контрактное тестирование, и послужит полезным руководством при оценке продавца инструментов или фреймворка. Вы должны четко представлять, чего ожидать от имитатора или тест-дублера – и почему имитаторы API должны иметь максимально высокую точность.

Обсудить в форуме