Playwright: local emulator app install and use.app.buildPath
August 3, 2026 · View on GitHub
This applies to local Android / iOS runs using EmulatorProvider and EmulatorConfigBuilder (e.g. projects in tests/playwright.config.ts with device.provider: emulator / iOS simulator).
Summary
use.app.buildPath | Global setup | Appium capabilities (local emulator) |
|---|---|---|
Set (path to a local .apk or .app file) | Fails if the path does not exist. Then reinstalls from that path with CLI tools (so the disk artifact always wins over any existing install): Android adb uninstall (best-effort) + adb install; iOS xcrun simctl uninstall (best-effort) + xcrun simctl install. Requires Android use.app.packageName and use.device for adb targeting; iOS use.app.appId and use.device.name for the simulator. | Sets appium:app to that path for the session. |
| Unset | Does not install anything. Fails if the app is not already on the device/sim. | Omits appium:app. Android: uses appium:appPackage + appium:appActivity. iOS: appium:bundleId + use.device sim name / UDID. |
buildPath is the same field name used for remote URLs on BrowserStack. EmulatorProvider is intended for local paths: remote URLs are not a valid on-disk build for this flow.
Skip CLI reinstall
Set the environment variable SKIP_APP_REINSTALL so global setup does not run adb / xcrun simctl uninstall+install (useful to speed up local runs when the sim/emulator already has a good build).
- Skip reinstall:
true,1, oryes(case-insensitive) - Default (reinstall): unset, or
false,0, orno
Path validation for buildPath still runs. The Appium session can still use appium:app pointing at the same path; only the explicit uninstall+install step in EmulatorProvider.globalSetup is skipped. See .e2e.env.example.
fullReset and noReset (local emulator)
We keep Appium’s reset flags mild in EmulatorConfigBuilder:
appium:fullReset:falseappium:noReset:true
Reinstall / “clean” from buildPath is handled in globalSetup with adb / xcrun simctl, not by toggling fullReset, to avoid the flaky sim/emulator behavior seen with driver-driven full reset.
Note:
noReset: truefor the Appium session still means the driver is not asked to wipe app data on its own. AfterglobalSetup’s explicit uninstall+install, the app is freshly installed for that run.
Session reuse (local emulator)
Playwright Appium runs on emulator/simulator reuse one WDIO session per worker by default (APPIUM_SESSION_REUSE). Between tests, withFixtures({ restartDevice: true }) soft-reloads the app (clear data + launch + fixture bootstrap) without deleteSession.
- Disable reuse:
APPIUM_SESSION_REUSE=false - BrowserStack: reuse is always off
- Details: appium-smoke-testing.md
Android device targeting
For Android, the adb serial is resolved from use.device.name (AVD name) or use.device.udid — see resolveAndroidAdbUdid and the EmulatorConfig JSDoc in types.ts.
iOS device targeting
For iOS, using the DeviceName as iPhone 16 Pro can become problematic if different XCode versions are installed locally so the device UDID can be used along with the device name.
Example:
use: {
platform: Platform.IOS,
device: {
provider: ProviderName.SIMULATOR,
osVersion: '26.2',
name: 'iPhone 16 Pro',
udid: '<DEVICE_UDID>'
}
}
Get available Simulators:
$ xcrun simctl list devices available
Related code
reinstallLocalBuildFromPath—adb/simctlinstall helpers.EmulatorProvider.globalSetup— path check, then reinstall whenbuildPathis set; orisAppInstalled()when unset.EmulatorProvider.getDriver/EmulatorConfigBuilder.build— capabilities includingappium:appwhenbuildPathis set.- Worker session reuse —
sessionReuse.ts,driver.fixture.ts. - Soft reload —
softReloadApp.ts.