Maestro vs Appium for Android UI testing
i run Android phones for a living, and a lot of my week is spent making sure an app on a real device does what it is supposed to do after a tap, a scroll and a login. two tools keep coming up when people ask me how to automate that: Maestro and Appium. they solve the same problem from opposite ends. Maestro gives you a YAML file and a command line. Appium gives you a WebDriver server and a full programming language.
Maestro is the one i reach for when i want a flow running in ten minutes and readable by someone who does not write code. Appium is the one i reach for when the test needs real logic, a language my team already writes, or a device setup that is not a single phone on a USB cable. the mistake i see most is picking Appium because it is the famous one, then spending a week on setup for a flow that is twelve taps long.
here is the verdict per use case, and the reasoning is below. small team with a mobile app and no test engineer: Maestro. a QA team with Java, Python or JavaScript skills and a large existing suite: Appium. smoke tests on every pull request: Maestro, narrowly. anything that has to mix device control, API calls and custom assertions in one test: Appium. i have not run a controlled benchmark between them and i am not going to invent numbers, so everything below is from operating both and from reading the official docs.
TL;DR comparison table
| Maestro | Appium | |
|---|---|---|
| test format | YAML flows | WebDriver code in Java, Python, JavaScript, Ruby, C# and others |
| licence and price | open source CLI, free. Maestro Cloud is a paid hosted service (check the vendor pricing page, plans change) | open source, free. you pay for your own devices, or a third party device cloud |
| platforms | Android, iOS, plus web support | Android, iOS, desktop and more through drivers |
| Android engine | on-device driver started by the CLI over adb | UiAutomator2 driver (Espresso driver also exists) |
| setup effort | install the CLI, have Java and adb, run a flow | Node.js, the Appium server, a driver, the Android SDK, a client library, capabilities |
| flakiness handling | built in waiting and retry behaviour for taps and assertions | you write explicit waits yourself |
| logic and branching | limited, with JavaScript hooks and conditions | anything your language can do |
| support | open source community, docs, Maestro Cloud vendor support | large community, many integrations, no vendor support unless you buy it elsewhere |
| target user | developers, small teams, mobile QA without a coding background | test automation engineers, larger QA orgs, teams with existing suites |
Maestro at a glance
Maestro is an open source mobile UI testing framework from mobile.dev. you describe a user journey in a YAML file, and the CLI runs it against an emulator or a connected phone. the official docs live at docs.maestro.dev, and that is where i checked the command names below.
a flow looks like this:
appId: com.example.app
---
- launchApp
- tapOn: "Log in"
- tapOn: "Email"
- inputText: "[email protected]"
- tapOn: "Password"
- inputText: "not-a-real-password"
- tapOn: "Submit"
- assertVisible: "Welcome back"
the commands in that file (launchApp, tapOn, inputText, assertVisible) are standard Maestro commands. you run it with maestro test flow.yaml. there is also maestro studio, which opens a local inspector in the browser where you can click elements and have commands written for you.
install on macOS and Linux is the curl one liner from the docs, and it needs Java installed. on Windows the docs describe a different route, which i will cover under setup. the install steps have changed before, so check the docs rather than copying mine.
what i like in practice:
- the flow files are short enough to review in a pull request without opening an IDE
- you select elements by visible text, ids or accessibility labels, which is how a human describes the screen
- one flow can call another with
runFlow, so a login flow gets written once - it handles waiting for you more than most tools, which matters for the flakiness section later
what i do not like: the language is small on purpose. when i need a loop over an API response or a computed value, i am pushing JavaScript into a YAML file, and that is where it starts to feel awkward.
Appium at a glance
Appium is an open source automation server that speaks the WebDriver protocol. your test code, written in the language you prefer, sends commands to the Appium server, which hands them to a platform driver. for Android that is normally the UiAutomator2 driver, documented in the appium-uiautomator2-driver repository. the main docs are at appium.io.
since Appium 2, the server and drivers are separate installs. the basic sequence from the docs is:
npm install -g appium
appium driver install uiautomator2
appium
appium driver doctor uiautomator2 is the check i run after install to see what is missing from the Android side. as of October 2026 the current major line is Appium 3, and it needs a recent Node.js, so check the release notes for the exact minimum before you pin anything.
a test then looks like normal code. here is a Python sketch using the Appium Python client:
from appium import webdriver
from appium.options.android import UiAutomator2Options
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
options = UiAutomator2Options()
options.platform_name = "Android"
options.app = "/path/to/app-debug.apk"
driver = webdriver.Remote("http://127.0.0.1:4723", options=options)
wait = WebDriverWait(driver, 15)
wait.until(EC.element_to_be_clickable((AppiumBy.ACCESSIBILITY_ID, "Log in"))).click()
treat that as a shape, not a copy-paste target, since option names change between client versions. the point is that Appium gives you the whole language: fixtures, parametrised tests, API calls to seed data, database checks, retries, reports. it also gives you more ways to get it wrong.
Head-to-head
Setup and first run
Maestro wins the first hour. install the CLI, plug in a phone with USB debugging on, run maestro test. if the device is not showing up, the problem is almost always the phone, not Maestro. i have a whole post on fixing a greyed out USB debugging toggle on Android, and that one catches more people than any framework bug does. on Xiaomi and Redmi phones the next wall is usually a blocked install, covered in fixing INSTALL_FAILED_USER_RESTRICTED on Xiaomi and Redmi.
Windows is the weaker story for Maestro. the project’s docs have pointed Windows users toward WSL or a native setup with caveats, and WSL does not see USB devices without extra work. if your team is on Windows laptops, test the install before you commit.
Appium takes longer because you are assembling a stack. Node.js, the server, the driver, Android SDK platform tools on your path, ANDROID_HOME set, a client library in your language, a test runner, and a capabilities block that has to match your device. none of it is hard, but each piece is a place to lose an afternoon. after that, Appium is as stable as any other piece of infrastructure you maintain. someone on the team needs to own it.
verdict on setup: Maestro for speed, Appium for a stack you control end to end.
Writing and maintaining tests
a YAML flow is readable by a product manager. an Appium test is readable by an engineer. which of those matters depends on who maintains the suite in six months.
with Maestro, the common maintenance cost is selectors. text changes, copy changes, a button becomes an icon. you fix the YAML. with Appium the cost is the same selectors plus the page objects, helpers and fixtures you built around them. a mature Appium suite has more structure, which is good when you have fifty engineers and bad when you have one.
there is one Android specific thing i should mention. Appium on Android lets you use UiAutomator selectors directly, including UiSelector strings. if you are relying on those, read my note on whether UiSelector is deprecated in Android’s UI Automator first. Maestro hides the selector layer from you, which is a benefit until you need something it does not expose.
Capabilities
Appium can do more because it is a general automation server. a few examples that come up in real work:
- running adb shell commands from a test, which needs the server started with an explicit flag such as
appium --allow-insecure=uiautomator2:adb_shell, because the server blocks it by default - driving system UI like notification shade, permission dialogs and settings screens
- mixing UI steps with API calls, database setup and file checks in the same test
- controlling a hybrid app by switching context into a WebView
Maestro covers the common cases well: launching apps, taps, text entry, scrolling until something is visible (scrollUntilVisible), waiting for a condition (extendedWaitUntil), clearing state, granting permissions, and screenshots. it can also launch a different app mid flow, which handles most of what people mean by “cross app”.
the gap shows up when a test needs state from outside the device. Maestro can run scripts, but you are working around the tool. for the platform level limits both tools sit on top of, can one Android app control another through UI Automator explains why some of this is restricted by Android itself.
Flakiness handling
flaky tests are the real cost of UI automation, so this axis matters more than the feature list.
Maestro’s docs describe built in tolerance for flakiness and for UI loading time. in practice that means a tapOn will wait and retry for the element to appear instead of failing on the first frame where the screen is not ready, and you do not scatter sleeps through the file. that removes the single most common cause of flaky tests in my experience, which is a test that is faster than the app.
Appium gives you the tools and leaves the discipline to you. implicit waits, explicit waits with WebDriverWait, custom polling, retries at the test runner level. a well written Appium suite can be very stable. a badly written one has time.sleep(5) everywhere and fails on a slow CI machine. the framework does not stop you.
neither tool fixes flakiness caused by the app itself: animations that never finish, network calls to a staging server that is down, a login that sends an SMS code. those need fixes in the test environment, such as test accounts, mocked backends or a debug build with animations off. the phone matters too, so i keep test phones on a fixed OS image, plugged in, with animations disabled.
CI and scale
Maestro runs headless from a CI job: boot an emulator or attach a device, run maestro test against a folder of flows. the CLI can write JUnit style output with --format junit and --output, which most CI systems understand. Maestro Cloud is the hosted option for running many flows in parallel on devices you do not own, and it is paid. check the vendor’s pricing page for current plans, since i would be guessing at numbers.
Appium on CI is the same pattern with more parts: start the server, start the emulator, run the test runner. you get the full reporting ecosystem of your language, whether that is pytest, JUnit, Mocha or something else. for parallel runs you run multiple Appium servers on different ports with different device ids, or use a grid.
for real hardware, the limit is the host, not the framework. if you plan to run many phones from one machine, read host limits when running many Android phones before you buy hubs. USB bandwidth, power and adb server stability all bite earlier than people expect.
if your CI produces a test only APK, installing a test only APK with adb install -t covers the flag, whichever framework launches the app afterwards.
Where each one breaks down
Maestro breaks down when the test needs programming. long conditional logic, data driven tests with many parameters, anything that needs to talk to a backend in the middle of a flow. you can do some of it, and it gets ugly fast. it can also be a poor fit if your team has an existing suite in another framework and no reason to migrate.
Appium breaks down on the human side. the setup is heavier, the learning curve is steeper, and the suite needs an owner. i have also seen Appium projects rot when the one person who understood the driver versions left. version drift between the server, the driver, the client library and the Android OS is a real maintenance cost. as of October 2026 i would pin versions in a lockfile and upgrade deliberately.
both tools can fail on apps that actively fight automation. i am not going to cover ways around that: automate apps you own or are authorised to test, using a debug or staging build.
Use case verdicts
Smoke tests on every pull request
winner: Maestro. a ten flow smoke suite that logs in, opens the main screens and checks that nothing crashes is exactly what the tool is for. writing it takes an afternoon, and anyone on the team can read the result.
A large regression suite maintained by QA engineers
winner: Appium. when you have hundreds of tests, shared fixtures, data driven cases and engineers who already write Java or Python, the structure of a real programming language pays off.
Mixing device control with backend checks
winner: Appium. if a test has to create a user through an API, drive the app, then verify a database row, you want one language doing all three. Maestro can be bent to it, but you will feel the bend.
Do you need both, or something else?
this is not a Maestro versus Appium question, but it comes up. for logic inside the app, instrumented tests are faster and more reliable than any black box UI tool. i wrote about whether you need both instrumented Android tests and Appium in one project, and the short answer is that they cover different layers. the same reasoning applies to Maestro. use instrumented tests for components and logic, and a black box tool for a handful of end to end journeys.
Testing on a real phone with a Singapore mobile connection
winner: it depends, and it is mostly a hardware question. both tools run fine on a real device. if you need a real Android phone on a Singapore mobile network, for example to check how an app behaves for Singapore users, you can either keep a phone on your desk or rent one. cloudf.one rents real Android phones in Singapore on dedicated hardware, each with a persistent Singapore mobile IP, controlled from the browser. it is Singapore only. there is no self service adb on it: adb and Appium reach a rented phone only through a WireGuard tunnel that we set up on request by email to [email protected]. if you only need to drive the UI by hand, the browser control is enough, and if you need scripted runs, ask us about the tunnel first. cloudf.one is the only place i mention it, and if you are testing from outside Singapore and location does not matter to your app, you do not need it.
Who should pick Maestro
- a solo developer or small team that wants end to end tests running this week
- mobile QA people who know the product well but do not write code every day
- teams that want flows that double as documentation of user journeys
Who should pick Appium
- teams with test automation engineers and an existing suite in Java, Python, JavaScript, Ruby or C#
- projects that need custom logic, API calls, database checks or complex data in the same test
- organisations that already run Selenium and want one mental model across web and mobile
- teams that need to drive system UI, hybrid app WebViews or unusual device setups
Verdict overall
there is no single winner, and i am saying that because it is true, not to dodge. Maestro is the better default for most small teams starting out on Android UI testing, because it removes the setup and flakiness tax that kills a lot of test suites before they get useful. Appium is the better choice once you have the people and the requirements to justify a general purpose automation server.
if i were starting a new Android project today with one or two developers, i would write the first ten journeys in Maestro, keep them in the repo, run them in CI, and add instrumented tests for the logic underneath. if the project grew a QA team and the flows outgrew YAML, i would move the complex ones to Appium and keep the simple ones where they are. run your most annoying real flow in each and see which one you would rather maintain. more Android automation notes are collected on the blog.
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-10-08.