Building a Maestro mobile automation workspace from zero

The structure, conventions, and CI wiring behind the first automation workspace I built — and what I'd keep or change doing it again.

When I joined my first QA team, every release meant a full manual regression pass. It worked, but it was slow, repetitive, and easy to rush under deadline pressure. I got the chance to fix that by building the company's first mobile automation workspace, and I chose Maestro for it. This post is the practical version of what I set up: the structure, the conventions, and the CI wiring.

Why Maestro

Maestro's flows are plain YAML, which means anyone on the team can read a test and understand what it does — no page-object classes to learn before your first contribution. It also handles the flakiest parts of mobile UI testing (waiting, retries, animations) by default. For a small team starting from zero, time-to-first-useful-test matters more than framework power, and Maestro's is measured in minutes.

Workspace structure

The single most important early decision was separating flows (what a test covers) from subflows (reusable steps). My layout:

.maestro/
  flows/
    auth/login.yaml
    auth/logout.yaml
    orders/create-order.yaml
  subflows/
    login-as.yaml
    dismiss-onboarding.yaml
  config.yaml

Anything used by two or more flows becomes a subflow. Login is the obvious first one:

# subflows/login-as.yaml
appId: ${APP_ID}
---
- launchApp:
    clearState: true
- tapOn:
    id: "email-input"
- inputText: ${USERNAME}
- tapOn:
    id: "password-input"
- inputText: ${PASSWORD}
- tapOn:
    id: "login-button"
- assertVisible:
    id: "home-screen"

Credentials and app IDs come from environment variables, so the same flows run against staging and production builds without edits.

Selector and assertion standards

Flaky selectors kill automation projects faster than anything else. Our rules were simple:

Wiring it into GitHub Actions

Automation that only runs on someone's laptop isn't automation — it's a demo. The GitHub Actions job boots an emulator, installs the build, and runs the tagged suite:

- name: Run smoke suite
  run: maestro test .maestro/flows --include-tags=smoke

- name: Upload failure artifacts
  if: failure()
  uses: actions/upload-artifact@v4
  with:
    name: maestro-recordings
    path: ~/.maestro/tests

Two details paid for themselves many times over: parallel execution (splitting flows across shards so the suite finishes in a fraction of the serial time) and failure artifacts — screenshots and recordings uploaded automatically, so a red build comes with evidence instead of a mystery.

What it changed

Regression testing time dropped by roughly half. But the bigger change was psychological: developers stopped asking "did QA check this?" and started checking the CI status. When the suite is green on every build, release conversations get shorter.

If you're starting your own workspace: begin with five smoke flows for the paths that would embarrass you in production, get them running in CI the same week, and only then grow the regression suite. CI-first beats coverage-first.