Developing E2E Tests for Mobile Applications (Maestro)
Maestro is the youngest among E2E tools for mobile applications, but already occupied a niche due to one quality: tests written in YAML, run with one command, and require no Appium server setup, XCUITest runner, or agent embedding in the app. This is black-box testing in pure form — the tool communicates with device via Accessibility API and knows nothing about app internals.
YAML Scenarios: Simple, But Nuances Exist
Minimal authorization flow:
appId: com.example.myapp
---
- launchApp:
clearState: true
- tapOn: "Email"
- inputText: "[email protected]"
- tapOn: "Password"
- inputText: "password123"
- tapOn: "Sign In"
- assertVisible: "Home"
tapOn searches for element by text, accessibilityLabel, testID or id. Search order is left to right in Accessibility hierarchy. If two elements on screen have same text — Maestro taps first, which may not be intended. In such cases use tapOn with clarification:
- tapOn:
text: "Add"
index: 1 # second element with this text
Or through id:
- tapOn:
id: "add_to_cart_button"
Important: id on Android is resource-id (com.example.app:id/add_to_cart_button), on iOS is accessibilityIdentifier. Maestro auto-detects platform.
Variables and Subflows
Maestro supports variables and nested flow calls — without this large test suites become copy-paste:
# flows/login.yaml
appId: com.example.myapp
---
- tapOn: "Email"
- inputText: ${EMAIL}
- tapOn: "Password"
- inputText: ${PASSWORD}
- tapOn: "Sign In"
# flows/checkout_test.yaml
appId: com.example.myapp
env:
EMAIL: [email protected]
PASSWORD: password123
---
- runFlow: flows/login.yaml
- tapOn: "Catalog"
- tapOn: "Buy"
- assertVisible: "Checkout"
runFlow allows building complex scenarios from reusable blocks. Variables overridden at run: maestro test --env [email protected].
Execution: Locally and in CI
Local execution without extra setup — Maestro's main advantage:
# Installation
curl -Ls "https://get.maestro.mobile.dev" | bash
# Run one test
maestro test flows/login_test.yaml
# Run entire directory
maestro test flows/
# Studio mode (UI with live preview)
maestro studio
maestro studio launches browser UI showing Accessibility hierarchy in real time and allows interactive element selection. For writing tests — faster than manual locator hunting.
Maestro Cloud
For CI without own devices — Maestro Cloud (paid service from creators):
maestro cloud --apiKey $MAESTRO_CLOUD_API_KEY flows/
Uploads app and flow files, runs on real devices in cloud, returns report with screenshots. GitHub Actions integration:
- name: Run Maestro tests on Maestro Cloud
uses: mobile-dev-inc/action-maestro-cloud@v1
with:
api-key: ${{ secrets.MAESTRO_CLOUD_API_KEY }}
app-file: app/build/outputs/apk/debug/app-debug.apk
flows-file: flows/
For self-managed CI (without Maestro Cloud) — local emulator + regular maestro test in pipeline.
Limitations to Know
Maestro can't do custom gestures: pinch, rotate, multi-touch. For apps with maps or galleries needing zoom — use Appium or Detox.
No direct JavaScript context access (unlike Detox). If need to check Redux store state or call method — no way without workarounds (e.g., deep link with test command).
Assertions limited to visibility (assertVisible, assertNotVisible) and text presence. Can't check exact attribute value or element coordinate.
Despite this, for standard CRUD apps, marketplaces, service apps Maestro covers 80–90% of needed E2E scenarios with minimal maintenance effort.
What's Included
- Writing YAML flows for key user scenarios
- Setting up variables and reusable subflows
- CI integration (GitHub Actions / GitLab CI)
- Maestro Cloud execution setup or local emulator
- Documentation for adding new tests
Timeline
3–5 days depending on scenario count. 5–7 flows for typical CRUD app — 3 days. Complex multi-screen scenarios with variables and nested flows — 5 days. Cost is calculated individually.







