Skip to main content

Mobile Testing

The platform runs Appium-based mobile UI tests against four execution tiers. Pick the one that fits your team's constraints — vendor lock-in, infrastructure ownership, iOS coverage, cost.

The four tiers

TierWhere the device livesBest forCost
T1 — Local emulatorDeveloper's macOS hostDev loop, demos$0
T2 — Self-hosted in your K8sCustomer-owned bare-metal or KVM-enabled cloud nodesProduction CI, on-prem, "no vendor lock"infra + ops
T3 — Self-hosted real devicesOpenSTF / DeviceFarmer in your device labHardware-specific bugs, full sensor accesshardware + ops
T4 — Hosted device farmsBrowserStack / Sauce Labs / AWS Device FarmiOS without owning Macs, on-demand scaleper-minute

You can mix tiers. Common shapes:

  • Dev → T1, CI → T2, release matrix → T4 — most popular split
  • All T2 — strongest "data stays in our infra" posture
  • All T4 — fastest to set up, no ops burden

How a mobile app is configured

Every mobile app on the platform carries a cloud_provider value:

ValueRoutes to
NONET1 (local Appium)
SELF_HOSTEDT2 (your K8s registry — picks an emulator pod by capability match)
BROWSERSTACKT4 BrowserStack App Automate
SAUCELABST4 Sauce Labs Real Device Cloud
AWS_DEVICE_FARMT4 AWS Device Farm (async; coming soon)

The agent reads this field at job time and dispatches to the right driver.

What's the same across tiers

  • YAML test definition — write once, run anywhere. See yaml-format.
  • Test data — credentials, app binaries, environment variables work the same way.
  • Result reporting — pass/fail/screenshots flow back into the same Job History view.
  • Credential vault — vendor keys live once in your environment vault, referenced by tag. See credentials.

Before you crawl: static inspection

Before booting a device, run static inspection on an uploaded APK/IPA — it extracts a screen map + element inventory with no device (seconds, backend-side), and tells you whether a live crawl is even needed via a recommendation field. Reliable for native apps; it honestly declines for React Native / Flutter and points you at the live device inspection.

After you crawl: what you get back

A crawl returns the same element shape for Android and iOS, so a tool written against one platform works unchanged against the other — see Crawl element schema.

It also grades how testable the app is. Controls that can only be found by their text or their position on screen are flagged, with a plain suggestion for the developer, because those are exactly the tests that break on the next redesign. That verdict is the part only your team can act on.

What's different across tiers

ConcernT1 LocalT2 Self-hostedT4 Vendor
iOS supportSimulator only (macOS)Android only (KVM)Yes (real devices)
Real device supportVia USBVia OpenSTF (T3)Yes
APK uploadLocal fileLocal fileAuto-uploaded to vendor
Parallel runs1N podsUp to your concurrency tier
Network accessLocalhostCluster-internalVendor-managed
Setup time30 min1-2 days infra15 min (signup)

Quick start

The fastest way to see a passing mobile test:

  1. Set up Appium locally — see Local emulator for the macOS native path
  2. Create a mobile app — pick cloud_provider = NONE, upload an APK
  3. Write a YAML test — three steps: tap, type, assert
  4. Run — agent connects to local Appium and executes

Once that's green, switch the same test to BrowserStack by changing cloud_provider and pointing at a vault credential. No YAML changes. See device-farms.

Architecture diagram

Platform Backend
┌────────────────────┐
│ Application registry│
│ (Mobile apps) │
│ /mobile-config │
└─────────┬──────────┘
│ job created

mobile-test-agent (JAR)

┌─────────────────┼─────────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ T1 Local │ │ T2 Self │ │ T4 Vendor│
│ Appium │ │ hosted │ │ farm │
│ on macOS │ │ pods │ │ APIs │
└────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │
▼ ▼ ▼
Emulator on Emulator in BrowserStack /
developer Mac K8s pod (KVM) Sauce Labs cloud

When to use which tier

Use T1 when: you're a developer iterating on tests, or running a demo on your laptop.

Use T2 when: you self-host the platform, you have bare-metal or KVM-enabled K8s capacity, and you want zero vendor data exposure. Best balance of cost + control for sustained CI usage.

Use T4 when: you need iOS coverage (without owning Macs), real-device behavior (sensors, biometrics, OEM-specific bugs), or burst capacity beyond what your own infra provides.

Mix tiers when: your workflow has different stages with different needs (dev loop = T1, CI = T2, release matrix on real devices = T4). The platform doesn't care — same YAML, same Job History, different cloud_provider per app.

Next steps