skills/make-tests/SKILL.md
Walk the app using computer use and generate Grantiva screen definitions and flow YAML files for every discovered user flow. Use after /swift-assist:doctor for reliable tests.
npx skillsauth add grantiva/swift-assist make-testsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Walk the running app with computer use, discover user flows, and generate grantiva.yml screen definitions plus standalone flow YAML files that can be run with grantiva ci run or locally with grantiva diff capture.
/swift-assist:make-tests
/swift-assist:make-tests --flow=onboarding
/swift-assist:make-tests --flow=login
/swift-assist:make-tests --all
/swift-assist:make-tests --output=flows/
--flow=<name>: Generate tests for a specific flow (e.g., onboarding, login, checkout, settings)--all: Discover and generate tests for all reachable flows--output=<dir>: Output directory for flow YAML files (defaults to flows/)grantiva runner start)/swift-assist:doctor and /swift-assist:add-identifiers first so elements have accessibility identifiersIf no doctor report exists, warn:
No doctor report found. Tests will be more reliable with accessibility
identifiers. Run /swift-assist:doctor --fix first, or continue without them.
Continue anyway? (y/n)
Using computer use, walk the app to map its structure:
Use the Grantiva driver to inspect the hierarchy at each screen:
# The driver exposes the accessibility tree - use it to identify tappable elements
Group the discovered screens into logical user flows:
| Flow Name | Description | Screens |
|-----------|-------------|---------|
| onboarding | First-launch experience | Welcome -> Features -> Permissions -> Home |
| login | Authentication flow | Login -> Home |
| signup | New account creation | Signup -> Verify -> Home |
| settings | Settings navigation | Home -> Settings -> (each setting) -> Back |
| profile | Profile management | Home -> Profile -> Edit -> Save |
| checkout | Purchase flow | Cart -> Payment -> Confirmation |
If --flow is specified, only generate that flow. Otherwise:
--all, generate all discovered flowsFor each screen in the selected flows, add a screen entry to grantiva.yml:
screens:
- name: Landmarks
path: launch
- name: Favorites
path:
- tap: "Favorites"
- name: DeepLinks
path:
- tap: "Deep Links"
- name: CachingDemo
path:
- tap: "deeplinks-link-caching-demo"
- wait: 1
- name: LandmarkDetail
path:
- tap: "Landmarks"
- wait: 5
- tap: "Golden Gate Bridge"
- wait: 1
Note the mix: tabs are tapped by label text ("Favorites"), inner elements by accessibility identifier ("deeplinks-link-caching-demo"), and list items by visible content ("Golden Gate Bridge"). Use whatever the hierarchy actually exposes for each element.
Create standalone Maestro-compatible flow files in the output directory:
flows/browse-landmarks.yaml:
appId: com.example.myapp
---
- launchApp
- assertVisible: "Landmarks"
- assertVisible: "Featured"
- takeScreenshot: "Landmarks Home"
- tapOn: "Golden Gate Bridge"
- assertVisible: "Plan Visit"
- takeScreenshot: "Landmark Detail"
flows/plan-visit.yaml:
appId: com.example.myapp
---
- launchApp
- assertVisible: "Landmarks"
- tapOn: "Golden Gate Bridge"
- tapOn: "landmark-detail-link-plan-visit"
- assertVisible: "Visit Scheduled!"
- takeScreenshot: "Visit Confirmation"
- tapOn: "visit-confirmation-button-done"
- assertVisible: "Landmarks"
flows/deep-links.yaml:
appId: com.example.myapp
---
- launchApp
- tapOn: "Deep Links"
- assertVisible: "Deep Links"
- tapOn: "deeplinks-link-caching-demo"
- assertVisible: "Caching Demo"
- takeScreenshot: "Caching Demo Screen"
For apps that load data from an API, the recommended approach is mock services with a UI_TESTING build flag:
.mock or .preview service variantsSWIFT_ACTIVE_COMPILATION_CONDITIONS='DEBUG UI_TESTING'grantiva diff capture --app-file <path-to-built-app> to test with the mock binaryFor flows that require specific app state (logged in, onboarded, etc.), use run_flow to reference shared setup:
appId: com.example.myapp
---
- launchApp
- tapOn: "Deep Links"
- tapOn: "deeplinks-link-caching-demo"
- assertVisible: "Caching Demo"
- takeScreenshot: "Caching Demo"
Note to user:
Test state management (v1): Flows use a shared setup file for authentication.
For more robust state management (mock servers, seed data, launch arguments),
this will be expanded in a future version.
For each generated flow, do a quick sanity check:
run_flow references point to files that existTest Generation Report
======================
Flows generated: 5
Screen definitions added to grantiva.yml: 12
Flow YAML files created: 7
flows/navigate-to-home.yaml (shared setup)
flows/_setup-authenticated.yaml (auth setup)
flows/onboarding.yaml (4 steps)
flows/login.yaml (6 steps)
flows/settings.yaml (8 steps)
flows/profile.yaml (5 steps)
flows/checkout.yaml (7 steps)
Next steps:
/swift-assist:test - Run these flows locally
/swift-assist:vrt - Capture visual baselines for each screen
For cloud CI integration, push your grantiva.yml and flows/ directory,
then add `grantiva ci run` to your GitHub Actions workflow.
See: https://docs.grantiva.io/cli/ci-integration
tap actions when available - never use coordinates# TODO: needs accessibilityIdentifierwait steps after navigation actions to allow transitions to completeassert_visible after navigation to verify the expected screen loadedrun_flow for shared setup (like authentication) instead of duplicating stepstesting
Run visual regression testing using Grantiva's diff pipeline. Capture screenshots, compare against baselines, and report visual differences. Use for catching unintended UI changes.
testing
Approve current VRT captures as new baselines. Can approve all or specific screens selectively. Use after reviewing /swift-assist:vrt results.
testing
Run generated test flows against the app in the simulator using Grantiva. Use after /swift-assist:make-tests to execute and validate your user flows.
development
Add the UI_TESTING / .mock services pattern to the app entry point so Grantiva can run tests with deterministic data and no live server. Use before make-tests when the app talks to an API.