Вызовы запросов и проверки
expect — проверка ответа
Заголовок раздела «expect — проверка ответа»CreateUser: POST /users { body { name: "Viktor" }
expect { status == 201 body.name == "Viktor" body.id matches /^u_\d+$/ headers.content-type.contains("json") duration < 500 body matches { id: string, name: string, tags?: [string] } }}По проверке на строку; каждая должна быть истинной. Выполняются все проверки, даже после упавшей, и у упавшей видно, почему:
✗ api/users/create.outry CreateUser POST http://localhost:8080/users 201 Created 9ms 211B ✓ status == 201 ✗ body.name == "Viktor" — body.name is "viktor" ✗ body matches { id: string, name: string, tags?: [string] } — body.id: expected string, got 42Сравнение не приводит типы ("1" != 1), отсутствующее поле — это null, а не ошибка, а matches
принимает регулярное выражение, форму прямо в файле, именованную форму
или файл JSON Schema. Все операторы и методы — в разделе Выражения.
Вызов другого запроса
Заголовок раздела «Вызов другого запроса»Запрос — это функция: вызовите его по имени, результат — его ответ.
Login: POST /auth/login { params { email: "dev@example.com" password }
body { email, password } expect { status == 200 }}Me: GET /me { headers { Authorization: "Bearer ${Login().body.token}" } expect { status == 200 }}outry run api/users/me.outry # сам сначала залогинится✓ api/users/me.outry Me GET http://localhost:8080/me 200 OK 8ms 96B ↳ Login 200 31ms ✓ status == 200-
Не нужно следить за порядком.
Meработает сам по себе — он вызываетLogin, когда нужен токен. -
Один раз за прогон. Десять запросов с
Login()логинятся один раз, остальные берут тот же ответ (↳ Login cached).fresh Login()всегда отправляет заново.cache: 30mуLoginхранит его ответ и между запусками. -
Аргументы заполняют
paramsи параметры пути{…}вызываемого:GetUser(id: 7),Login(email: "admin@example.com"). -
Ошибки поднимаются наверх. Если у
Loginупалexpect, падает иMe— с цепочкой:✗ api/users/me.outry MeMe → Login: status == 200 — status is 401 -
Cookies из
Set-Cookieхранятся весь прогон, как в браузере.
Имена запросов уникальны в проекте; если Create есть в двух папках, вызывайте users.Create().
outry check сообщает о неизвестных именах, неверных аргументах и циклах вызовов.
flow — сценарий
Заголовок раздела «flow — сценарий»// Checkoutflow Checkout { user = CreateUser(name: "Bob") order = CreateOrder(customer: user.body.id) Pay(order: order.body.id) expect { GetOrder(id: order.body.id).body.status == "paid" }}Шаги выполняются сверху вниз, сценарий останавливается на первом упавшем. В приложении сценарий
показывает trace всех вызванных запросов. Запуск по имени: outry run Checkout.
save — сохранить значение
Заголовок раздела «save — сохранить значение»save order_id = body.idСохранённое значение — переменная для следующих запросов прогона и запоминается между запусками, для
каждого проекта и окружения: после одного outry run CreateOrder запрос GetOrder и сам по себе знает
order_id. Значения хранятся вне репозитория, см. Сохранённые значения.
Для токенов и подобного лучше вызовы: они не зависят от того, что запускалось раньше.
Коды выхода
Заголовок раздела «Коды выхода»outry run завершается с кодом:
0— все запросы отправлены, все проверки и сохранения прошли;1— хотя бы один запрос упал (проверка, сохранение, сетевая ошибка, нет переменной);2— Outry не смог запуститься: неверные аргументы, неизвестное окружение, сломанныйenv.toml.
С --fail-fast прогон останавливается на первом упавшем запросе.