Compose UI tests

Testing Mid-level Kotlin 2.0+ API 24+ Reviewed By Best Latest Apps

Fill the blank

Tap the Add button and check that one note shows.

@get:Rule val compose = createComposeRule()

@Test
fun addShowsNote() {
    compose.setContent { NotesTestScreen() }
    compose.onNodeWithText("Add").____()
    compose.onNodeWithText("Note 1").assertIsDisplayed()
}
Options
Hint 1 of 1

Actions on nodes start with perform.

Choose an answer, then open Show answer below to check it.

Show answer

Answer: A performClick

Correct. It sends a click to the node.

Why not the others?
  • B click. click() exists inside performTouchInput, not on the node.
  • C assertIsDisplayed. That asserts; it doesn't tap.
  • D invoke. Not a test action.

30-second answer

Use createComposeRule() (or createAndroidComposeRule for a real Activity), set content, then find nodes through the semantics tree with finders like onNodeWithText or onNodeWithTag, perform actions such as performClick(), and assert with assertIsDisplayed() or assertTextEquals(). Compose tests wait for idle automatically, so there are no sleeps.

Practise saying it · 30 s. No recording, just a timer

Explain Compose UI testing.

Say your answer out loud, then check which of these points you covered:

  • createComposeRule
  • Semantics finders and actions
  • Automatic idling
  • Test content with fake state

Deep dive

Test the stateless content composable with fake state; test one or two journeys with the real ViewModel.

Modifier.testTag for nodes without text; prefer finding by text or content description, which also checks accessibility.

mainClock.autoAdvance = false lets you step through animations.

Compose UI tests can run on Robolectric locally or on devices.

The screen under test Compile-checked · Kotlin 2.4.21
@Composable
fun NotesTestScreen() {
    var notes by remember { mutableStateOf(listOf<String>()) }
    Column {
        Button(onClick = { notes = notes + "Note ${notes.size + 1}" }) { Text("Add") }
        notes.forEach { Text(it) }
    }
}

Common mistakes

  • Using Thread.sleep to wait.
  • Test tags on everything instead of user-visible text.
  • Testing through the real network.

Senior take & follow-ups

Mention the semantics tree and automatic synchronisation.

Follow-up questions

Think of your answer first, then open the hint.

  1. Why prefer finding by text or contentDescription?

    Show hint

    It's how users and accessibility services find things.

  2. How do you control animations?

    Show hint

    Turn off mainClock.autoAdvance and advance manually.

Similar on iOS: UI tests with XCUITest XCUITest drives the app through accessibility; Compose tests query the semantics tree in-process.

Suggest a fix if something here is wrong or out of date.