Skip to main content

Mobile Configuration

Nothing mobile loads unless the active configuration has a mobile: section. Every key except platform has a default.

mobile:
serverUrl: ${MOBILECLI_URL:-http://localhost:12000}
autoStartServer: true # start mobilecli when the loopback server does not answer
mobilecliPath: mobilecli # full path when mobilecli is not on PATH
platform: android # android | ios (required)
deviceId: "" # exact id; wins over deviceName
deviceName: "" # regex on the device name
devices: [] # device pool: ids handed out one per test
pool: false # pool every online device matching deviceName
app:
bundleId: com.example.app # Android package / iOS bundle id
install: "" # optional .apk/.ipa/.app path, installed when the device opens
activity: "" # Android only: launcher activity, for apps with several (e.g. LeakCanary in debug)
reset: relaunch # none | relaunch | clearData
timeouts:
actionMs: 5000 # auto-wait budget of one action or assertion
pollMs: 100 # pause between two reads of the screen
rpcMs: 30000 # upper bound of one request to mobilecli
reserveMs: 300000 # wait for a device another test in this JVM holds
serverStartMs: 20000 # wait for an auto-started server to answer
allowRemote: false
headers: {} # e.g. Authorization: Bearer ${MOBILECLI_TOKEN}
screenshotOnFailure: true
recordVideo: off # off | failures | always
alerts: none # none | accept | dismiss (iOS alerts, Android permission dialogs)
animations: "" # on | off; empty leaves the device as it is
appearance: "" # light | dark; empty leaves the device as it is
KeyDefaultDescription
serverUrlhttp://localhost:12000mobilecli server; TestFly calls <serverUrl>/rpc.
autoStartServertrueStart mobilecli server start when a loopback serverUrl does not answer.
mobilecliPathmobilecliCommand used by autoStartServer.
platform— (required)android or ios.
deviceId""Exact device id (AVD name, serial or simulator UDID).
deviceName""Regex on the device name, used when deviceId is empty.
devices[]Device pool: ids handed out one per test.
poolfalsePool every online device of the platform that matches deviceName.
app.bundleId""App under test: Android package or iOS bundle id.
app.install"".apk, .ipa or .app path installed when the device opens.
app.resetrelaunchnone, relaunch or clearData, applied before each test.
timeouts.actionMs5000Auto-wait budget of one action, read, assertion or @WaitFor.
timeouts.pollMs100Pause between two reads of the screen.
timeouts.rpcMs30000Upper bound of one request to mobilecli.
timeouts.reserveMs300000How long a test waits for a device another test in this JVM holds.
timeouts.serverStartMs20000How long an auto-started server may take to answer.
allowRemotefalseAllow a non-loopback serverUrl (needs https://).
headers{}Extra HTTP headers on every request, e.g. for an authenticating proxy.
screenshotOnFailuretrueAttach a device screenshot to a failed test.
recordVideooffScreen recording per test: off, failures (kept for failed tests) or always; see Screen recording.
alertsnoneSystem alerts that cover the app: accept or dismiss them before every read of the screen, like Appium's autoAcceptAlerts / autoDismissAlerts (and autoGrantPermissions on Android). iOS (tracking, location, notifications): accept taps Allow/OK, dismiss taps Don't Allow/Ask App Not to Track/Cancel; with other labels (another device language) the last or first button. Android runtime permission dialogs: by button id, in any language. none leaves them to the test.
animations(empty)on or off, set when the device opens; off makes tests faster and steadier. Empty leaves the device as it is.
appearance(empty)light or dark, set when the device opens. Empty leaves the device as it is.

Values support the usual placeholders (${MOBILE_DEVICE_ID:-}); see Configuration.

Device selection​

deviceId must match exactly one online device of the platform; otherwise the deviceName regex must; otherwise exactly one online device of the platform must exist. Zero or several matches fail with DeviceSelectionException, listing the devices mobilecli reported.

Device pool (parallel runs)​

List the devices in devices: [id1, id2], or set pool: true to use every online device of the platform that matches deviceName. Each test gets a free device; when all are in use it waits up to reserveMs, then fails with MobileTimeoutException.

  • Run at most as many parallel mobile workers as there are devices.
  • devices cannot be combined with deviceId or pool; pool cannot be combined with deviceId.
  • Offline ids in devices are skipped with a warning.
  • The reservation is per JVM: separate JVMs or machines sharing devices are not coordinated.

App reset​

relaunch terminates and launches bundleId before each test; clearData clears its data and launches it; none leaves it alone. Except with none, the app is terminated after the test. Use none when tests continue from each other's state (for example a login that should survive).

Server auto-start​

When serverUrl is a loopback address (localhost, 127.*, ::1) and nothing answers, TestFly runs <mobilecliPath> server start --listen <host:port>:

  • once per endpoint and JVM; parallel tests wait for the same server, and a failed start makes later tests fail fast with the same error;
  • output goes to target/mobilecli-autostart.log;
  • it waits up to timeouts.serverStartMs for the server to answer;
  • the server is stopped when the JVM exits.

A server that already answers is used as is and never stopped. Remote servers are never started. Set autoStartServer: false to require a running server. The mobilecli agent (iOS only) is not installed automatically; install it once per device (mobilecli agent install --device <id>).

Screen recording​

With recordVideo: failures or always, every mobile test records the screen from the moment its device opens:

  • failures: a failed test keeps its video as target/reports/videos/<test>_mobile_<time>.mp4 and logs a "Device recording" step; a passed test's video is deleted.
  • always: every video is kept there; outside a test runner the file is named after the device.
  • mobilecli writes the file, so recording works with a local server (the default loopback serverUrl). If a device or platform cannot record, a warning is logged and the test runs without a video.

Record by hand with device().startRecording(path) and device().stopRecording().

iOS and Android in one config​

Give each platform its own block under mobile:; the values it leaves out come from the shared block. Each test picks its platform with @MobileTest(platform = …) next to the engine's @Test (a method's value wins over its class's). Tests without one run on mobile.platform.

mobile:
platform: ios # used by tests without @MobileTest(platform = …)
alerts: dismiss # shared
app:
reset: relaunch
ios:
deviceId: ${IOS_UDID:-}
app: { bundleId: com.example.ios }
android:
deviceId: ${ANDROID_AVD:-}
app: { bundleId: com.example.android }
public class LoginTest extends BaseMobileTest {
@Test
@MobileTest(platform = MobilePlatform.IOS)
public void loginOnIos() { ... }

@Test
@MobileTest(platform = MobilePlatform.ANDROID)
public void loginOnAndroid() { ... }
}

A platform block takes deviceId, deviceName, devices and app (bundleId, install, reset). A run with both platforms needs a simulator and an emulator (or devices) online. Cucumber scenarios use mobile.platform.

Profiles​

Keep mobile settings in a profile, src/test/resources/testfly-<name>.yml, and select it with -Dtestfly.profile=<name>. One profile per app and platform keeps the same tests running on iOS and Android:

mvn test -Dtestfly.profile=myapp-ios     -Dtest=LoginTest
mvn test -Dtestfly.profile=myapp-android -Dtest=LoginTest

A profile with a mobile: block needs no browser, execution or timeouts block: missing web values get inert defaults (headless local Chrome, http://localhost, 10 s / 30 s) and values you set are kept. The examples testfly-mobile-ios.yml, testfly-mobile-android.yml and testfly-mobile-login.yml show a complete profile.

Security​

mobilecli has no authentication, so only loopback addresses are accepted. A remote server needs allowRemote: true and an https:// URL, for example mobilecli behind a TLS-terminating, authenticating proxy or an SSH tunnel; send its credentials with headers and an environment placeholder. Never commit credentials: test accounts belong in environment variables.