How to Write Android Tests with Appium
Write your first Android test with Appium and UiAutomator2. Set up an emulator or device, run a Python test, and troubleshoot common setup issues.
To write an Android test with Appium, install the Appium server and its UiAutomator2 driver, make an Android emulator or development-enabled device visible to the Android Debug Bridge (ADB), then create a session, find an element, perform an action, and end the session. This walkthrough uses Python and Appium’s official Python client; Java, Ruby, and .NET clients are also available, and integrations include WebdriverIO, Nightwatch.js, and Robot Framework.
1. Prepare Appium and Android
Appium uses platform drivers to automate devices. UiAutomator2 is the official Android driver and supports native, hybrid, and web automation modes. Follow the UiAutomator2 setup guide for current requirements; driver and Android SDK requirements can change.
Install the prerequisites
- Install Node.js and npm, then install the Appium server:
npm install --global appium - Install the Android SDK Platform and Android SDK Platform-Tools. Set
ANDROID_HOMEto your SDK directory and make the SDK tools available in your shell’sPATH. - Install a Java Development Kit (JDK) and set
JAVA_HOME. The current UiAutomator2 guidance names JDK 9 for the most recent Android API levels and JDK 8 otherwise. Check the live driver documentation for the version and API level you use. - Choose an Android Virtual Device (AVD) in Android Studio’s Device Manager, or connect a physical Android device configured for development with USB debugging enabled.
Appium’s CLI manages the server and extensions such as drivers. The relevant subcommands include server and driver; running appium starts the server with its default local endpoint.
2. Start and verify an Android target
For a physical device, connect it over USB and accept its debugging prompt. For an emulator, create an AVD and launch it. In either case, check that ADB can see the target:
adb devices
A connected target should appear in the output. A physical device may show as unauthorized until you unlock it and accept the authorization prompt. An emulator must be fully started before you create an Appium session.
Install UiAutomator2 and check its prerequisites:
appium driver install uiautomator2
appium driver doctor uiautomator2
The session must identify the Android platform and use UiAutomator2 as its automation name. The doctor command can help identify missing environment setup before you debug a test.
3. Install the Python client and write a test
Create a project directory, make a virtual environment, and install the official Appium Python client:
python -m venv .venv
# macOS or Linux:
source .venv/bin/activate
# Windows PowerShell:
# .venv\Scripts\Activate.ps1
python -m pip install Appium-Python-Client
Save the following as test_settings.py. It opens Android’s built-in Settings app, finds the Apps entry, clicks it, and always closes the session.
from appium import webdriver
from appium.options.android import UiAutomator2Options
from appium.webdriver.common.appiumby import AppiumBy
options = UiAutomator2Options()
options.platform_name = "Android"
options.automation_name = "UiAutomator2"
options.app_package = "com.android.settings"
options.app_activity = ".Settings"
# The Appium server must be running at this address.
driver = webdriver.Remote(
"http://localhost:4723",
options=options,
)
try:
apps_item = driver.find_element(
AppiumBy.ACCESSIBILITY_ID,
"Apps",
)
apps_item.click()
print("Opened the Apps settings screen")
finally:
driver.quit()
What the test does
UiAutomator2Optionsbuilds the Android session capabilities.platform_nameselects Android,automation_nameselects the installed driver, andapp_packageplusapp_activityidentify the app to launch.webdriver.Remoteconnects the client to the Appium server and starts a session on the available target.find_elementlocates an element by its accessibility identifier. Stable accessibility identifiers are usually preferable in your own app; if the UI exposes none, choose a locator supported by the client and inspect the screen’s element tree.click()performs the interaction. Add assertions against the resulting screen or app state to turn an interaction script into a test that can fail meaningfully.finallyensuresquit()releases the session even if lookup or interaction raises an error.
This example targets the built-in Settings app, so it does not need an app file. To launch your app from an APK, use the driver’s app capability with the APK path instead of specifying the installed app’s package and activity. Keep the APK path valid on the machine running the Appium server. For an already installed app, use its package and launch activity. Consult the driver documentation for capabilities specific to your app and driver version.
4. Run the test
Open a separate terminal and start the Appium server:
appium
Leave it running, with the emulator or device connected. In the project terminal, run:
python test_settings.py
The Python client connects to http://localhost:4723, the endpoint used by the official quickstart example. If you change the server address or port, make the same change in webdriver.Remote. Keep the server terminal open to see session and driver logs when a test fails.
5. Choose a target and client that fit your project
Emulator or physical device?
| Target | Use it when | Setup checks |
|---|---|---|
| AVD emulator | You need a convenient Android target and do not need access to physical hardware for this test. | Launch the AVD and confirm it appears in adb devices. |
| Physical device | The test requires a real device or hardware-specific behavior. | Enable USB debugging, accept the computer’s authorization prompt, and confirm the device appears as authorized in adb devices. |
Appium supports both paths; the appropriate choice depends on what your test needs to exercise. A physical phone is optional.
Choose the client language
Use the client that fits your team and test project. The official Appium client ecosystem lists Java, Python, Ruby, and .NET. It also lists integrations such as WebdriverIO and Nightwatch.js, plus Robot Framework. Install and configure the client for your chosen language, but keep the session lifecycle the same: connect, locate, act, assert, and quit.
6. Troubleshooting
| Symptom | Likely cause | What to check or fix |
|---|---|---|
| Appium reports that no driver can handle the session | UiAutomator2 is not installed, or the automation name is missing or misspelled. | Run appium driver install uiautomator2; set automation_name to UiAutomator2; confirm the driver is installed with the Appium CLI. |
| The session cannot find an Android device | The emulator is stopped, ADB cannot see the target, or a physical device is unauthorized. | Run adb devices. Start the AVD, reconnect the device, unlock it, and accept its USB debugging prompt. Resolve any unauthorized status before retrying. |
| The driver doctor reports missing Android tools | The SDK or platform tools are missing, or the environment points to the wrong SDK directory. | Install Android SDK Platform and Platform-Tools, verify ANDROID_HOME, and ensure the SDK tools are on PATH. Run appium driver doctor uiautomator2 again. |
| UiAutomator2 cannot find Java or fails during setup | JAVA_HOME is unset or points to the wrong JDK, or the JDK version does not meet the current driver requirement. |
Set JAVA_HOME to the installed JDK and check the live UiAutomator2 setup page for the requirement matching your Android API and driver version. |
| Python reports connection refused | The Appium server is not running at the URL used by the test. | Start appium in another terminal and check that the client URL, host, and port match the server. |
| Python raises an import error for Appium | The package was installed into a different Python environment from the one running the test. | Activate the project virtual environment and run python -m pip install Appium-Python-Client using that same interpreter. |
| The app fails to launch | The package name, activity name, or APK path is incorrect for the target. | Verify the app identifiers and that the app is installed, or provide the correct APK path as the app capability. Check the Appium server log for the underlying launch error. |
| The element lookup times out or fails | The element is not present yet, its accessibility label differs, or the wrong screen opened. | Confirm the app reached the expected screen, inspect its available accessibility properties, and use the correct locator. For asynchronous screens, wait for a condition instead of assuming the element is immediately present. |
7. Reliability, speed, and cost
Test reliability starts with repeatable setup: use a known emulator or device, keep the Appium server and client pointed at the same endpoint, use stable app identifiers, and release every session with quit(). When an error occurs, preserve the Appium server output; it helps distinguish a connection problem from a driver, app-launch, or locator problem.
Keep tests focused on observable app behavior and avoid unnecessary fixed delays. Wait for a condition when an element or screen is expected to appear asynchronously. Emulator and device startup, app launch, and UI synchronization all contribute to execution time; there is no single runtime that applies to every app and target. Parallel runs require separate sessions and suitable target capacity, and should be introduced only after the basic test is stable.
The setup shown here uses open-source Appium components and an AVD or device you already have; the research sources do not establish a universal monetary cost or runtime. Device hardware, hosted device services, and CI infrastructure can add costs depending on your setup. A physical device is not a prerequisite for getting started.
8. Capture a screenshot of a web page from a test
Appium automates Android app interfaces. If a test workflow also needs a clean screenshot of a website, that is a separate capture task. You can manage a browser yourself or use ScreenshotNeo, a website screenshot API and MCP server for developers.
Or skip the browser setup
Make one GET request with the target URL to receive an image or PDF. The examples below request a WebP capture of Stripe; replace the target URL as needed. See the ScreenshotNeo API documentation for parameters and response details.
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://stripe.com \
-o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://stripe.com'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await import('node:fs/promises').then(async (fs) => {
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
});
ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed; response headers report the page verdict and billing status. Its MCP server gives AI agents tools to take screenshots, get page information, and capture PDFs. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.
Create a free ScreenshotNeo account to get 1,000 screenshots a month with no card.
FAQ
Do I need a physical Android phone to write an Appium test?
No. Appium can use an Android Virtual Device. Use a physical device when your test needs real hardware.
Does this example test my app?
The runnable example opens Android Settings so it has a built-in target. To test your app, provide its package and launch activity or point the session at its APK, then use locators and assertions for your app’s screens.
Can Appium automate Android web apps?
UiAutomator2 supports native, hybrid, and web automation modes. The example here demonstrates a native Settings screen; web automation needs the appropriate app and driver configuration.
Which Appium client should I choose?
Choose based on the language and tooling your project already uses. Official clients include Java, Python, Ruby, and .NET.
Where can I check whether my setup is supported?
Use the current UiAutomator2 setup guide and run appium driver doctor uiautomator2 to check local prerequisites.


