← all articles

Do you need both instrumented Android tests and Appium in one project?

A question that keeps coming up on Stack Overflow and in Android team standups: if you already have instrumented tests running through Android Studio, why also stand up a separate Appium suite that seems to do the same thing, tap buttons, check screens, assert text. Short answer: they solve different problems, and most teams that test Android apps at any real scale end up running both, not because someone got lazy about consolidating tooling, but because one genuinely can’t do the other’s job.

Picking the wrong split, or only running one, has a real cost. Either your CI takes fifteen minutes to check a two-line UI change, or your tests pass clean and the exact failure that shows up on a customer’s phone, say, an OAuth redirect into a banking app, never gets caught because nothing in your suite can follow the user across that process boundary. Worth working out the split before you build a whole pipeline around the wrong one.

what it is

Instrumented Android tests run inside, or directly alongside, your app’s own process on a device or emulator. They’re built with AndroidX Test, most often written with Espresso for view assertions or UI Automator for anything that touches system UI, and launched through Gradle’s connectedAndroidTest task. Android’s own testing docs describe them as tests that need an actual Android device or emulator because they depend on framework APIs and the app’s compiled resources. They have direct, synchronous access to your view hierarchy, which is why Espresso can wait on an idling resource instead of guessing with a sleep.

Appium is a separate, open source automation server that speaks the W3C WebDriver protocol, the same spec Selenium uses for browsers. On Android it drives the device from outside your app’s process, over adb, using a bootstrap component (UiAutomator2 in almost every setup I’ve seen) that translates WebDriver calls like findElement and click into UI Automator actions. It doesn’t need your test APK or your source. It needs the installed app and enough resource-ids or accessibility labels to find elements on screen. If you’re deciding between Espresso and UI Automator for the instrumented half of this, I wrote up the actual tradeoffs in espresso vs ui automator.

how it works

The mechanism differs more than the surface behavior suggests. An instrumented test gets compiled into a separate test APK, installed next to your app APK, and started with adb shell am instrument. Espresso then talks to your views directly inside that instrumented process, matching on onView and onData, synchronizing against the main thread’s message queue so it doesn’t need arbitrary waits. UI Automator, still part of AndroidX Test, works one level out: it walks the full device UI tree, including the notification shade, system dialogs, and other apps’ windows, because it isn’t tied to a single app’s process the way Espresso is.

Appium sits a layer further out again. An Appium server runs on your host machine (or a CI runner), and it forwards WebDriver commands over adb to that UiAutomator2 bootstrap app on the device, which then makes the same kind of UI Automator calls under the hood. So on Android, Appium for the most part wraps the framework you’d already use for cross-app instrumented tests, just behind an HTTP API and a client library in whatever language your test runner speaks, Python, Java, JavaScript. That extra hop is exactly why an Appium script can tap a share button in your app and then assert on a screen inside WhatsApp or Gmail in the same test, something a pure Espresso test can’t do because it never leaves your app’s process. If you want the deeper mechanics of one app driving another through the accessibility tree, I covered that separately in can one Android app control another through UI Automator.

why it matters

Four situations where the difference actually changes what you build.

Feedback speed on every pull request. Espresso tests inside a single activity or fragment run in seconds and don’t need a full device boot each time, which is why they belong in the loop that runs on every PR. An Appium suite that installs the app, boots UiAutomator2, and drives full journeys through the app is going to add minutes, not seconds, per run.

Cross-app and system flows. Payment SDKs that hand off to a banking app, OAuth redirects, share sheets, deep links from a notification. None of that lives inside your app’s process, so Espresso literally cannot assert on it. This is squarely UI Automator or Appium territory.

Testing apps you don’t own the source of. RPA-style automation, competitive monitoring, accessibility checks on a partner’s app. You can’t write an instrumented test against a package you don’t control, no source means no test APK to compile against. Appium only needs the installed app and its element identifiers, which is why it’s the tool for that job, provided it’s an app and device you’re actually authorized to test.

Real device behavior instead of emulator behavior. Emulators are consistent, which is also their limitation, they don’t reproduce a specific phone’s thermal throttling, its actual radio, or region-specific app behavior. If a client needs Appium hitting a real phone with a real Singapore-registered mobile connection rather than an emulator, that’s the specific gap cloudf.one fills, real Android phones on dedicated hardware in Singapore, each with its own persistent Singapore mobile IP, controlled from the browser. Worth knowing going in: there’s no self-service adb on those phones. Adb and Appium reach a rented phone only through a WireGuard tunnel that gets set up on request (email [email protected]), not something you can just switch on yourself.

common misconceptions

“Appium is UI Automator with extra steps, so you can drop Espresso.” I’d push back on this one. Espresso’s synchronous view access and idling resources are exactly what keeps single-app UI checks from flaking, and Appium’s extra network hop doesn’t remove that need, it just adds latency on top of it. Drop Espresso for Appium-only and you’ve usually just added flakiness, not removed complexity. Some of that flakiness has nothing to do with which tool you pick anyway, worth reading why Android UI tests are flaky before blaming the framework.

“Instrumented tests are ‘real,’ Appium tests are ‘fake’ because they go over a protocol.” Not really. Both eventually execute through the same on-device instrumentation. Appium’s WebDriver layer adds a network round trip, it doesn’t fake the interaction.

“Just replace Espresso entirely, Appium tests are more real-world.” I’ve seen teams try this and regret it. Boot time, app install, and driver startup on every test make Appium a bad fit for the fast, per-PR checks you want on every commit. Keep those in Espresso. Save Appium and UI Automator for the smaller set of true end-to-end and cross-app journeys where they’re the only option.

“Appium needs source access like instrumented tests do.” It doesn’t. It needs the app installed and enough resource-ids or accessibility labels to find things on screen, nothing from the codebase. That’s also the boundary to respect: automate only apps and devices you own or are explicitly authorized to test, and don’t use that black-box access to work around root detection, Play Integrity, or a platform’s anti-automation terms. That’s a different, much narrower conversation than the testing question here.

One honest gap on my end: I’ve mostly seen Appium on Android run through the UiAutomator2 driver, not the Espresso driver Appium also ships. So if your stack is on the Espresso driver specifically, some of what’s above about the extra network hop still holds, but I wouldn’t claim deep experience with that particular path.

where to go from here

A few directions worth reading next depending on which half of this you’re building out.

More explainers like this one are in the full archive.

Written by Xavier Fok

disclosure: this article may contain affiliate links. if you buy through them we may earn a commission at no extra cost to you. verdicts are independent of payouts. last reviewed by Xavier Fok on 2026-09-28.

free download
The adb and scrcpy command cheat sheet

The commands we reach for on a rack of real phones, on one printable page. Leave your email and we will also tell you when we publish a new guide, a few times a month at most.

from the team behind cloudf.one
Passes on the emulator, fails on a real phone?

cloudf.one rents real Android phones in Singapore that you control from the browser, each on a persistent Singapore mobile IP. Real hardware, a real OEM build and a real carrier network, without buying and racking the phones yourself.

test on a real phone →
read on
More from ADB Handbook

adb commands, scrcpy flags, automation frameworks, and why a test passes on one phone and fails on the next.

browse all articles →