Outry и OpenAPI
Если у вас уже есть спецификация OpenAPI, может возникнуть вопрос, что добавляет Outry. Они отвечают на разные вопросы:
- OpenAPI — что API обещает? Контракт: эндпоинты, параметры, схемы. Из него строятся Swagger UI, сгенерированные клиенты, настройки шлюзов.
- Outry — выполняет ли работающий сервис это обещание и подходят ли наши запросы к коду? Запросы, которые действительно отправляются, с настоящими данными, в том порядке, в каком их отправил бы пользователь, и проверяются в каждом pull request.
Чего не умеет спецификация
Заголовок раздела «Чего не умеет спецификация»OpenAPI-файл — это описание. Он не залогинится, не создаст пользователя, не оформит и не оплатит заказ и не
проверит сумму. Он может сказать, что поле — string, но не может сказать, что после оплаты status
становится "paid" в течение десяти секунд.
flow Checkout { user = CreateUser(name: "Bob Stone") order = CreateOrder(user_id: user.body.id, qty: 3) PayOrder(id: order.body.id) paid = WaitUntilPaid(id: order.body.id)
expect { paid.body.total == 45.5 }}WaitUntilPaid: GET /v1/orders/{id} { poll body.status == "paid" every 1s for 10s}Каждый шаг — запрос из другого файла, вызванный как функция; Login() внутри них выполняется один раз за
запуск и переиспользуется. Обычно это живёт в коллекции Postman или в отдельных тестах — рядом со
спецификацией и в расхождении с ней.
Расхождение: кто заметит, что код изменился
Заголовок раздела «Расхождение: кто заметит, что код изменился»Спецификацию пишут руками или генерируют из аннотаций в комментариях. В обоих случаях ничто не мешает обработчику измениться, а спецификации остаться прежней: переименованное поле, новый обязательный параметр, ещё один middleware. Первыми об этом узнают клиенты.
Outry читает сам код на Go — роуты, структуру, в которую читается тело, query-параметры, заголовки,
middleware, тип ответа — без аннотаций. Каждый запрос .outry сравнивается со своим обработчиком, и CI
падает на конкретной строке:
$ outry checkapi/v1/users/post.outry:17:8: error: required field `full_name` (string) is missing from body ← internal/api/users.go:13Подробнее — в Импорте роутов из Go.
Сравнение
Заголовок раздела «Сравнение»| OpenAPI | Outry | |
|---|---|---|
| Назначение | Описать контракт | Запустить и проверить API |
| Отправляет запросы | Нет (только «Try it out» в Swagger UI) | Да: CLI, приложение, редакторы, CI |
| Проверяет значения и коды ответа | Нет | expect { … } |
| Сценарии из нескольких запросов | Нет | Запросы вызывают друг друга, flow, poll |
| Окружения и секреты | Только servers |
env.toml, системное хранилище паролей, OUTRY_* в CI |
| Совпадает с кодом на Go | Если кто-то обновил | outry check сравнивает с обработчиками |
| Генерация клиентов, Swagger UI | Да | Нет |
Outry не заменяет спецификацию — оставьте её для публичного контракта, документации и генерации клиентов. Outry нужен для того, чего спецификация не умеет: отправлять запросы, собирать из них сценарии и ловить расхождения с кодом в CI.
Если для тел ответов есть JSON Schema, Outry проверяет ответы по ним напрямую:
shape Order = schema("./schemas/order.json")Импорт из OpenAPI в файлы .outry запланирован.