Перейти к содержимому

Команды

Terminal window
tapstep test <flow.yaml | dir> [--driver web|android|ios|app[:port]] [-v]
tapstep test app.flow.yaml --headed # реальное окно браузера
tapstep test app.flow.yaml -c # watch-режим: перезапуск этого флоу при сохранении
tapstep test flows/ --tags smoke --shards 4 # прогон папки: фильтр по тегам, 4 флоу параллельно
tapstep live <flow.yaml> [--port 7878] # интерактивный live-просмотр в браузере

--driver web|android|ios|app[:port] выбирает цель (app = десктоп-приложение с тестовым мостом, порт по умолчанию 9223 — см. Десктоп-приложения). Без флага tapstep определяет цель сам: appId-URL означает web, иначе — подключённое Android-устройство или загруженный iOS-симулятор. Флоу с заголовком vscode: идёт на драйвер VS Code, а флоу с device: none выполняется вообще без устройства.

--browser chrome|chromium|edge|brave|opera|vivaldi|yandex|firefox|managed или путь к исполняемому файлу браузера выбирает браузер (managed = прибитый Chromium в ~/.tapstep/browsers). --viewport WxH, --locale en-US настраивают браузер; --video-scale 1–4 пишет --video в N× от вьюпорта (чёткий ролик для демо). -e KEY=VAL переопределяет переменные сценария; --env-file FILE подгружает дополнительные dotenv-файлы поверх автоматически найденного .env; --env-set NAME гоняет против названного окружения из блока environments: конфига (иначе берётся его defaultEnvironment) и подгружает вместе с ним .env.NAME — см. config.yaml.

Остальные флаги test:

  • --tags a,b / --exclude-tags a,b — фильтр прогона папки по tags: флоу.
  • --shards N — запускать до N флоу папки одновременно.
  • --config <config.yaml> — умолчания рабочей области: flows, теги, ai, report; флаги важнее — см. config.yaml.
  • -c / --continuous, --video, --capture-network — только для одного флоу: перезапуск при сохранении, запись видео рядом с флоу, захват сетевого трафика.
  • --analyze — AI-триаж упавшего флоу (нужен блок ai: в конфиге или TAPSTEP_AI_ENDPOINT/MODEL/KEY).
  • --strict-selectors — валить прогон, если шаг прошёл только потому, что совпала одна из его альтернатив or:. Без флага такой шаг зелёный, а прогон пишет ⚠ N step(s) passed on an alternative selector.
  • --report json|junit|html|allure, --output <file|dir> — см. Отчёты.
  • Тюнинг, в мс: --wait-timeout, --settle-timeout, --settle-stable-for, --poll-interval; повторы: --action-retries, --scroll-attempts.

live тоже принимает --driver, --browser, --headed, --viewport, --locale и флаги тюнинга.

Terminal window
tapstep inspect [target] [--measure] [--driver …] [--browser …] # компактный снимок экрана
tapstep list-devices # браузеры, устройства Android, симуляторы iOS
tapstep start-device android|ios [--name <avd|sim>] # поднять эмулятор / симулятор
tapstep doctor # проверить внешние инструменты каждого драйвера
tapstep privacy install # локальная модель маскирования PII (~945 МБ загрузки)
tapstep privacy status # privacy-режим: включён? модель установлена?
tapstep validate <flow.yaml | dir> # проверить сценарии разбором и загрузить include, без устройства
tapstep fix-paths [path] [--write] [--all] # переписать пути runFlow с ../ от корня проекта
tapstep init [path] [--samples] [--agents] # стартовый сценарий / примеры / настройка агентов
tapstep skill status # по каждому агенту: установлен? той же версии, что бинарь?
tapstep skill install # скилл агента для Claude Code / Codex / Gemini CLI / Cursor / OpenCode
tapstep skill refresh # перезаписать установленные копии версией из этого бинаря
tapstep mcp [--driver app:9223] [--browser …] # stdio MCP-сервер для AI-клиента
tapstep appmeta <apk|ipa|app> # метаданные сборки как JSON
tapstep bugreport [path] # zip с локальной диагностикой для issue
tapstep update [--check] # самообновление до последнего релиза

tapstep mcp по умолчанию берёт подключённое устройство, иначе web. tapstep update после обновления запускает skill refresh, чтобы установленные скиллы агентов шли за бинарём; skill refresh ничего не устанавливает заново — для этого есть skill install.

tapstep validate читает сценарий (или целую папку, включая файлы .helper.yaml) и сообщает то, на чём споткнулся бы test, ещё до подъёма устройства. Он же предупреждает про ${VAR}, который остаётся незакрытым в каком-то окружении, и называет, в каком именно, — та самая проверка, что ловит тест, записанный на одном окружении, до того как его запустят на другом. Хелперы так не проверяются: их переменные приходят от вызывающего.

