Maestro Testing Skill
Maestro is a declarative YAML-based mobile UI testing framework. It provides deterministic regression tests that run without AI and are suitable for CI.
When to Use Maestro
- •Regression testing: Verify that existing flows still work after code changes
- •Smoke tests: Quick validation that the app launches and basic UI is functional
- •CI integration: Automated tests that block PRs on failure
- •Flow validation: Verify that Maestro flows exported from idb exploration work deterministically
Flow Structure
appId: com.example.myapp
name: Flow Name
tags:
- smoke
- regression
---
- launchApp:
appId: "com.example.myapp"
clearState: true
- tapOn:
id: "tab_home"
- assertVisible:
id: "home_content"
Selector Priority
Always prefer the most stable selector:
- •
id:-- Accessibility identifier. Most stable. Survives text changes and localization. - •
text:-- Visible text. Human-readable but breaks on localization. - •
point:-- Percentage coordinates. Last resort. Fragile across screen sizes.
# Best: id selector
- tapOn:
id: "login_button_submit"
# OK: text selector (only for single-language apps)
- tapOn:
text: "Submit"
# Avoid: coordinate selector
- tapOn:
point: "50%,90%"
SwiftUI TabView exception: Use
text:selectors for tab bar navigation..accessibilityIdentifier()on TabView children sets the ID on the content view, which is only in the tree when that tab is active. Seereferences/maestro-selectors.md.
See references/maestro-selectors.md for the full selector reference.
Key Commands
| Command | Purpose |
|---|---|
tapOn | Tap an element |
inputText | Type text into focused field |
assertVisible | Assert element is on screen |
assertNotVisible | Assert element is NOT on screen |
assertWithAI | Vision-based assertion using AI |
scroll | Scroll in a direction |
swipe | Swipe gesture |
launchApp | Launch/restart the app |
waitForAnimationToEnd | Wait for UI to settle |
takeScreenshot | Capture screenshot |
See references/maestro-flow-writing.md for the complete command reference.
Running Flows
# Run all flows in a directory maestro test tests/maestro/flows/ # Run a specific flow maestro test tests/maestro/flows/smoke/app_launch.yaml # Continuous mode (re-runs on file change) maestro test --continuous tests/maestro/flows/smoke/ # Filter by tags maestro test tests/maestro/flows/ --include-tags=smoke
Configuration
Create tests/maestro/config.yaml:
appId: "com.example.myapp" tags: - smoke - regression flows: - "flows/**/*.yaml"
Flow Maintenance
When flows break after UI changes:
- •Identify failure: Check which step failed and why
- •Update selector: If text changed, switch to
id:selector - •Re-record: If flow structure changed, re-run idb exploration to generate new flow
- •Validate: Run
maestro teston the updated flow - •Empty hierarchy: If
maestro hierarchyreturns almost no elements butidb ui describe-allworks, the app is likely running at legacy 320x480 resolution. Fix by addingUILaunchScreen: {}to Info.plist, then uninstall and reinstall the app.
See references/maestro-ci-integration.md for CI setup.
Example Flows
See examples/ for generic flow templates:
- •
smoke-test.yaml-- App launch verification - •
form-flow.yaml-- Form input and submission - •
navigation-flow.yaml-- Tab/screen navigation
Reference Files
- •
references/maestro-flow-writing.md-- Complete step type reference - •
references/maestro-selectors.md-- Selector types and best practices - •
references/maestro-ci-integration.md-- GitHub Actions and CI setup