API-, интеграционное и E2E-тестирование
latest update of the page: 31-10-2024, 18:18 UTC
Какая интеграция вообще бывает?
Предположим, что мы знаем, что интеграция между приложениями в общем случае может происходить:
-
прямыми вызовами API "точка-точка" по шаблону request-reply (запрос-ответ) или one-way (отправка в одну сторону).
Обычно реализуется посредством REST API или RPC-взаимодействия.
-
обменом через слой среднего уровня, например через системы управления очередями (message brokers) типа RabbitMQ и Apache Kafka
или при посредстве КСШ (ESB) (которая, по-сути тоже является собой совокупность тех же message brokers)
-
обменом файлами, складываемыми/читаемыми в условленном "месте".
Таким местом может быть как некий общий локальный storage, так и удалённый, (от)куда файлы читаются/передаются по протколам FTP, SSH et cetera.
-
на уровне баз данных:
- одна общая БД для нескольких систем (привет монолитам и всяческому легаси)
- баз несколько, но связанных процессами ETL/ELT
Тестирование API
Тестирование API (API testing) = процесс тестирования приложения (сервиса) с целью проверки того, что реализация его внешних интерфейсов соответствует установленным требованиям.
Обычно включает в себя тестирование
- WADL/WSDL SOAP API (XML)
-
HTTP REST API, сиречь HTTP-request вида:
- POST host:9090/entity с body, содержащим text/json/xml
- GET host:9090/entity/1
- PUT host:9090/entity/1 с body, содержащим text/json/xml
-
HTTP non-REST API. Например, запросы с использованием GraphQL или банально HTTP-запросы вида:
- POST host:9090/CreateEntity с body, содержащим text/json/xml
- GET host:9090/GetEntity?id=1
- POST host:9090/UpdateEntity с body, содержащим text/json/xml
- RPC-взаимодействия с сервером, например, в виде java-call клиентской библиотеки, см. также gRPC
-
Тестирование т.н. контрактов (CDC — consumer driven contract) для всех вышеуказанных разновидностей API в виде:
- Тестов клиентов сервисов-поставщиков. Обычное используется заглушка, которая автоматически формируется из контракта. Это позволяет избежать развёртывания окружения в виде Сервисов-Поставщиков.
- Тестов для API сервисов-поставщиков. Они также могут генерироваться из контракта.
-
Тестирование обратной совместимости API.
Что мы можем проверить в API
Проверки, связанные с логикой API-методов как таковых:
- Ответ получен
- Время ответа укладывается в SLA (нефункциональное)
- Код ответа соответствует контракту API и варианту запроса (позитивные сценарии + негативные сценарии)
- Тело ответа в наличии, если предусмотрено контрактом API
Проверки данных, независимо от бизнес-логики:
-
(позитивное) отправили только обязательный набор полей согласно контракту API с корректной аутентификацией+авторизацией,
набор данных в ответа соответствует схеме данных в контракте API и варианты запроса: состав полей, их вложенность, типы значений.
-
(позитивное, вариативность) отправили обязательный и опциональный набор полей согласно контракту API с корректной аутентификацией+авторизация,
набор данных в ответа соответствует схеме данных в контракте API и варианты запроса: состав полей, их вложенность, типы значений.
-
(негативное, вариативность) отправили обязательный и опциональный набор полей согласно контракту API, НО с некорректной аутентификацией/авторизацией,
код и тело ответа соответствуют некорректности запроса. Например, в случае с HTTP web-API это могут быть ошибки 4XX, если ошибки 5XX — это уже повод насторожиться.
-
(негативное, вариативность) отправили набор полей, который не соответствует контракту (лишние поля / нет обязательных / мусорные данные / типы данных несоответствую контракту и т.д.) с корректной аутентификацией+авторизацией,
код и тело ответа соответствуют некорректности запроса. Например, в случае с HTTP web-API это могут быть ошибки 4XX, если ошибки 5XX — это уже повод насторожиться.
Проверки, связанные с бизнес-логикой, за которую отвечает API-метод:
- Данные пришли именно те, которые мы запрашивали. Например, если мы запрашивали данные клиента N, то должны прийти данные именно этого клиента.
- Бизнес-осмысленность данных. Например, дата не просто дата, а в определённом диапазоне, или ИНН, который должен соответствовать формату и "внутренней логике" номера.
- Если в качестве реации на запрос, должна быть произведена запись в БД, создан экземпляр какой-либо бизнес-сущности в этой или связанной системе, то следует проверить факт и корректность записи, хотя это уже движение в сторону интеграционного тестирования.
Инструменты для тестирования web-API
Postman
GUI-инструмент для тестирования REST/SOAP. Поддерживает создание скриптов для автотестов (Javascript).
SoapUI
GUI-инструмент для тестирования REST/SOAP. Поддерживает создание test-suit'ов со скриптами для автоматизации тестирования (разные ЯП).
curl
CLI-инструмент для для взаимодействия с серверами по протоколам с синтаксисом URL.
Авторизация
# отправить GET-запрос, содержащий заголовок с JWT (JSON Web Token)
curl -H GET https://localhost:8080/some -H "Authorization: <JWT>" -i
# отправить GET-запрос, содержащий имя пользователя user и его пароль pass прямо в командной строке (антисекурно)
curl -u "user:pass" -H GET https://localhost:8080/some -i
# отправить GET-запрос, содержащий имя пользователя user, а пароль curl спросит при отправке, он не будет виден на экране и останется в истории команд консоли
curl -u "user" -H GET https://localhost:8080/some -i
Отправка данных
# отправить POST-запрос с телом запроса из определённого файла и с заголовком, объявляющим, что мы несём JSON
curl -X POST https://localhost:8080/createSomething -H "Content-Type: application/json" -d "@data.json" -i
# отправить POST-запрос с телом запроса, указанном прямо в строке, и с заголовком, объявляющим, что мы несём JSON
curl -X POST https://localhost:8080/createSomething -H "Content-Type: application/json" -d '{"somefield":"somevalue"}' -i
# url encode
curl -X GET "https://1.1.1.1:8080/find" -G --data-urlencode "param=123 abc" -i
Интеграционное тестирование
Интеграционное тестирование (Integration testing) = проверка корректности взаимодействия чего-то с чем-то, в зависимости от контекста:
- проверка взаимодействия модулей (компонентов) кода в рамках одного приложения
- проверка взаимодействия приложения с ОС (операционной системой) или оборудованием
- проверка интеграции между сервисами/системами. В настоящей "статье" мы будем говорить об этом.
Сиречь, "дёргаем"/наблюдаем нечто-1, инициирующее вызовы к нечто-2, проверяем, что взаимодействие происходит согласно имеющимся интеграционным описаниям обоих нечт: одно корректно "спрашивает", другое корректно "отвечает", и наборот, если взаимодействие двустороннее.
Например: отправили в Систему-1 http-методом POST по эндпоинту /someapi/v1/message json с некими данными, в ответ получили 200 OK, через 2 секунды выполнили определённый SELECT SQL-запрос в БД Системы-2, убедились что нужные данные "осели" в таблице в требуемых полях.
E2E-тестирование
Сквозное тестирование (End-To-End / E2E / Chain testing) = проверка некоего полного клиентского сценария, ценной для Клиента функциональности (feature) по всей "цепочке" её исполнения:
от инициирующих действий Клиента (либо клиентского приложения) в CLI / TUI / GUI / API / filesystem / DB -->
--> через взаимосвязанные системы/сервисы нашего Продукта -->
--> до предоставления Клиенту (его приложению) результата в обозначенном требованиями формате и месте.
Например выполнили цепочку действий в UI: регистрация нового пользователя, создание задачи от имени пользователя, дожидание/доведение задачи до конечного статуса, скачивание файла с результатом.
Чуть подробнее здесь.
Пример. Обследование
Изложенное ниже является очень сжатой компиляцией личного опыта, и не номинируется на истину в последней инстанции.
Рассматривается тот участок процесса поставки, когда тестируемые системы/сервисы уже прошли своё "личное" функциональное тестирование, а теперь нам нужно убедиться, что они слаженно работают вместе как единый продукт.
Речь пойдёт о том как подступиться к интеграционному (системному) тестированию совокупности взаимодействующих систем/сервисов,
- которое предполагается автоматизировать
- при этом не используя заглушки (stubs) и моки (mocks), т.е. в максимально "живом и натуральном" окружении.
Обследуем сервисы/системы, составляющие наш условный Продукт, ища и изучая следующие информационные артефакты (список избыточный):
- Сценарии использования (use cases) и БТ (бизнес-требования) по ним
- Архитектура (общая, компонентная, интеграционная)
- Диаграммы последовательности (sequence diagram) интеграционных взаимодействий
- СТ (системные требования) к API, описание/контракты API
- Объектная модель (object model)
- Ролевая модель (role model)
- Диаграмма развёртывания (DD, deployment diagram), руководства/инструкции по установке и администрированию
Изучение их позволит обрести
понимание по каждому сервису/системе:
- список ВОПРОСОВ к команде сервиса/системы
- для чего вообще нужен, какие его самые важные фичи
- входящие интеграционные потоки
- исходящие интеграционные потоки
- как производит аутентификацию запросов
- как происходит авторизация
- какие протоколы где использует (требуются ли сертификаты и ключи)
- какими сущностями оперирует
- какие действия в GUI и/или запросы к API инициируют исходящие запросы в другие сервисы/системы
- для каких ролей эти действия должны быть доступны
- при каких способах развёртывания и каких именно настройках интеграция будет идти тем или иным образом
Это понимание И полученные ответы на ваши уточняющие вопросы должны позволить приступить к
разработке тестовых сценариев:
- определить необходимые предусловия (какая учётная запись с какими правами нужна для каких действий, экземпляры каких сущностей должны быть созданы в этой и смежных системах, какая д.б. конфигурация у сервиса/системы)
- составлять корректные шаги
- приоритизировать сценарии по уровню критичности проверяемой функциональности
Абстрактный пример обследуемой архитектуры
Предположим, мы имеем некий Продукт, состоящий из Системы А, Системы Б, Системы В. Продукт предоставляет Клиенту некое публичное API, в которое клиентское приложение постоянно пишет некие данные. Продукт также предоставляет Клиенту web-UI. Основным юзкейсом нашего Продукта является приём данных от Клиента, обработка их каким-то образом и предоставление в некотором человекочитаемом виде в web-UI. Также наш Продукт для каких-то внутренних потребностей собирает какие-то данные со своих Систем.
Для упрощения опустим интеграцию с системами аутентификации и авторизации.
скачать схему в формате diagrams.net (бывший draw.io)
В этом случае с точки зрения API / integration / E2E тестирования нас будут интересовать следующие элементы архитектуры:
- API 4 шт.
- Message broker 1 шт.
- Интеграционные потоки 4 шт.
Какие же сценарии?
Интеграционные тестовые сценарии можно поделить, например, на следующие группы (по возрастанию сложности):
-
Auth.
Тестовые сценарии на проверку возможности аутентификации и/или авторизации запросов к API. mTLS, basic-auth, JWT,... вот это вот всё. Можно совмещать с базовыми проверками ролевой модели, если это возможно сделать запросами к (web-UI) API.
-
API.
- В этой группе проверяем такие методы API, которые НЕ инициируют подзапросов в другие Системы, в противном случае это уже будут integration-тесты.
- Тесты, имеющие целью проверки того, что на запросы к методам API, составленные на основе требований и/или контракта этого API, приходит ответ, соответствующим требованиям/контракту.
-
Тесты, имеющие целью проверки того, что обращения к API позволяют успешно производить CRUD операции наl сущностями, которыми оперирует система-владелец API.
Успешность создания/изменения/удаления сущностей можно проверять как и цепочкой обращений к методам API (при наличии соответствующих), так и запросами к БД, если есть такая возможность.
-
Integration.
Тесты корректности интеграции двух систем. "Дёргаем" (по API / web-UI) первую систему, проверяем, что она корректно "пообщалась" с другой системой.
Порой, такой тест м.б. частным случаем E2E, если в реализации фичи (бизнес-процессе) задействовано всего 2 системы.
-
E2E.
Проверка такого бизнес-процесса (фичи, если угодно) ИТ-Продукта, в процессе выполнения которой задействовано 3 и более системы: система, в которой было совершено инициирующее воздействие (обращение к API, манипуляция в UI), "промежуточные" системы, система, в которой "даются" даные для итогового результата.
Рекомендуется соотношение одна фича = один E2E-тест (базовый положительный случай), потому что E2E — самые долгие и дорогие по автоматизации и поддержке тесты.
Какие же тесты по группам будут для нашего примера
API
скачать схему в формате diagrams.net (бывший draw.io)
Integration
скачать схему в формате diagrams.net (бывший draw.io)
E2E
скачать схему в формате diagrams.net (бывший draw.io)
Для ускорения E2E, или если вам кажется, что пункты 3 и 4 дублируют интеграционные тесты, то эти шаги в кейсе можно опустить, но тогда поиск неизбежных ошибок усложнится, потому что не будет сразу очевидно на каком участке затык. Так что здесь надо взвешивать что вам в вашем конкретном случае важнее.