Developing UI tests for an Android application (Espresso)

NOVASOLUTIONS.TECHNOLOGY is engaged in the development, support and maintenance of iOS, Android, PWA mobile applications. We have extensive experience and expertise in publishing mobile applications in popular markets like Google Play, App Store, Amazon, AppGallery and others.
Development and support of all types of mobile applications:
Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1 servicesAll 1735 services
Developing UI tests for an Android application (Espresso)
Medium
~3-5 business days
FAQ
Our competencies:
Development stages
Latest works
  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1050
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    445

UI Test Development for Android Application (Espresso)

Espresso is instrumental UI test framework from Google, built into Android SDK. Runs in same process as app, giving advantage: UI thread synchronization automatic. Espresso knows when app is "busy" — unlike UIAutomator, doesn't need sleep() between actions.

Basics and Critical Nuances

Basic Espresso test structure: onView(matcher).perform(action).check(assertion).

@Test
fun loginWithValidCredentials_navigatesToHome() {
    onView(withId(R.id.emailInput))
        .perform(typeText("[email protected]"), closeSoftKeyboard())
    onView(withId(R.id.passwordInput))
        .perform(typeText("password123"), closeSoftKeyboard())
    onView(withId(R.id.loginButton))
        .perform(click())
    onView(withId(R.id.homeTitle))
        .check(matches(isDisplayed()))
}

Most common reason for flaky tests — IdlingResource. If app does async operation (Retrofit, Coroutine), Espresso doesn't know and tries finding next element before operation completes. Solution — register IdlingResource:

// For OkHttp/Retrofit
val idlingResource = OkHttpIdlingResource.create("okhttp", okHttpClient)
IdlingRegistry.getInstance().register(idlingResource)

For coroutines — IdlingCoroutineDispatcher or EspressoIdlingResource from Google.

Compose UI Testing

If project uses Jetpack Compose, Espresso approach replaced with ComposeTestRule:

@get:Rule
val composeTestRule = createAndroidComposeRule<MainActivity>()

@Test
fun loginScreen_showsErrorOnInvalidEmail() {
    composeTestRule.onNodeWithTag("emailInput")
        .performTextInput("invalid-email")
    composeTestRule.onNodeWithTag("loginButton")
        .performClick()
    composeTestRule.onNodeWithText("Неверный формат email")
        .assertIsDisplayed()
}

testTag in Compose — analog of accessibilityIdentifier in iOS. Mandatory to set on all testable elements via Modifier.testTag("loginButton").

Hilt and DI in Instrumented Tests

If project uses Hilt, tests require HiltAndroidRule:

@HiltAndroidTest
class LoginScreenTest {
    @get:Rule(order = 0)
    val hiltRule = HiltAndroidRule(this)

    @get:Rule(order = 1)
    val composeTestRule = createAndroidComposeRule<MainActivity>()

    @BindValue
    val authRepository: AuthRepository = FakeAuthRepository()

    @Before
    fun init() { hiltRule.inject() }
}

@BindValue allows substituting real repository with fake without changing main code — test doesn't depend on network or database.

Robot Pattern (Page Object Analog)

class LoginRobot(private val composeTestRule: AndroidComposeTestRule<*, *>) {
    fun enterEmail(email: String) = apply {
        composeTestRule.onNodeWithTag("emailInput").performTextInput(email)
    }
    fun enterPassword(password: String) = apply {
        composeTestRule.onNodeWithTag("passwordInput").performTextInput(password)
    }
    fun clickLogin() = apply {
        composeTestRule.onNodeWithTag("loginButton").performClick()
    }
    fun assertHomeVisible() {
        composeTestRule.onNodeWithTag("homeScreen").assertIsDisplayed()
    }
}

// Test reads as scenario
@Test
fun validLogin_showsHome() {
    LoginRobot(composeTestRule)
        .enterEmail("[email protected]")
        .enterPassword("pass123")
        .clickLogin()
        .assertHomeVisible()
}

CI: Firebase Test Lab

Local emulator sufficient for development, but before release — Firebase Test Lab with real devices:

- name: Run Espresso tests on Firebase Test Lab
  run: |
    gcloud firebase test android run \
      --type instrumentation \
      --app app/build/outputs/apk/debug/app-debug.apk \
      --test app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk \
      --device model=Pixel8,version=34 \
      --device model=GalaxyS23,version=33

Results — Logcat, screenshots on failure, video of run — saved to Google Cloud Storage.

Testing Scope

Critical flows: login/registration, payment, main user path. Edge cases: deep link when not logged in, push notification tap, return from background. Accessibility: TalkBack via UIAutomator + AccessibilityChecks from Google (AccessibilityChecks.enable() in setUp()).

Timeframe: 3–5 days for basic suite of critical flows with Robot pattern, Hilt integration and CI on Firebase Test Lab.