Контрактное тестирование API – визуальное руководство |
10.07.2025 00:00 | ||||||||||||||||||||
Автор: Питер Томас (Peter Thomas) В последнее время интерес к контрактному тестированию растет – появляется все больше и больше инструментов, постов и статей. Но мне всегда казалось, что этот термин несколько недопонят. Такие термины, как «контрактное тестирование, управляемое потребителем», могут сбить с толку новичков тест-автоматизации. К тому же многие материалы, продвигающие контрактное тестирование, упускают ряд важных деталей. Эта статья нацелена на то, чтобы помочь командам понимать и обсуждать ключевые концепции – а также прояснить, что же это такое, и чем оно не является. Мой опыт говорит мне, что контрактное тестирование – это довольно трудно, и оно требует очень хорошей дисциплины в команде и компании. Команды не должны хвататься за него, не добившись определенного уровня зрелости. Иерархия потребностейОдно из заблуждений, касающихся контрактного тестирования, заключается в том, что это единственное необходимое вам тестирование. Все ровным счетом наоборот – это одна из последних стадий, которую я бы прицепил к стратегии тест-автоматизации! Эта диаграмма объяснит, почему. По сути на это может опираться любая команда, занимающаяся тестированием API, если ей нужно оценить здоровье тест-автоматизации. Вы вообще проверяете, что значения данных, возвращаемые сервером, соответствуют ожиданиям? Если нет – все бросьте и сделайте с этим что-нибудь! Порядок и приоритет различных уровней, конечно, могут отличаться у разных команд – скажем, можно поспорить, не стоит ли отправить негативные тесты пониже, сделать их фундаментальнее. Несмотря на это, суть тут вот в чем – контрактным тестированием стоит заниматься, только если у вас есть хорошая база. Для многих команд это означает, что вначале надо разобраться с тестированием производительности и безопасности, и только потом воспарять к более высоким целям. Нужны ли вам вообще имитаторы?Для начала признаю, что в зависимости от респондентов есть разница между терминами «заглушка» и «имитатор», но я буду здесь и далее использовать термины «имитатор» и «тест-дублёр» или просто дублёр. Очевидно, что имитаторы вам не нужны, если вы не зависите от каких-то внешних сервисов. Имитаторы, скорее всего, не нужны, если сервисы, от которых вы зависите:
Классическая ситуация нужды в имитаторах – это зависимость от API или сервиса, который принадлежит другой команде, а в экстремальных случаях выходит за рамки вашей компании. Имитаторы необходимы, если сервис нельзя развернуть на тест-стенде, или он настолько ненадежен, что только мешает вам жить. Отсутствие достаточно стабильного для тестирования производительности тест-окружения – это распространенная проблема. Другой граничный случай – вы зависите от сервиса, разработка которого идет одновременно с вашим, и у вас только два варианта – или ждать появления и деплоя новой версии, или использовать какой-то имитатор. Определение контрактного тестированияПрежде чем ударяться в детали, попробую описать контрактное тестирование в двух предложениях:
Ключевой термин тут – поведение. Тут множество дискуссий, с которыми я сталкивался, скатываются в допущения и серые области. Итак, что же мы конкретно имеем в виду под «ведет себя не так»? В идеальном мире имитатор будет вести себя в точности так же, как и «оригинал». Это предполагает, что вам нужно приложить усилия, эквивалентные усилиям команды, которая разрабатывала реальный сервис. Очевидно, что это непрактично. Поэтому в реальности вам надо срезать углы. Имитатор всегда будет неточной версией реального сервиса. Срезаем углыВот в чем разница между неточным и точным имитатором.
Суть в том, что вам нужно определиться, какой уровень точности нужен вашему имитатору. На самом низком уровне вы получите «тупой» имитатор, который может возвращать только жестко закодированные ответы вне зависимости от сути запросов. Или же можно потратить время на крайне умный имитатор, способный справляться со всеми граничными случаями и бизнес-правилами, встроенными в реальный сервис. Тут нужен компромисс. Как правило, безопасность – это сквозная функциональность, часть архитектуры и деплоя. Этот уголок можно срезать. Иными словами, в имитатор не надо встраивать нечто вроде авторизационного фильтра HTTP-запросов. Мы, однако, не совсем уж игнорируем безопасность – это можно покрыть контрактными или интеграционными end-to-end тестами, и позднее мы к этому вернемся. То, может ли имитатор работать с параллельными запросами, обычно зависит от выбранной для него технологии или способа реализации. Если ваш имитатор не справляется с параллельными запросами, то это просто означает, что вы не можете параллельно запускать ваши тесты. Если у реального поставщика сервиса нет тест-окружения для проверки производительности, это серьезно ограничит ваши возможности в плане нагрузочного тестирования. Это оставляет нам важный аспект Состояний – а также Валидации содержимого. Состояния правят миромЯ считаю состояния «концом света» - именно тут, конечно, кроется большинство проблем и граничных случаев, в нашем-то безжалостном мире распределенных систем и микросервисов. Можно поспорить, что имитатор, не умеющий работать с состояниями, не очень-то полезен. Этот аргумент только усилится, если вы согласитесь, что многие команды, практикующие разработку на основе первичного определения контракта, или генерирующие код на основании какой-либо схемы, без проблем управятся с валидацией содержимого или соответствия схеме – она встроена в их код. То же верно для большинства фреймворков, при помощи автоматической магии превращающих аннотации или объекты домена в JSON или XML/ Ранее я заявил, что точность имитатора – это компромиссное решение. Оценивая фреймворк для создания имитатора API (или тест-двойника), очень важно спросить:
Итак, в чем же заключается тот компромисс, о котором я все время твержу? Как я рад, что вы спросили! Представьте вот чтоПредставьте, что вы работаете в команде, разрабатывающей синий (потребительский) сервис, и вы зависите от сервиса поставщика. Одна из ваших целей – возможность протестировать Потребителя, не нуждаясь в полноценной работоспособности Провайдера. Единственный способ сделать это – создать имитатор. Но подвох тут в том, что это должен быть имитатор высокой точности. Помните, у вас две основных задачи:
Я считаю, что контрактный тест должен суметь валидировать любое поведение Поставщика, включая сложные сценарии, зависящие от состояния (или предыдущих запросов). Конечно, любой API поставщика, который вы не вызываете, не рассматривается. Но я хочу подчеркнуть, что если вы концентрируетесь только на валидации схемы, ваш контрактный тест будет не очень-то полезен, и мы сейчас разберем, почему. Контрактные тесты – это функциональные тесты?Перефразирую вышесказанное – ваш контрактный тест должен быть настоящим функциональным тестом поставщика и не срезать никакие углы. На самом деле ему может даже понадобиться покрыть такие аспекты, как безопасность и авторизационные сценарии, которые я выше назвал «не нужными» имитатору. И тут-то и кроется проблема инструментов и фреймворков контрактного тестирования, подталкивающих вас НЕ писать настоящие функциональные тесты, приступая к контрактным. Я считаю это дезертирством. У вашего контрактного теста есть еще одна важная роль – убедиться, что имитатор симулирует поставщика максимально тщательно. Что тут имеется в виду? Краткий ответ: до такой степени, чтобы суметь заменить поставщика в интеграционном тесте – последней строчке диаграммы. Это – ключевой момент. Если ваш имитатор недостаточно хорош для тестирования всех граничных случаев, вы всегда будете критически зависимы от реального сервиса. Это понижает вашу производительность. А также вашу уверенность. Частота запуска набора контрактных тестов реального сервиса зависит от частоты ожидаемых изменений у поставщика. Если ваш контрактный тест прошел, он всеобъемлющ, и ваш имитатор способен пройти этот тест – вы достигли вершины зрелости автоматизации API-тестирования! Теперь можно просто использовать имитатор – поставщик вам не нужен. В некоторых случаях это может длиться неделями. Добро пожаловать в неидеальный мирЕще одно, финальное замечание – конечно, создать «идеальный имитатор» может быть непростой задачей, и начать можно с имитатора «низкой точности» (третья строчка диаграммы). Это значит, что если вы действительно хотите прогнать свои интеграционные тесты, то можете это сделать – но вам придется «исключить» некоторые тесты, зависящие от сложных граничных случаев или состояний, не поддерживаемых имитатором. ЗаключениеНадеюсь, статья поможет вам определиться, подходит ли вам контрактное тестирование, и послужит полезным руководством при оценке продавца инструментов или фреймворка. Вы должны четко представлять, чего ожидать от имитатора или тест-дублера – и почему имитаторы API должны иметь максимально высокую точность. |