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.

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