Maestro Testing with DeviceLab

Run Maestro tests on physical devices, emulators, and simulators with DeviceLab. This guide covers setup, parallel testing, environment variables, and iOS physical device support - a feature that DeviceLab uniquely enables for Maestro.

Quick Start

Android

bash
curl -fsSL https://app.devicelab.dev/test-node/YOUR_ORG_KEY | sh -s -- \
  --framework maestro \
  --platform android \
  --app ./app.apk \
  --tests ./maestro-tests

Replace YOUR_ORG_KEY with your organization ID from the DeviceLab dashboard.

iOS Simulator

bash
curl -fsSL https://app.devicelab.dev/test-node/YOUR_ORG_KEY | sh -s -- \
  --framework maestro \
  --platform ios \
  --app ./MyApp.app \
  --tests ./maestro-tests

Writing Tests

Test File Structure

my-project/
├── app.apk
└── maestro-tests/
    ├── login.yaml
    ├── checkout.yaml
    └── settings.yaml

Sample Test (login.yaml)

yaml
appId: com.example.myapp
---
- launchApp
- tapOn: "Email"
- inputText: "[email protected]"
- tapOn: "Password"
- inputText: "password123"
- tapOn: "Sign In"
- assertVisible: "Welcome"

Device Selection

Specific Device

bash
curl -fsSL https://app.devicelab.dev/test-node/YOUR_ORG_KEY | sh -s -- \
  --framework maestro \
  --app app.apk \
  --tests maestro-tests/ \
  --device-names "Pixel 8"

Multiple Devices (Parallel)

bash
curl -fsSL https://app.devicelab.dev/test-node/YOUR_ORG_KEY | sh -s -- \
  --framework maestro \
  --app app.apk \
  --tests maestro-tests/ \
  --device-count 3

Default (1 Device)

bash
curl -fsSL https://app.devicelab.dev/test-node/YOUR_ORG_KEY | sh -s -- \
  --framework maestro \
  --app app.apk \
  --tests maestro-tests/

Test Suites

Run a specific suite file:

bash
curl -fsSL https://app.devicelab.dev/test-node/YOUR_ORG_KEY | sh -s -- \
  --framework maestro \
  --app app.apk \
  --tests maestro-tests/ \
  --suite regression.yaml

Suite file (regression.yaml):

yaml
flows:
  - login.yaml
  - checkout.yaml
  - settings.yaml

Environment Variables

Pass environment variables to your tests:

bash
curl -fsSL https://app.devicelab.dev/test-node/YOUR_ORG_KEY | sh -s -- \
  --framework maestro \
  --app app.apk \
  --tests maestro-tests/ \
  --cli-params "-e USERNAME=testuser -e PASSWORD=secret123"

Use in test (login.yaml):

yaml
appId: com.example.app
---
- launchApp
- tapOn: "Email"
- inputText: ${USERNAME}
- tapOn: "Password"
- inputText: ${PASSWORD}
- tapOn: "Sign In"

Test Timeout

Set timeout per test (in minutes):

bash
curl -fsSL https://app.devicelab.dev/test-node/YOUR_ORG_KEY | sh -s -- \
  --framework maestro \
  --app app.apk \
  --tests maestro-tests/ \
  --test-timeout 30

Default: 15 minutes.

iOS Physical Device

DeviceLab enables Maestro testing on physical iOS devices, which Maestro doesn’t natively support.

Build Your App for Physical Device

Apps built for simulator won’t work on physical devices (different architecture).

bash
cd /path/to/YourApp

xcodebuild build \
  -project YourApp.xcodeproj \
  -scheme YourApp \
  -destination 'generic/platform=iOS' \
  -derivedDataPath ./build \
  CODE_SIGN_STYLE=Automatic \
  DEVELOPMENT_TEAM=YOUR_TEAM_ID

Find your Team ID:

  • Xcode: Preferences > Accounts > Select Apple ID > View Details
  • Command line: security find-identity -v -p codesigning | grep "Apple Development"

Built app location:

bash
./build/Build/Products/Debug-iphoneos/YourApp.app

Run Tests on Physical Device

bash
curl -fsSL https://app.devicelab.dev/test-node/YOUR_ORG_KEY | sh -s -- \
  --framework maestro \
  --platform ios \
  --app ./YourApp.app \
  --tests ./maestro-tests/ \
  --device-names "John's iPhone"

What happens:

  1. DeviceLab builds Maestro iOS runner for your device (~2-5 min first time)
  2. Installs your app
  3. Runs tests
  4. Returns results

Subsequent runs are much faster (~30 sec) - runner is cached.

Device Node Setup for iOS Physical

On the Mac with the iPhone connected:

bash
curl -fsSL https://app.devicelab.dev/device-node/YOUR_ORG_KEY | sh -s -- \
  --apple-team-id "YOUR_TEAM_ID"

CI/CD Integration

GitHub Actions

yaml
name: Maestro Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Run Maestro Tests
        run: |
          curl -fsSL https://app.devicelab.dev/test-node/${{ secrets.DEVICELAB_ORG_KEY }} | sh -s -- \
            --framework maestro \
            --app ./app.apk \
            --tests ./maestro-tests/

GitLab CI

yaml
maestro-tests:
  script:
    - curl -fsSL https://app.devicelab.dev/test-node/$DEVICELAB_ORG_KEY | sh -s --
        --framework maestro
        --app app.apk
        --tests maestro-tests/

Jenkins

groovy
pipeline {
    agent any
    stages {
        stage('Maestro Tests') {
            steps {
                sh '''
                    curl -fsSL https://app.devicelab.dev/test-node/${DEVICELAB_ORG_KEY} | sh -s -- \
                      --framework maestro \
                      --app app.apk \
                      --tests maestro-tests/
                '''
            }
        }
    }
}

Troubleshooting

“No devices available”

Ensure Device Node is running:

bash
curl -fsSL https://app.devicelab.dev/device-node/YOUR_ORG_KEY | sh

Verify devices appear in DeviceLab dashboard.

“App installation failed” (iOS Physical)

Check app was built for physical device:

bash
file /path/to/YourApp.app/YourApp
# Should show: Mach-O 64-bit executable arm64
# NOT: Mach-O 64-bit executable x86_64 (that's simulator)

Rebuild for physical device with correct DEVELOPMENT_TEAM.

“Maestro runner build failed” (iOS Physical)

Set APPLE_TEAM_ID on the device node machine:

bash
curl -fsSL https://app.devicelab.dev/device-node/YOUR_ORG_KEY | sh -s -- \
  --apple-team-id "YOUR_TEAM_ID"

“Tests not found”

Check test directory structure:

bash
ls -la maestro-tests/
# Should contain .yaml files

Use absolute path if relative fails:

bash
--tests /full/path/to/maestro-tests/

Test timeouts

Increase timeout:

bash
--test-timeout 45

Device name not found

Use exact device name from dashboard:

bash
--device-names "John's iPhone"  # Include apostrophe
--device-names "Pixel 8"        # Exact match

Or use device count instead:

bash
--device-count 1

Best Practices

  1. Organize tests by feature - Group related tests in directories
  2. Use environment variables - Keep credentials out of test files
  3. Start small - Run 1 test on 1 device first, then scale
  4. Version your tests - Track test changes with git

Recommended project structure:

project/
├── app.apk
└── tests/
    ├── smoke/
    │   └── basic-flow.yaml
    ├── regression/
    │   ├── login.yaml
    │   ├── checkout.yaml
    │   └── suite.yaml
    └── e2e/
        └── full-journey.yaml

Next Steps