С версии 0.13.12. CLI и десктоп постарше читают путь в runFlow: только от папки файла, который его пишет, поэтому записанный от корня include во вложенном флоу там не загрузится — обновите оба, прежде чем запускать fix-paths --write.

Путь в runFlow: ищется сначала в папке файла, который его пишет, затем от корня проекта (папки ближайшего config.yaml). Записанная от корня — helpers/login.helper.yaml — та же строка работает во флоу на любой глубине, поэтому группа шагов, скопированная из одного теста в другой, продолжает запускаться. Правило одно для всех файлов, которые называет шаг: runScript:, схема request:, uploadFile:, installApp: и хелперы хуков before:/after:.

validate загружает каждый include оттуда, где лежит файл, и по строкам сообщает: хелпера по этому пути нет (и какой файл с таким именем нашёлся в проекте), обязательные параметры не переданы, есть цикл, — и завершается с ненулевым кодом; хелпер за пределами проекта — предупреждение.

tapstep fix-paths переписывает include с ../ (или ./, или разделителями \) в форму от корня. По умолчанию он только показывает изменения:

Terminal window
$ tapstep fix-paths flows
flows/checkout/cart/pay.flow.yaml
4 - ../../../helpers/login.helper.yaml
4 + helpers/login.helper.yaml
1 path(s) in 1 file(s) would change — run again with --write to apply

--write сохраняет файлы; --all переписывает от корня и include, которые называют хелпер рядом с флоу (login.helper.yaml). Include, который после переписывания нашёл бы другой файл или лежит вне проекта, остаётся как есть.

Terminal window
tapstep import playwright <spec.ts|dir> [-o flows] # вывод codegen -> флоу
tapstep export playwright <flow.yaml|dir> [-o playwright] # флоу -> *.spec.ts
tapstep export extester <flow.yaml|dir> [-o extester] # флоу с vscode: -> *.test.ts

Куда попадает экспорт — настройка проекта, а не привычка отдельной команды: без -o обе пишут в папку, названную в блоке exports: файла config.yaml, и только в его отсутствие — в playwright/ и extester/ в корне проекта. Десктоп и MCP-инструменты читают ту же настройку; блок exports:, который не разбирается, останавливает экспорт, а не молча откатывает его в папку по умолчанию.

Каждый экспортированный файл открывается строкой // tapstep: с именем сценария, из которого он вышел, и хешами обеих сторон, — так следующий экспорт понимает, остался ли файл тем, что говорит сценарий, ушёл ли сценарий вперёд и не правил ли файл кто-то руками.

Импорт читает то, что пишет playwright codegen: по одному флоу на каждый test(...), локаторы переводятся в селекторы (getByTestId → testId, getByRole → role + name, .nth() → index, .filter({ hasText }) → containsDescendants). Всё, что перенести нельзя — циклы, вспомогательные функции, xpath-локаторы, аргументы, вычисляемые во время выполнения, — попадает в отчёт с номером строки и записывается во флоу как комментарий # TODO ровно в том месте, где встретилось. Ничего не выбрасывается молча, поэтому отчёт и есть список того, что ещё нужно доделать руками.

export playwright пишет браузерную часть флоу. Шаги без эквивалента в Playwright (вся мобильная часть, AI-проверки) становятся комментариями // TODO и перечисляются в сводке. ${VAR} превращается в process.env.VAR, так что сгенерированный спек читает значения так же, как их читал флоу; значение env, которое само выражение (TITLE: "Order ${Date.now()}"), становится одним const в начале спека, и его читает каждый шаг — прогон тоже вычислял его один раз. Каждый элемент ищется через маленький хелпер ui(), который смотрит на странице и во всех фреймах внутри неё: флоу никогда не говорит, в каком документе элемент, так что превью в <iframe> не требует frameLocator руками. tapOn с последующим вводом становится одним fill(), а проверка, уточнённая по тексту, сохраняет обе половины (expect(locator).toHaveText(…)). before: / after: флоу — вся разрешённая цепочка, вместе с хуками проекта и testspace — становятся test.beforeEach / test.afterEach спека; у флоу без хуков блоков нет. Флоу с заголовком vscode: экспортируется вместо этого как самостоятельный Electron-спек: он ставит vsix флоу в одноразовый профиль и запускает установленный VS Code через Electron-лаунчер Playwright — так же, как это делают собственные smoke-тесты VS Code. vscodeCommand превращается в название палитры, на которое команда отзывается, а id без известного названия остаётся // TODO, а не превращается в команду, делающую другое. Палитра находит команду и по её id, и именно поэтому три команды пресета clean, которые палитра скрывает, когда нужное состояние уже есть, печатаются как id: их отсутствие читается как «делать нечего», а в интерфейсе на другом языке английское название не найдётся никогда. Остальные — названия, так что экспорт рассчитан на VS Code по-английски; для другого языка поставьте "locale": "en" в argv.json.

