Шаги тест-кейсов — Low-Code сценарий
Тест-кейсы в Mockarty собираются из шагов. Шаг — это одно действие в
тесте: «открой страницу логина», «отправь POST /auth», «проверь, что пришло
письмо». Эта страница — практическое руководство по сборке шагов в стиле
low-code: кликаем и выбираем вместо того, чтобы писать код, чтобы человек
без опыта программирования собрал end-to-end тест с реальными вызовами API,
переносом значений между шагами, пошаговой отладкой и зелёным/красным
результатом на каждом прогоне.
Об URL в примерах: все примеры используют
localhost:5770как адрес
Mockarty по умолчанию. Если экземпляр работает на удалённом сервере, замените
localhost:5770на его реальный адрес (например,https://mockarty.company.com).
См. Полезные функции и советы.
Связанные страницы: Управление тест-кейсами ·
Runtime-вид прогона ·
Тест-планы ·
Просмотр прогона тест-плана ·
Переопределения ·
Хранилище секретов ·
Руководство по JsonPath
Чтобы запустить кейс внутри тест-плана и увидеть, как он разворачивается
инлайн рядом с другими элементами плана (load, fuzz, chaos, contract,
вложенные планы), смотрите гид
Просмотр прогона тест-плана. Как
{{plan.X}}значения текут между plan-level overrides и case-step
extracts — на странице Переопределения.
1. Что такое шаг — ручной или автоматический
Каждый шаг тест-кейса бывает ручным или автоматическим. Выбор делается
двухсегментным переключателем в шапке каждой строки шага в редакторе.
| Режим | Когда использовать | Что выполняется при прогоне |
|---|---|---|
| Ручной (иконка руки) | Когда тестировщику нужно посмотреть на экран и решить pass/fail — визуальные проверки, реальные устройства, проверка на инциденте. | Никакая автоматика. Прогон ставится на паузу, открывается модал пошагового прогона, тестировщик фиксирует вердикт. |
| Автоматический (иконка робота) | Когда проверку можно выразить HTTP-вызовом (или цепочкой вызовов), чей ответ определяет pass/fail. | Раннер делает запрос, проверяет ожидания и сохраняет результат без участия человека. |
В одном кейсе можно смешивать оба типа. Частый паттерн: автоматика для
инфраструктуры, ручная — для пользовательского результата: залогиниться
через API, получить профиль через API, а потом попросить человека «открой
почтовик и убедись, что письмо пришло».
Чтобы переключить режим, нажмите на иконку руки или робота в шапке шага.
Тело шага перестроится и покажет нужные поля для выбранного режима.
[Строка шага с переключателем режима — screenshot pending]
2. Привязка запроса из API Tester к шагу
В автоматических шагах вся работа происходит внутри API Tester —
встроенного HTTP / gRPC / GraphQL клиента Mockarty. Запрос создаётся и
сохраняется там, а из шага на него выставляется ссылка. Раннер
перечитывает запрос на каждом прогоне, поэтому правки в API Tester мгновенно
применяются ко всем существующим кейсам — никакого копи-пасты и расхождений.
Чтобы привязать запрос:
- Откройте тест-кейс в редакторе (
/ui/test-cases). - Убедитесь, что шаг в режиме Автоматический (активна иконка робота).
- Внутри тела шага нажмите Pick endpoint («Выбрать запрос»).
- Откроется дерево пикера со всеми сохранёнными запросами API Tester по
коллекциям. Введите часть имени, метода или пути — список отфильтруется.
Выберите нужный. - Тело шага свернётся в одну строку-чип:
POST /api/v1/auth — Login. Имя
чипа повторяет имя запроса в API Tester — переименуете там, чип обновится.
[Привязка запроса из API Tester к шагу — screenshot pending]
Чтобы отвязать, нажмите на чип запроса и выберите Clear («Очистить»).
Тело шага вернётся в состояние (none — pick a request).
Что приходит вместе со связанным запросом
Когда кейс выполняет привязанный шаг, Mockarty заново подтягивает запрос из
API Tester (метод, URL, заголовки, тело, ожидания) и запускает его через тот
же движок, что и в API Tester. Ответ сохраняется на прогон шага, чтобы
runtime-вид прогона показал, что именно
вернулось.
3. Привязка окружения к шагу
API Tester группирует хосты, базовые пути, токены и пер-команд значения в
окружения (например, «staging», «production», «regional-eu»). Каждый
шаг может выбрать собственное окружение, чтобы один и тот же логический
тест работал на разных стендах без переписывания запросов.
Привязка окружения у шага состоит из трёх слоёв:
- Окружение — одно именованное окружение из API Tester. Подставляет
значения во все плейсхолдеры{{env.X}}. - Переопределения (Overrides) — список пар key/value на конкретный шаг,
который имеет приоритет над окружением только для этого шага. Полезно,
когда «весь кейс на staging, но именно этот шаг — на staging-eu». - Секреты (Secrets) — указатели на Хранилище секретов
с алиасом на конкретный шаг. Значение секрета подгружается и подставляется
в момент выполнения; оно никогда не попадает в определение кейса.
Чтобы настроить окружение шага:
- В теле автоматического шага нажмите Environment («Окружение»).
- Выберите окружение из выпадающего списка (с поиском по имени). Оставьте
пустым, чтобы наследовать окружение уровня кейса. - Нажмите Add override («Добавить переопределение»), чтобы добавить
строкиkey = value. Каждая строка даёт одно значение{{env.<key>}},
которое перебивает значение из окружения для этого шага. - Нажмите Add secret («Добавить секрет»), чтобы привязать секрет.
Пикер секретов покажет все секреты, к которым у текущего пользователя
есть доступ в этом пространстве имён. Выберите исходный секрет и алиас —
алиас это имя, под которым вы обращаетесь к секрету в шаге
({{secret.<alias>}}), поэтому можно использовать{{secret.API_TOKEN}}
независимо от того, как реально называется секрет (prod_api_tokenили
staging_api_token).
Реалистичный пример: вход в staging-eu с токеном из prod-секретов
Шаг логина, бьющий по окружению staging, но в европейский регион (через
переопределение host), с API-токеном из prod-хранилища секретов:
| Слой | Значение |
|---|---|
| Окружение | Staging (даёт host=https://api.staging.example.com, tenant=acme) |
| Переопределение | host = https://api.staging-eu.example.com |
| Секрет | источник prod_api_token, алиас API_TOKEN |
URL связанного запроса API Tester:
{{env.host}}/v1/auth
с заголовком Authorization: Bearer {{secret.API_TOKEN}}. При выполнении
раннер резолвит URL в https://api.staging-eu.example.com/v1/auth
(переопределение бьёт окружение) и подставляет токен из prod-хранилища.
Значение секрета маскируется в runtime-виде и в аудит-логе — после прогона
оно нигде не видно.
4. Подстановка переменных в шаге
В любом текстовом поле шага — URL, значение заголовка, тело, JSON-путь,
ожидание — можно использовать плейсхолдер вида {{namespace.key}}. Есть
четыре namespace’а:
| Namespace | Источник | Когда заполняется |
|---|---|---|
{{plan.X}} |
Значения, извлечённые предыдущими шагами того же прогона (см. §5). | В момент, когда у предыдущего шага сработало правило извлечения. |
{{override.X}} (неявно) |
Список переопределений шага. | При резолве привязок шага в начале его выполнения. |
{{env.X}} |
Переменные привязанного окружения. | При резолве привязок шага в начале его выполнения. |
{{secret.X}} |
Запись из Хранилища секретов, привязанная к алиасу X. |
В момент сборки запроса — нигде не сохраняется. |
Приоритет — побеждает самое специфичное
Когда одно и то же имя живёт в нескольких namespace’ах, Mockarty берёт
наиболее специфичное значение. Слева направо порядок такой:
plan > override > env > secret
Поэтому в §3 {{env.host}} резолвится в переопределение
https://api.staging-eu.example.com (override бьёт env), а будь у нас
шаг ниже, который записал host в plan.host, он бы перебил уже и override.
В строке шага рядом с ключом, у которого несколько активных источников,
показывается небольшой бейдж conflict, а тултип сообщает, какой
источник победит. Если приоритет не подходит вашему сценарию, самое простое
— переименовать ключ (например, дать переопределению более специфичное имя
host_eu).
5. Извлечение данных из одного шага для следующего
Шаг логина возвращает токен; следующий шаг ему нужен. Извлечения
(Extracts) — это правила, копирующие значения из ответа одного шага в
контекст прогона ({{plan.X}}), чтобы следующие шаги их использовали.
В секции Extract шага можно добавить правило. Четыре типа:
| Тип | Что забирает | Пример |
|---|---|---|
| JSONPath | Значение из JSON-тела ответа. | $.access_token |
| Regex | Группу захвата из заголовка, всего блока заголовков или тела. | Bearer\s+(?P<t>[A-Za-z0-9._-]+) по header.authorization |
| Header | Значение одного заголовка ответа. | X-Request-Id |
| Status | HTTP-статус как число. | (без поля From — просто выберите тип) |
У каждого правила есть поле To — имя под plan., по которому
последующие шаги читают значение. JSONPath-правило с From $.access_token
и To plan.token означает «после успешного шага в {{plan.token}}
лежит access token из тела ответа».
Для regex-правил выпадающий список Source определяет, против чего
запустить паттерн:
- body (по умолчанию) — сырое тело ответа.
- header.<имя> — значение одного заголовка (например,
header.authorization). - header_raw — все заголовки склеены строками
Name: value.
Победителем становится именованная группа захвата t (или, если она не
названа, группа 1).
Реальная цепочка: login → fetch profile
| Шаг | Метод | Extract | Использует следующий шаг |
|---|---|---|---|
| 1. Login | POST /auth |
JSONPath $.access_token → plan.token |
— |
| 2. Fetch profile | GET /me с Authorization: Bearer {{plan.token}} |
JSONPath $.id → plan.userId |
— |
| 3. Audit log query | GET /audit?user={{plan.userId}} |
— | — |
Когда шаг 1 проходит, в plan.token пишется токен. Шаг 2 стартует уже с
подставленным заголовком Authorization. Шаг 2, в свою очередь, пишет
plan.userId, и шаг 3 использует это в query string.
Test on last response
В редакторе извлечений есть кнопка Test on last response («Проверить
на последнем ответе»). После того как шаг хотя бы раз выполнился в
debug-прогоне (см. §8), эта кнопка прогоняет правило по сохранённому
ответу без обращения к серверу, и вы можете итеративно подбирать JSONPath
или regex без повторного вызова API. Кнопка показывает резолвленное
значение рядом с правилом или сообщение об ошибке, если путь не сработал.
Если сохранённый ответ есть только на сервере (например, прогон был на
другой машине), кнопка автоматически делает короткий серверный preview-вызов
с тем же результатом.
5a. Проверки ответа — структурный pass/fail
Extracts извлекают значения для следующего шага; assertions
(проверки) решают, прошёл ли вообще этот шаг. Шаг, который вызвал
POST /auth и получил 503 Service Unavailable, технически — «запрос
завершился»: без проверки диспетчер примет это как PASS и аккуратно
запишет «отравленный» токен в plan.token. Добавление проверки
status == 200 закрывает дыру: шаг падает закрыто, harvester
пропускается, downstream-шаги никогда не увидят плохие данные.
Откройте секцию Проверки (assertions) в шаге, чтобы добавить
правило. Доступны шесть типов:
| Тип | Что проверяет | Операторы |
|---|---|---|
| status | HTTP-статус ответа | = ≠ > ≥ < ≤ |
| header | Заголовок ответа по имени (нечувствительно к регистру) | = ≠ содержит не_содержит regex_match существует не_существует |
| jsonpath | Значение в теле по JSONPath | Все указанные плюс > ≥ < ≤ для числовых значений |
| body_contains | Тело ответа целиком как строка | содержит не_содержит regex_match |
| duration_ms | Время шага в миллисекундах | = ≠ > ≥ < ≤ |
| body_size | Размер тела ответа в байтах | = ≠ > ≥ < ≤ |
Поля каждой проверки:
- Тип (Kind) — что проверять.
- Источник (Source) — обязателен для
header(имя заголовка) и
jsonpath(путь вроде$.user.id). Для остальных четырёх типов
игнорируется. - Оператор (Operator) — операция сравнения. Числовые операторы
работают на числовых leaf-значениях; строковые сравнивают как строки;
regex_matchкомпилирует Expected как регулярку и матчит
фактическое значение. - Ожидаемое (Expected) — значение для сравнения. Для
regex_match
это сам паттерн; дляexists/not_existsполе игнорируется. - Заметка (Note) — необязательный человеко-читаемый комментарий,
который виден в runtime view рядом с упавшей проверкой. Помогает
напомнить почему проверка важна, а не только что она упала.
Когда что использовать
| Хочется проверить, что… | Используйте |
|---|---|
| API ответил успехом | status = 200 (или >= 200 + < 300) |
| В теле пришёл конкретный пользователь | jsonpath $.user.email = ${env.email} |
| Токен по форме похож на JWT | jsonpath $.token regex_match ^eyJ[A-Za-z0-9._-]+$ |
| Был выставлен trace-id заголовок | header X-Request-Id существует |
| В ответ не утёк debug payload | body_contains не_содержит DEBUG_TRACE |
| Эндпоинт уложился в SLA-бюджет | duration_ms < 500 |
| Тело не пустое подозрительно | body_size > 0 |
Прогон на последнем ответе
Редактор проверок повторяет паттерн Extracts: кнопка Прогнать на
последнем ответе позволяет вставить sample payload (или взять
кэшированный с прошлого debug-прогона) и применить все проверки в
браузере. Каждая строка показывает pass или текст упавшего сообщения —
удобно при доводке regex’а / JSONPath’а.
Что происходит в runtime
Проверки выполняются после возврата executor’а и до того, как
harvester что-то пишет в plan-контекст. Поток для каждого шага:
- Executor отправляет запрос, получает ответ.
- Проверки применяются к ответу. ЛЮБАЯ невыполненная проверка → шаг
падает закрыто, с multi-line сообщением, перечисляющим все неудачи. - Harvest выполняется только если шаг прошёл — значит упавшая
проверка никогда не оставит после себяplan.X.
В runtime view упавшие проверки видны inline: у каждого шага с
неудачами появляется красный чип «Проверки» в шапке карточки и
секция «Проверки» в panel’е деталей со списком всех упавших проверок
(тип, оператор, ожидаемое, фактическое, ваша Заметка).
6. Зависимости между шагами
По умолчанию шаги выполняются по порядку: шаг 2 стартует только после
завершения шага 1. Это годится для большинства кейсов, но означает, что
медленный шаг блокирует более быстрые даже там, где между ними нет реальной
зависимости по данным.
Пикер Depends on («Зависит от») — выпадающий список внутри тела шага,
показывающий остальные шаги текущего кейса, — позволяет описать это явно.
Раннер считает dependsOn единственным реальным ограничением порядка:
- Когда вы добавляете совершенно новый шаг, его
dependsOnпредзаполняется
предыдущим шагом (чтобы «по умолчанию последовательно» сохранилось). - Уберите зависимость — и шаг сможет стартовать сразу при старте кейса,
параллельно с соседями. - Добавьте несколько зависимостей, чтобы собрать вход: «этому шагу нужны
и Login, и Seed data». - Расходитесь от одного шага в несколько: «после Login параллельно тянем
профиль, заказы и настройки».
В шапке любого шага, у которого есть хотя бы одна зависимость, есть
маленький бейдж link с числом зависимостей. По наведению — список имён
upstream-шагов.
Когда зависимость заканчивается failed или cancelled, все
downstream-шаги уходят в skipped с причиной dependency failed: <имя шага>. Runtime-вид красит такие чипы серым, чтобы было видно, какую
ветку оборвали.
Когда раскидывать параллельно
- Независимая подготовка — наполнение фикстур, прогрев кэшей,
пред-создание тестовых пользователей — параллельно сокращает общее время. - Независимые проверки — три разных эндпоинта должны быть зелёными
после деплоя — параллельно по той же причине.
Когда оставлять линейно
- Цепочка токенов — шагу N нужен
{{plan.X}}от шага N-1. Оставьте
дефолтныйdependsOn: [previous], раннер сериализует автоматически. - Stateful-операции — «создать заказ» должно завершиться раньше «отменить
заказ». Выразите порядок черезdependsOn.
7. Просмотр прогона в реальном времени
Нажмите Run на кейсе, или запустите элемент Test Plan,
ссылающийся на кейс, — откроется Runtime Flow View.
Каждый шаг — это карточка в дереве. Разверните карточку и увидите прямо в
ней:
- запрос, который ушёл (URL, заголовки, тело — полностью резолвленные,
секреты замаскированы); - ответ (статус, заголовки, тело, длительность);
- чип env summary — какое окружение, сколько переопределений, сколько
секретов; - все значения, которые извлекли правила Extract (например,
plan.token = "ey…").
Небольшой чип на каждой карточке несёт live-статус: pending,
waiting (заблокирован зависимостью), running, passed,
failed, skipped, awaiting manual.
Runtime-вид обновляется по ходу прогона — обновлять страницу не нужно.
Полный справочник — на странице
Runtime-вид прогона.
8. Пошаговая отладка (sequential debug)
Debug-прогон запускает кейс так же, как обычный, но ставит паузу
после каждого шага. Вы смотрите, что произошло, решаете, что делать
дальше, и нажимаете Continue, чтобы идти дальше.
Чтобы запустить debug-прогон:
- Откройте кейс.
- В меню запуска выберите Debug run вместо обычного Run.
- Первый шаг стартует и завершится, runtime-вид покажет внизу жёлтую
полосу paused с тремя кнопками:
| Кнопка | Действие |
|---|---|
| Continue | Отпускает паузу. Стартует следующий шаг (или следующий слой параллельных шагов). |
| Continue & edit | Позволяет до возобновления подправить значения plan, переопределения шага или тело запроса следующего шага. Изменение пишется в историю прогона. |
| Stop | Отменяет прогон. Уже завершённые шаги сохраняют свой результат; прогон завершается со статусом cancelled. |
С помощью Continue & edit удобно чинить «летящий» токен прямо в
середине отладки: вручную подменить plan.token на заведомо рабочий,
нажать Resume — и увидеть, как следующий шаг зеленеет.
Debug-прогоны — это обычные прогоны: они появляются в истории кейса, учитываются
в квотах ретеншна и попадают в общий Allure-отчёт, если кейс был
запущен в составе тест-плана. Единственное отличие — пауза после каждого
шага.
9. Типовые ошибки
Раннер строго относится к незаконченной конфигурации. Когда шаг не может
выполниться, runtime-вид помечает его красным, а чип ошибки в шапке шага
содержит полный текст сообщения — копируйте его сюда, чтобы найти лекарство.
«unresolved placeholder: {{plan.X}}»
В тексте шага есть {{plan.X}}, но никакой предыдущий шаг не записал
значение под этим именем.
Решение: откройте upstream-шаг (тот, что должен дать X), добавьте
правило Extract с To plan.X. Если переименовали — поправьте и
downstream-ссылки; бейдж конфликта в строке шага помогает найти большинство.
«secret not found: <alias>»
Шаг ссылается на {{secret.<alias>}}, но к этому алиасу не привязан секрет.
Решение: откройте Environment-блок шага, нажмите Add secret,
выберите исходный секрет в пикере и задайте алиас <alias>. Если пикер
секретов пуст — у вас нет прав на чтение ни одного секрета в этом пространстве имён:
попросите пространство имён-админа выдать доступ или создайте секрет через
Хранилище секретов.
«dependency cycle detected»
Вы задали dependsOn так, что, идя по стрелкам, возвращаетесь в исходную
точку (A → B → A).
Решение: откройте пикер Depends on у шагов в цикле и уберите одну из
обратных стрелок. Имена шагов в цикле перечислены в тексте ошибки — начните
с них.
«conflict — env override beats plan value»
Один и тот же ключ пишется и upstream-шагом (в plan.X), и переопределением
текущего шага. Runtime-вид показывает бейдж конфликта, предупреждая, что
победил plan-context.
Решение: решите, чей источник вам нужен. Если должно выиграть значение
upstream-шага — уберите строку override на downstream-шаге. Если override —
переименуйте либо ключ override, либо To в upstream-Extract, чтобы они
больше не пересекались.
«environment not found»
Привязанное окружение было удалено или перемещено в другое пространство имён после
того, как шаг был создан. Прогон шага падает уже на стадии резолва.
Решение: откройте дропдаун окружений в шаге и перевыберите. Если
окружение действительно удалили — пересоздайте его в API Tester или
возьмите другое с теми же именами переменных.
Продолжать ли при провале
По умолчанию, если ЛЮБОЙ шаг кейса падает — раннер каскадно скипает все
оставшиеся шаги, и кейс завершается со статусом Провал. Это
стандартное поведение для смоук-теста: первая поломка означает, что
весь сценарий сломан.
Но не каждый шаг критичен. Возможно, шаг 3 — это «отправить метрику в
аналитику»: полезно записать, но не повод останавливать релизный flow.
Тоггл Продолжать кейс, если этот шаг провалится на строке шага
помечает шаг как неблокирующий:
- Provider на неблокирующем шаге фиксирует провал (увеличивает
счётчик failed_steps, шаг подсвечивается красным в runtime-виде),
но раннер активирует следующий pending-шаг как обычно. - Кейс завершается со специальным статусом Пройдено с мягкими
провалами, если все остальные шаги прошли. Это «янтарный» статус,
отличный от зелёного Пройдено и красного Провал — дашборды
и CI-гейты могут решать, насколько строго к нему относиться. - Если позднее проваливается блокирующий шаг (либо пользователь
явно выбирает «остановить кейс» в модалке резолва — см. ниже),
кейс всё равно завершится статусом Провал, а оставшиеся шаги
каскадно скипнутся: hard fail доминирует над soft.
Переопределение на уровне резолва (модалка ручного разрешения)
Авторский флаг шага задаёт значение по умолчанию, но пользователь
может переопределить его для одной попытки. В модалке ручного резолва
чекбокс Продолжать при провале рядом с кнопкой Fail предзаполнен
из авторского флага шага:
- Оставьте как есть — чтобы уважить намерения автора кейса.
- Включите (если автор пометил шаг блокирующим) — чтобы продолжить
кейс несмотря на этот провал. Полезно, если вы знаете, что причина
— окружение, и перезапуск не имеет смысла. - Выключите (если автор пометил шаг неблокирующим) — чтобы
принудительно запустить каскад. Полезно, если вы видите более
серьёзную проблему и хотите остановить линию.
Переопределение записывается в строку попытки рядом с вложениями и
заметкой, так что audit-trail показывает, кто именно явно продолжил
или остановил кейс вопреки авторской настройке.
Когда использовать
- Используйте на: отправке телеметрии, опциональных шагах
очистки, проверках «nice to have», follow-up вызовах, не
гейтящих основной flow. - Не используйте на: аутентификации, основном действии под
тестом, setup-шагах, от которых зависят downstream-шаги
(кейс продолжится, но downstream всё равно упадёт — и вы
потеряете сигнал, который дал бы hard fail).
Audit trail
Журнал аудита фиксирует каждый резолв шага:
- Шаг выполнен — записывается при каждом резолве, независимо от результата.
- Продолжение при провале — записывается отдельно, когда пользователь явно выбрал «продолжить» на провальном шаге. Это позволяет отличить подавленный каскад от авторского значения по умолчанию.
Администраторы могут просмотреть этот след в Админ → Аудит.
Дальше: прочитайте Runtime-вид прогона
для полного справочника по live-просмотру, и
Управление тест-кейсами — для общей модели кейсов /
папок / версий.