There are three main ways to interact with UI elements:

- **Finders** let you select one or multiple elements (or*nodes*in the semantics tree) to make assertions or perform actions on them.
- **Assertions**are used to verify that the elements exist or have certain attributes.
- **Actions**inject simulated user events on the elements, such as clicks or other gestures.

Some of these APIs accept a[`SemanticsMatcher`](https://developer.android.com/reference/kotlin/androidx/compose/ui/test/SemanticsMatcher)to refer to one or more*nodes*in the semantics tree.
| **Note:** Testing a Compose UI is different from testing a view-based UI. The view-based UI toolkit clearly defines what a view is. A view occupies a rectangular space and has properties, like identifiers, position, margin, and padding. In Compose, because only some composables*emit*UI into the UI hierarchy, you need a different approach to matching UI elements.

### Finders

You can use[`onNode`](https://developer.android.com/reference/kotlin/androidx/compose/ui/test/SemanticsNodeInteractionsProvider#onNode(androidx.compose.ui.test.SemanticsMatcher,kotlin.Boolean))and[`onAllNodes`](https://developer.android.com/reference/kotlin/androidx/compose/ui/test/SemanticsNodeInteractionsProvider#onAllNodes(androidx.compose.ui.test.SemanticsMatcher,kotlin.Boolean))to select one or multiple nodes respectively, but you can also use convenience finders for the most common searches, such as[`onNodeWithText`](https://developer.android.com/reference/kotlin/androidx/compose/ui/test/package-summary#(androidx.compose.ui.test.SemanticsNodeInteractionsProvider).onNodeWithText(kotlin.String,kotlin.Boolean,kotlin.Boolean,kotlin.Boolean)), and[`onNodeWithContentDescription`](https://developer.android.com/reference/kotlin/androidx/compose/ui/test/package-summary#(androidx.compose.ui.test.SemanticsNodeInteractionsProvider).onNodeWithContentDescription(kotlin.String,kotlin.Boolean,kotlin.Boolean,kotlin.Boolean)). You can browse the complete list in the[Compose Testing cheat sheet](https://developer.android.com/develop/ui/compose/testing-cheatsheet).

#### Select a single node

    composeTestRule.onNode(<<SemanticsMatcher>>, useUnmergedTree = false): SemanticsNodeInteraction

    // Example
    composeTestRule
        .onNode(hasText("Button")) // Equivalent to onNodeWithText("Button")

#### Select multiple nodes

    composeTestRule
        .onAllNodes(<<SemanticsMatcher>>): SemanticsNodeInteractionCollection

    // Example
    composeTestRule
        .onAllNodes(hasText("Button")) // Equivalent to onAllNodesWithText("Button")

#### Unmerged tree

Some nodes merge the semantics information of their children. For example, a button with two text elements merges the text element labels:  

    MyButton {
        Text("Hello")
        Text("World")
    }

From a test, use[`printToLog()`](https://developer.android.com/reference/kotlin/androidx/compose/ui/test/package-summary#(androidx.compose.ui.test.SemanticsNodeInteraction).printToLog(kotlin.String,kotlin.Int))to show the semantics tree:  

    composeTestRule.onRoot().printToLog("TAG")

This code prints the following output:  

    Node #1 at (...)px
     |-Node #2 at (...)px
       Role = 'Button'
       Text = '[Hello, World]'
       Actions = [OnClick, GetTextLayoutResult]
       MergeDescendants = 'true'

If you need to match a node of what would be the*unmerged* tree, you can set`useUnmergedTree`to`true`:  

    composeTestRule.onRoot(useUnmergedTree = true).printToLog("TAG")

This code prints the following output:  

    Node #1 at (...)px
     |-Node #2 at (...)px
       OnClick = '...'
       MergeDescendants = 'true'
        |-Node #3 at (...)px
        | Text = '[Hello]'
        |-Node #5 at (83.0, 86.0, 191.0, 135.0)px
          Text = '[World]'

The`useUnmergedTree`parameter is available in all finders. For example, here it's used in an`onNodeWithText`finder.  

    composeTestRule
        .onNodeWithText("World", useUnmergedTree = true).assertIsDisplayed()

### Assertions

Check assertions by calling`assert()`on the[`SemanticsNodeInteraction`](https://developer.android.com/reference/kotlin/androidx/compose/ui/test/SemanticsNodeInteraction)returned by a finder with one or multiple matchers:  

    // Single matcher:
    composeTestRule
        .onNode(matcher)
        .assert(hasText("Button")) // hasText is a SemanticsMatcher

    // Multiple matchers can use and / or
    composeTestRule
        .onNode(matcher).assert(hasText("Button") or hasText("Button2"))

You can also use convenience functions for the most common assertions, such as[`assertExists`](https://developer.android.com/reference/kotlin/androidx/compose/ui/test/SemanticsNodeInteraction#assertExists(kotlin.String)),[`assertIsDisplayed`](https://developer.android.com/reference/kotlin/androidx/compose/ui/test/SemanticsNodeInteraction#(androidx.compose.ui.test.SemanticsNodeInteraction).assertIsDisplayed()), and[`assertTextEquals`](https://developer.android.com/reference/kotlin/androidx/compose/ui/test/SemanticsNodeInteraction#(androidx.compose.ui.test.SemanticsNodeInteraction).assertTextEquals(kotlin.Array,kotlin.Boolean)). You can browse the complete list in the[Compose Testing cheat sheet](https://developer.android.com/develop/ui/compose/testing-cheatsheet).

There are also functions to check assertions on a collection of nodes:  

    // Check number of matched nodes
    composeTestRule
        .onAllNodesWithContentDescription("Beatle").assertCountEquals(4)
    // At least one matches
    composeTestRule
        .onAllNodesWithContentDescription("Beatle").assertAny(hasTestTag("Drummer"))
    // All of them match
    composeTestRule
        .onAllNodesWithContentDescription("Beatle").assertAll(hasClickAction())

### Actions

To inject an action on a node, call a`perform...()`function:  

    composeTestRule.onNode(...).performClick()

| **Note:** You cannot chain actions inside a perform function. Instead, make multiple`perform...()`calls.

Here are some examples of actions:  

    performClick(),
    performSemanticsAction(key),
    performKeyPress(keyEvent),
    performGesture { swipeLeft() }

You can browse the complete list in the[Compose Testing cheat sheet](https://developer.android.com/develop/ui/compose/testing-cheatsheet).

### Matchers

A variety of matchers are available for testing your Compose code.

#### Hierarchical matchers

Hierarchical matchers let you go up or down the semantics tree and perform matching.  

    fun hasParent(matcher: SemanticsMatcher): SemanticsMatcher
    fun hasAnySibling(matcher: SemanticsMatcher): SemanticsMatcher
    fun hasAnyAncestor(matcher: SemanticsMatcher): SemanticsMatcher
    fun hasAnyDescendant(matcher: SemanticsMatcher):  SemanticsMatcher

Here are some examples of these matchers being used:  

    composeTestRule.onNode(hasParent(hasText("Button")))
        .assertIsDisplayed()

#### Selectors

An alternative way to create tests is to use*selectors*which can make some tests more readable.  

    composeTestRule.onNode(hasTestTag("Players"))
        .onChildren()
        .filter(hasClickAction())
        .assertCountEquals(4)
        .onFirst()
        .assert(hasText("John"))

You can browse the complete list in the[Compose Testing cheat sheet](https://developer.android.com/develop/ui/compose/testing-cheatsheet).

## Additional Resources

- **[Test apps on Android](https://developer.android.com/training/testing)**: The main Android testing landing page provides a broader view of testing fundamentals and techniques.
- **[Fundamentals of testing](https://developer.android.com/training/testing/fundamentals):**Learn more about the core concepts behind testing an Android app.
- **[Local tests](https://developer.android.com/training/testing/local-tests):**You can run some tests locally, on your own workstation.
- **[Instrumented tests](https://developer.android.com/training/testing/instrumented-tests):**It is good practice to also run instrumented tests. That is, tests that run directly on-device.
- **[Continuous integration](https://developer.android.com/training/testing/continuous-integration):**Continuous integration lets you integrate your tests into your deployment pipeline.
- **[Test different screen sizes](https://developer.android.com/training/testing/different-screens):**With some many devices available to users, you should test for different screen sizes.
- **[Espresso](https://developer.android.com/training/testing/espresso)**: While intended for View-based UIs, Espresso knowledge can still be helpful for some aspects of Compose testing.