export extester — второй способ уйти с флоу для VS Code: тест vscode-extension-tester — Mocha и chai поверх Selenium, запускается через extest. Флоу без заголовка vscode: он отвергает, а не пишет то, что не сможет выполниться; экспорт папки проходит мимо таких флоу и говорит, сколько их было. Первый экспорт в папку кладёт туда ещё и README.md с командами extest под неё (get-vscode, get-chromedriver, install-vsix, run-tests или setup-and-run одной командой), с --code_version, который назвал VS Code этой машины, и с workspace, который раннер должен открыть флагом -r. В самих тестах: одна константа TIMEOUT — бюджет всех ожиданий файла (пошаговые таймауты флоу намеренно не переносятся), а элементы ищутся через помощник withWebview(...), который пробует документ workbench, а затем каждый iframe.webview → #active-frame по очереди, потому что флоу записывает, что у шага есть элемент, а не в каком документе он лежит.

--report json|junit|html|allure печатает json/junit/html-отчёт в stdout или пишет его в --output <file>; allure пишет папку allure-results/ в текущей директории (или в --output <dir>). Прогон папки с --report даёт один сводный отчёт.

С --config config.yaml, где есть блок report: (format, output — по умолчанию html → reports/, относительно папки конфига), каждый прогон без всяких флагов пишет туда <flow>.<ext>; прогон папки пишет один сводный файл. --report/--output по-прежнему важнее.

Блок — runFlow в .helper.yaml, repeat или retry — это один шаг, названный по тому, что он запустил, а его собственные шаги вложены внутрь: у упавшего хелпера видно, какой именно шаг упал. Верхний уровень по-прежнему считает один шаг на команду — по нему индексируются отчёты в CI.

Шаг, которому пришлось действовать на неуспокоившейся странице, говорит об этом в любом формате: в JSON у шага есть "settled": false и "unsettledReason" (Loading, Network(2), Mutating, Navigating или Timeout), в JUnit — <property name="unsettled"> у этого теста, в Allure — параметр unsettled, в HTML — плашка acted while loading в строке. У шага на успокоившемся экране этих полей нет — см. как прогон понимает, что страница успокоилась.

Шаг, прошедший только потому, что совпала одна из его альтернатив or:, говорит об этом так же: в JSON у шага есть объект drifted (used, primary, alternative), в JUnit — <property name="drifted">, в HTML — плашка drifted в строке, а итог прогона их считает. Такой прогон всё равно выходит с кодом 0 — валит его только --strict-selectors.

0 — все флоу прошли. 1 — флоу выполнились, часть упала. 2 — ошибка конфигурации или инфраструктуры (плохой флаг, нет устройства, нечитаемый конфиг): CI отличает красный прогон от сломанного раннера.

При падении tapstep печатает экран на момент ошибки и пишет <flow-stem>-failure.png — плюс <flow-stem>-failure.network.json, если записывался сетевой трафик, — в reports/ и печатает путь к файлу:

  • внутри проекта (папка ближайшего config.yaml или --config) — папка отчётов проекта: report.output, если задан, иначе reports/. К имени добавляются папки флоу относительно корня проекта: flows/auth/login.flow.yaml падает в reports/flows-auth-login.flow-failure.png;
  • вне проекта — reports/ рядом с файлом флоу.

Никогда не в текущую директорию. Сетевой лог может содержать данные запросов — держите reports/ в .gitignore; tapstep один раз подскажет, если .gitignore проекта его не игнорирует (сам файл не правит).

Terminal window
tapstep login [--token tapstep_pat_…] # SSO в браузере; --token сохраняет персональный токен
tapstep logout
tapstep token create --name <name> [--expires-days N] # персональный токен для CI, показывается один раз
tapstep token list # ваши токены — id, имя, префикс, последнее использование; без секрета
tapstep token revoke <id|name>

tapstep login по умолчанию выполняет вход через браузер (SSO); --token вместо этого сохраняет токен, а TAPSTEP_TOKEN в окружении считается входом. Токен даёт tapstep token create: он один раз открывает браузер и печатает в stdout только токен (… | gh secret set TAPSTEP_TOKEN работает); list и revoke входят через браузер так же. Токен tapstep_pat_… сверяется с API раз в сутки и кэшируется в ~/.tapstep/token-check.json: отозванный или неизвестный останавливает команду, а недоступный API прогон никогда не останавливает (предупреждение — только если токен ещё ни разу не проверялся на этой машине). Любое другое значение TAPSTEP_TOKEN работает с предупреждением до 0.15 — см. CI / GitHub Actions.

Все команды, кроме login, logout, token, doctor, bugreport, privacy, update, schema, validate, fix-paths, skill status и skill refresh, требуют предварительного входа; после входа всё работает офлайн.