Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose an Android test by deciding what behavior you need to verify, where the test must run, and whether it stays inside your app. Use local JVM tests for fast, isolated logic checks; Espresso for View-based interfaces; Compose testing APIs for Compose UI; UI Automator for system or cross-app flows; and instrumented tests on an emulator or physical device when Android runtime behavior matters. Robolectric can run supported Android tests on the JVM. Kotlin works across these approaches—the test environment and UI toolkit determine which APIs fit.

Choose the test boundary and environment first

Android testing is not a choice between “unit tests” and “UI tests” alone. Decide whether the behavior needs Android itself, whether it crosses app boundaries, and which UI toolkit it exercises. Android’s testing fundamentals distinguish local tests, which run on a development machine or server, from instrumented tests, which run on an Android device or emulator.

What you need to test Good starting point Execution and boundary
Business logic that can be isolated Local JVM test Runs on the host machine; does not require a device.
Interaction with Android Views in your app Espresso Instrumented; exercises the app’s View UI.
Compose screen or component behavior Compose testing APIs Tests the Compose semantics model in an instrumented UI test.
Settings, launcher, or another installed app UI Automator Instrumented; can interact beyond your app, with additional synchronization considerations.
Supported Android behavior without a device Robolectric Runs supported tests locally on the JVM; it is not a substitute for every device-level check.
Framework, configuration, hardware, or device-specific integration Instrumented test on an emulator or physical device Runs against Android; choose a physical device when real hardware or a particular device configuration is material.

These are complementary layers, not mutually exclusive strategies. Keep inexpensive, focused logic checks local, and reserve device execution for behaviors that need the Android runtime or UI. Android’s UI testing guidance discusses the boundaries between UI tools and Robolectric.

Put Kotlin tests in the right source set

In an Android module, local tests normally live in src/test (commonly src/test/java, which can also contain Kotlin source files); instrumented tests belong in src/androidTest (commonly src/androidTest/java). The Android guidance on automating UI tests explains the distinction. The source set matters because it determines the test runtime and available dependencies: a local test runs on the host JVM, while an instrumented test is packaged and run on Android.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Instrumented JUnit 4 tests commonly use AndroidJUnitRunner. The runner executes them on devices and supports Android test libraries such as Espresso, UI Automator, and Compose testing. See the AndroidJUnitRunner documentation for setup and capabilities.

Test View interfaces with Espresso

For a View-based screen, Espresso provides APIs to find views, perform user-like actions, and assert the resulting UI. Its normal interaction model avoids direct activity and view access, which helps keep a test focused on observable behavior instead of implementation details. Espresso also coordinates with common app UI operations. Android’s Espresso basics walks through its interaction and assertion model.

A useful View test follows a user-visible path: locate a control, act on it, and assert what the user should see next. Keep the test’s purpose narrow enough that a failure identifies a behavior, not a long chain of unrelated setup. If the app starts work that Espresso cannot observe—such as an external network request—control that dependency or explicitly synchronize with it rather than relying on timing.

Test Compose interfaces through semantics

Compose tests interact with the semantics exposed by composables, not by assuming the traditional View hierarchy represents the screen. Use Compose finders or semantics matchers to identify content, perform actions, and assert outcomes. The official Compose testing APIs documentation covers finders, actions, and assertions.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Test at the scope that matches the behavior: a component test can verify a reusable control, while a larger screen test can verify meaningful interactions among components. For layout behavior, Compose testing supports configuration overrides, including dimensions and font scale, so a test can check how UI responds to changed inputs instead of depending only on one default setup. See Android’s Compose testing common patterns.

Use UI Automator when a flow leaves your app

Espresso and Compose testing are suited to your app’s UI; a flow that must operate Android settings, the launcher, or another installed app crosses that boundary. UI Automator is designed for interaction with system UI and other apps. That broader reach is useful for integration scenarios such as verifying a permission or settings journey, but system and cross-app transitions may need more deliberate synchronization than ordinary in-app UI actions. Android’s UI Automator guidance describes this role.

When Robolectric is a fit

Robolectric offers a local JVM route for supported Android tests, avoiding a device or emulator for those cases. It can be useful when a test needs Android behavior but faster host-side execution is desirable. Its coverage is not universal: use an instrumented test when the behavior depends on actual device or emulator execution, hardware, or configuration. Android’s UI testing overview identifies Robolectric alongside the Android UI testing options.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Make tests deterministic and synchronized

A test is only useful if its outcome reflects the behavior under test rather than network state, background timing, or system interruptions. Design app boundaries so tests can provide controlled dependencies—for example, an in-memory fake repository instead of a live network-backed repository. Android’s guidance on automating UI tests emphasizes architecture that supports deterministic test inputs.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Control external data: use stable test data and substitute external services where the test is not meant to verify those services.
  • Synchronize observable work: Espresso and Compose coordinate common UI work, but background database or network work may be outside their synchronization model. Add an appropriate synchronization mechanism when needed.
  • Account for animation: infinite animations or other ongoing work can prevent a test from reaching a stable state; control or adapt them for the test.
  • Reduce environmental noise: configure test devices so notifications or other system interruptions do not unexpectedly alter the flow.
  • Keep the scope intentional: test isolated components for focused behavior and larger flows when the interaction itself is important.

Android’s test stability guidance explains synchronization and sources of UI-test flakiness. Do not treat a sleep or arbitrary delay as a general synchronization strategy: it can make a test slower without proving the work has completed.

Decide whether to use an emulator or a physical device

A physical Android device is not required for every instrumented test: Android supports running those tests on emulators as well. Use an emulator for repeatable general UI and integration coverage; add real-device execution when the behavior depends on actual hardware or a specific device configuration. This lets the test boundary—not a blanket assumption—determine whether a device is needed. See Android testing fundamentals.

For configuration-change coverage, the Espresso Device API can trigger common changes such as rotation and unfolding in conjunction with Compose test rules. The documented setup is version-sensitive: Android’s Espresso Device API setup page lists Android Studio Iguana or newer, Android Gradle Plugin 8.3 or newer, Emulator 33.1.10 or newer, and a virtual device on API level 24 or newer. Treat these as the requirements stated on that page, and verify compatibility with the versions used by your project before adopting the workflow.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.