Marathon Cloud supports executing Maestro flows on both Android and iOS. The platform handles device provisioning and parallel execution of your YAML-defined flows.
Quick start
Section titled “Quick start”marathon-cloud run maestro android \ --api-key $MARATHON_CLOUD_API_KEY \ --application app-debug.apk \ --test-application flows/Flow structure
Section titled “Flow structure”Each Maestro flow is a separate YAML file and becomes one test that can run in parallel with the others.
Marathon Cloud discovers flows the same way maestro test does, so an existing workspace works unchanged.
Example flow
Section titled “Example flow”appId: com.example.apptags: - smoke---- launchApp- tapOn: "Login"- tapOn: "Password"- inputText: "password123"- tapOn: "Submit"- assertVisible: "Welcome"Workspace layout and config.yaml
Section titled “Workspace layout and config.yaml”Flow discovery follows Maestro’s workspace rules:
- By default only YAML files directly inside
--test-applicationare flows. Files in subdirectories are ignored unless aconfig.yamlat the root of the flows directory lists them. - Flows referenced by
runFlow(subflows) should live outside the matched patterns so they are not run on their own. includeTags/excludeTagsinconfig.yamlare applied at parse time, before Marathon Cloud’s own filtering.executionOrderis not supported; a workspace that defines it is rejected. Flows always run independently.
A typical layout:
flows/├── config.yaml├── login.yaml├── checkout/│ └── happy_path.yaml└── subflows/ └── sign_in.yaml # used via runFlow, not run directlyflows: - "*.yaml" - "checkout/**"A flow’s name: field is not used for test identity; the file name is. Two files with the same name in different directories are distinct tests.
Run Maestro tests
Section titled “Run Maestro tests”Marathon Cloud provides separate subcommands for Android and iOS Maestro execution.
Command
marathon-cloud run maestro android \ --api-key YOUR_API_KEY \ --application path/to/your-app.apk \ --test-application path/to/flows/Command
marathon-cloud run maestro ios \ --api-key YOUR_API_KEY \ --application path/to/YourApp.app \ --test-application path/to/flows/ \ --os-version 18.4The app must be a simulator build (Debug-iphonesimulator). A .app directory, .zip, or .ipa is accepted.
Point the --test-application parameter to the directory containing your YAML flows.
Common parameters
Section titled “Common parameters”| Parameter | Description |
|---|---|
--application |
Application binary: APK on Android; .app, .zip, or .ipa on iOS. |
--test-application |
Directory containing Maestro YAML flows. |
--os-version, --device |
Device selection, same values as run android / run ios. |
--arch |
Android only: amd64 (default) or arm64. arm64 needs Android 9 or later. |
--maestro-env |
Environment variable for flows (KEY=VALUE). Repeatable. |
--concurrency-limit |
Cap parallel devices if your backend cannot handle many flows at once. See limiting concurrency. |
FLOW... |
Positional flow files or directories to run; everything runs when omitted. |
Maestro runs always use google_apis Android images; --system-image and --flavor are not available.
Best practices
Section titled “Best practices”Self-contained flows
Section titled “Self-contained flows”Design each flow to be independent. Avoid relying on the state left by a previous flow, as Marathon Cloud executes flows in parallel across different devices.
Flow duration
Section titled “Flow duration”Aim for flows that take between 40 and 80 seconds to complete. Very short flows increase the relative overhead of device provisioning, while very long flows reduce the benefits of parallelization.
File organization
Section titled “File organization”Place one flow per YAML file and keep shared steps in subflows invoked with runFlow.
Marathon Cloud does not support executionOrder; if one flow depends on another, merge them or make each self-contained.
Advanced configuration
Section titled “Advanced configuration”Environment variables
Section titled “Environment variables”Use the --maestro-env flag to pass variables to your flows.
These can be accessed in your YAML files using the ${VARIABLE_NAME} syntax.
marathon-cloud run maestro android \ --application app.apk \ --test-application flows/ \ --maestro-env "API_URL=https://staging.api.com"Selecting flows
Section titled “Selecting flows”Pass flow files or directories as positional arguments after the flags to run a subset. Paths are relative to the working directory, inside --test-application.
marathon-cloud run maestro android \ --application app.apk \ --test-application flows/ \ flows/login.yaml flows/onboarding/Filtering by tag or path
Section titled “Filtering by tag or path”--filter-file works on Maestro runs. Each flow file becomes a test: the directory is the package, the class is always MaestroTest, the method is the file name without extension, and the flow’s tags: become annotations.
| Flow file | package |
method |
fully-qualified-test-name |
annotation |
|---|---|---|---|---|
flows/login.yaml |
(empty) | login |
MaestroTest#login |
its tags: |
flows/auth/login.yaml |
auth |
login |
auth.MaestroTest#login |
its tags: |
flows/checkout/cart/add.yaml |
checkout.cart |
add |
checkout.cart.MaestroTest#add |
its tags: |
Paths are relative to --test-application. Flows in subdirectories must be included by config.yaml (see workspace layout) or they are never parsed, regardless of the filter file.
Because every flow shares the class name, the useful filter types are annotation, package, method, and fully-qualified-test-name. simple-class-name and fully-qualified-class-name select whole directories at best.
Run only flows tagged smoke, excluding the experimental directory:
flows: - "**"appId: com.example.apptags: - smoke---- launchAppfilteringConfiguration: allowlist: - type: "annotation" values: ["smoke"] blocklist: - type: "package" values: ["experimental"]marathon-cloud run maestro android \ --application app.apk \ --test-application flows/ \ --filter-file smoke.yamlSee filtering for the full schema. For a one-off subset, positional arguments are simpler.
Troubleshooting
Section titled “Troubleshooting”Path syntax
Section titled “Path syntax”Always use Linux-style forward slashes (/) for file paths in your Maestro flows, even if you are developing on Windows.
Marathon Cloud executes tests in a Linux-based environment.
App ID mismatch
Section titled “App ID mismatch”Ensure the appId defined in your YAML flows matches the package name (Android) or bundle identifier (iOS) of the application you upload.
Mismatching IDs will prevent Maestro from launching the application.