### Basic Compose UI Test Example Source: https://developer.android.com/develop/ui/compose/testing A typical UI test for Compose applications. This example demonstrates setting content, performing a click action, and asserting that an element is displayed. ```kotlin // file: app/src/androidTest/java/com/package/MyComposeTest.kt class MyComposeTest { @get:Rule val composeTestRule = createComposeRule() // use createAndroidComposeRule() if you need access to // an activity @Test fun myTest() { // Start the app composeTestRule.setContent { MyAppTheme { MainScreen(uiState = fakeUiState, /*...*/) } } composeTestRule.onNodeWithText("Continue").performClick() composeTestRule.onNodeWithText("Welcome").assertIsDisplayed() } } ``` -------------------------------- ### Apply Multiple Configuration Overrides Source: https://developer.android.com/develop/ui/compose/testing/common-patterns Combine multiple configuration overrides using `DeviceConfigurationOverride.then()` to test your composables under complex scenarios. This example demonstrates applying font scale and font weight adjustments simultaneously. ```kotlin composeTestRule.setContent { DeviceConfigurationOverride( DeviceConfigurationOverride.FontScale(1.5f) then DeviceConfigurationOverride.FontWeightAdjustment(200) ) { Text(text = "text with increased scale and weight") } } ``` -------------------------------- ### Using hasParent Matcher Source: https://developer.android.com/develop/ui/compose/testing/apis Example demonstrating how to use the `hasParent` matcher to find a node that has a specific parent. This is useful for asserting properties of elements within a known parent structure. ```kotlin composeTestRule.onNode(hasParent(hasText("Button"))) .assertIsDisplayed() ``` -------------------------------- ### Assert with Single Semantics Matcher Source: https://developer.android.com/develop/ui/compose/testing/apis Use the `assert` function with a single `SemanticsMatcher` to verify node properties. The `hasText` matcher is a common example. ```kotlin // Single matcher: composeTestRule .onNode(matcher) .assert(hasText("Button")) // hasText is a SemanticsMatcher ``` -------------------------------- ### Compose Test Synchronization Example Source: https://developer.android.com/develop/ui/compose/testing/synchronization Demonstrates a scenario where a test fails due to lack of recomposition when automatic synchronization is implicitly off or not triggered. The assertion `assertTrue(lastSeenValue == 1)` fails because the state change `myCounter.value = 1` does not trigger a UI recomposition until an explicit action like `composeTestRule.onNodeWithText("1").assertExists()` is called. ```kotlin import androidx.compose.runtime.mutableStateOf import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onNodeWithText import androidx.compose.material.Text import org.junit.Assert.assertTrue import org.junit.Test class SynchronizationTest { val composeTestRule = createComposeRule() @Test fun counterTest() { val myCounter = mutableStateOf(0) // State that can cause recompositions. var lastSeenValue = 0 // Used to track recompositions. composeTestRule.setContent { Text(myCounter.value.toString()) lastSeenValue = myCounter.value } myCounter.value = 1 // The state changes, but there is no recomposition. // Fails because nothing triggered a recomposition. assertTrue(lastSeenValue == 1) // Passes because the assertion triggers recomposition. composeTestRule.onNodeWithText("1").assertExists() } } ``` -------------------------------- ### Print Semantics Tree to Log Source: https://developer.android.com/develop/ui/compose/testing/debug Call `composeTestRule.onRoot().printToLog()` at any point in your test to print the semantics tree. This log contains valuable information for tracking down bugs. ```kotlin composeTestRule.onRoot().printToLog() ``` -------------------------------- ### Migrate to Compose Testing v2 APIs with AI Prompt Source: https://developer.android.com/develop/ui/compose/testing/migrate-v2 Use this prompt in Gemini within Android Studio to automate the migration to v2 of the Compose testing APIs. ```text Migrate to Compose testing v2 APIs using the official migration guide. ``` -------------------------------- ### Apply Forced Size Configuration Override Source: https://developer.android.com/develop/ui/compose/testing/common-patterns Use `DeviceConfigurationOverride.ForcedSize()` to simulate a specific screen size for your composable. This is useful for testing layouts that depend on available space without needing a physical device with that exact configuration. ```kotlin composeTestRule.setContent { DeviceConfigurationOverride( DeviceConfigurationOverride.ForcedSize(DpSize(1280.dp, 800.dp)) ) { MyScreen() // Will be rendered in the space for 1280dp by 800dp without clipping. } } ``` -------------------------------- ### Print Semantics Tree to Log Source: https://developer.android.com/develop/ui/compose/testing/apis Use `printToLog` to inspect the semantics tree of the UI. This is useful for debugging and understanding how semantics are merged. ```kotlin composeTestRule.onRoot().printToLog("TAG") ``` -------------------------------- ### Test Compose and View Interop with Espresso Source: https://developer.android.com/develop/ui/compose/testing/interoperability Use Espresso to interact with both native Android Views and Compose UI elements within a hybrid application. This snippet demonstrates checking the state of a TextView, performing an action on a Compose button, and verifying the updated state. ```kotlin import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.test.espresso.Espresso.onView import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.matcher.ViewMatchers.isDisplayed import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.ext.junit.runners.AndroidJUnit4 import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class InteropTest { @get:Rule val composeTestRule = createComposeRule() @Test fun androidViewInteropTest() { // Check the initial state of a TextView that depends on a Compose state. onView(withText("Hello Views")).check(matches(isDisplayed())) // Click on the Compose button that changes the state. composeTestRule.onNodeWithText("Click here").performClick() // Check the new value. onView(withText("Hello Compose")).check(matches(isDisplayed())) } } ``` -------------------------------- ### Migrate from runTest to runComposeUiTest Source: https://developer.android.com/develop/ui/compose/testing/migrate-v2 Avoids issues with separate clocks by using `runComposeUiTest`, which properly synchronizes Compose and test coroutine schedulers. The previous approach using `runTest` with `createComposeRule` can lead to manual synchronization needs. ```kotlin @get:Rule val composeTestRule = createComposeRule() @Test fun testWithCoroutines() { composeTestRule.setContent { var status by remember { mutableStateOf("Loading...") } LaunchedEffect(Unit) { delay(1000) status = "Done!" } Text(text = status) } // NOT RECOMMENDED // Fails: runTest creates a new, separate scheduler. // Advancing time here does NOT advance the compose clock. // To fix this without migrating, you would need to share the scheduler // by passing 'composeTestRule.mainClock.scheduler' to runTest. runTest { composeTestRule.onNodeWithText("Loading...").assertIsDisplayed() advanceTimeBy(1000) composeTestRule.onNodeWithText("Done!").assertIsDisplayed() } } TestSnippets.kt ``` -------------------------------- ### Add Compose UI Testing Dependencies Source: https://developer.android.com/develop/ui/compose/testing Add these dependencies to your module's build.gradle file to enable Compose UI testing. This includes test rules and manifest configurations. ```gradle androidTestImplementation("androidx.compose.ui:ui-test-junit4:$compose_version") // Needed for createComposeRule(), but not for createAndroidComposeRule(): debugImplementation("androidx.compose.ui:ui-test-manifest:$compose_version") ``` -------------------------------- ### Perform Key Press Action Source: https://developer.android.com/develop/ui/compose/testing/apis Use `performKeyPress` to simulate a key press event on a focused UI element. This is useful for testing input fields or keyboard navigation. ```kotlin performKeyPress(keyEvent), ``` -------------------------------- ### Perform Gesture Action Source: https://developer.android.com/develop/ui/compose/testing/apis Use `performGesture` with predefined gestures like `swipeLeft` to simulate more complex user interactions. This allows testing of swipeable components. ```kotlin performGesture { swipeLeft() } ``` -------------------------------- ### Print Unmerged Semantics Tree to Log Source: https://developer.android.com/develop/ui/compose/testing/apis Use `printToLog` with `useUnmergedTree = true` to inspect the unmerged semantics tree. This shows individual nodes that might be merged in the default view. ```kotlin composeTestRule.onRoot(useUnmergedTree = true).printToLog("TAG") ``` -------------------------------- ### Perform Click Action Source: https://developer.android.com/develop/ui/compose/testing/apis Use `performClick` to simulate a click event on a selected UI element. This is a common action for interactive elements. ```kotlin composeTestRule.onNode(...).performClick() ``` -------------------------------- ### Compose UI Testing v1 vs v2 Coroutine Dispatching Source: https://developer.android.com/develop/ui/compose/testing/migrate-v2 In v1, coroutines executed immediately, potentially masking timing issues. In v2, coroutines are queued and require explicit advancement using test APIs. ```kotlin // In v1, this launched and finished immediately. viewModel.loadData() // In v2, this fails because loadData() hasn't actually run yet! assertEquals(Success, viewModel.state.value) ``` -------------------------------- ### Set Content and Access Activity Resources Source: https://developer.android.com/develop/ui/compose/testing/common-patterns Use `createAndroidComposeRule()` to set custom content and access activity resources like string resources within your tests. Ensure `ComponentActivity` is declared in your `AndroidManifest.xml` and include the `ui-test-manifest` dependency. ```kotlin class MyComposeTest { @get:Rule val composeTestRule = createAndroidComposeRule() @Test fun myTest() { // Start the app composeTestRule.setContent { MyAppTheme { MainScreen(uiState = exampleUiState, /*...*/) } } val continueLabel = composeTestRule.activity.getString(R.string.next) composeTestRule.onNodeWithText(continueLabel).performClick() } } ``` ```kotlin debugImplementation("androidx.compose.ui:ui-test-manifest:$compose_version") ``` -------------------------------- ### Verify State Restoration with StateRestorationTester Source: https://developer.android.com/develop/ui/compose/testing/common-patterns Use `StateRestorationTester` to simulate activity or process recreation and verify that the state of your composables, particularly those using `rememberSaveable`, is correctly restored. This class allows for state restoration checks without actual activity recreation. ```kotlin class MyStateRestorationTests { @get:Rule val composeTestRule = createComposeRule() @Test fun onRecreation_stateIsRestored() { val restorationTester = StateRestorationTester(composeTestRule) restorationTester.setContent { MainScreen() } // TODO: Run actions that modify the state // Trigger a recreation restorationTester.emulateSavedInstanceStateRestore() // TODO: Verify that state has been correctly restored. } } ``` -------------------------------- ### Select Multiple Nodes with Matcher Source: https://developer.android.com/develop/ui/compose/testing/apis Use `onAllNodes` with a SemanticsMatcher to select multiple UI elements. The `useUnmergedTree` parameter can be set to `true` to consider unmerged semantics. ```kotlin composeTestRule .onAllNodes(<>): SemanticsNodeInteractionCollection ``` ```kotlin // Example composeTestRule .onAllNodes(hasText("Button")) // Equivalent to onAllNodesWithText("Button") ``` -------------------------------- ### Define and Use Custom Semantics Properties Source: https://developer.android.com/develop/ui/compose/testing/common-patterns Create custom semantics properties to expose specific data to your tests. Define a `SemanticsPropertyKey` and use it with the `semantics` modifier. Assert the property's value in tests using `SemanticsMatcher.expectValue`. ```kotlin // Creates a semantics property of type Long. val PickedDateKey = SemanticsPropertyKey("PickedDate") var SemanticsPropertyReceiver.pickedDate by PickedDateKey ``` ```kotlin val datePickerValue by remember { mutableStateOf(0L) } MyCustomDatePicker( modifier = Modifier.semantics { pickedDate = datePickerValue } ) ``` ```kotlin composeTestRule .onNode(SemanticsMatcher.expectValue(PickedDateKey, 1445378400)) // 2015-10-21 .assertExists() ``` -------------------------------- ### Using Selectors for Filtering and Assertion Source: https://developer.android.com/develop/ui/compose/testing/apis This snippet shows how to use selectors with `onNode`, `onChildren`, and `filter` to locate and assert properties of child elements. It filters children by click action, asserts the count, and then checks the first child for specific text. ```kotlin composeTestRule.onNode(hasTestTag("Players")) .onChildren() .filter(hasClickAction()) .assertCountEquals(4) .onFirst() .assert(hasText("John")) ``` -------------------------------- ### Manual Synchronization with waitForIdle Source: https://developer.android.com/develop/ui/compose/testing/synchronization Use `waitForIdle()` to make the test wait until the Compose UI is idle. The behavior of `waitForIdle()` depends on the `autoAdvance` setting: when `true` (default), it advances the clock; when `false`, it only waits for registered idling resources. ```kotlin composeTestRule.mainClock.autoAdvance = true // Default composeTestRule.waitForIdle() // Advances the clock until Compose is idle. composeTestRule.mainClock.autoAdvance = false composeTestRule.waitForIdle() // Only waits for idling resources to become idle. ``` -------------------------------- ### Find Composable with testTag using By.res Source: https://developer.android.com/develop/ui/compose/testing/interoperability Find a composable with `Modifier.testTag` using `By.res(resourceName)`, where `resourceName` is the same as the `tag` provided to `Modifier.testTag`. This allows for interactions with the found composable. ```kotlin val device = UiDevice.getInstance(getInstrumentation()) val lazyColumn: UiObject2 = device.findObject(By.res("myLazyColumn")) // Some interaction with the lazyColumn. ``` -------------------------------- ### Perform Semantics Action Source: https://developer.android.com/develop/ui/compose/testing/apis Use `performSemanticsAction` to execute a specific semantics action on a node, identified by a key. This allows for custom or less common interactions. ```kotlin performSemanticsAction(key), ``` -------------------------------- ### Compose UI Test with Coroutines Source: https://developer.android.com/develop/ui/compose/testing/migrate-v2 Use `runComposeUiTest` to execute tests within a synchronized coroutine scope. This API manages the test clock automatically, simplifying asynchronous operations in your Compose UI tests. ```kotlin @Test fun testWithCoroutines() = runComposeUiTest { setContent { var status by remember { mutableStateOf("Loading...") } LaunchedEffect(Unit) { delay(1000) status = "Done!" } Text(text = status) } onNodeWithText("Loading...").assertIsDisplayed() mainClock.advanceTimeBy(1000 + 16 /* Frame buffer */) onNodeWithText("Done!").assertIsDisplayed() } } ``` -------------------------------- ### Registering Idling Resources in Compose Tests Source: https://developer.android.com/develop/ui/compose/testing/synchronization Register custom `IdlingResource` implementations with the `composeTestRule` to ensure tests wait for background asynchronous operations to complete before proceeding. Unregister them when they are no longer needed. ```kotlin composeTestRule.registerIdlingResource(idlingResource) composeTestRule.unregisterIdlingResource(idlingResource) ``` -------------------------------- ### Assert All Nodes in Collection Match Source: https://developer.android.com/develop/ui/compose/testing/apis Use `assertAll` on a `SemanticsNodeInteractionCollection` to verify that every node in the collection satisfies the given `SemanticsMatcher`. ```kotlin // All of them match composeTestRule .onAllNodesWithContentDescription("Beatle").assertAll(hasClickAction()) ``` -------------------------------- ### Select a Single Node with Matcher Source: https://developer.android.com/develop/ui/compose/testing/apis Use `onNode` with a SemanticsMatcher to select a single UI element. The `useUnmergedTree` parameter can be set to `true` to consider unmerged semantics. ```kotlin composeTestRule.onNode(<>, useUnmergedTree = false): SemanticsNodeInteraction ``` ```kotlin // Example composeTestRule .onNode(hasText("Button")) // Equivalent to onNodeWithText("Button") ``` -------------------------------- ### Assert with Multiple Semantics Matchers Source: https://developer.android.com/develop/ui/compose/testing/apis Combine multiple `SemanticsMatcher` instances using `or` to assert conditions on a node. This allows for more flexible verification. ```kotlin composeTestRule .onNode(matcher).assert(hasText("Button") or hasText("Button2")) ``` -------------------------------- ### Wait Until Node Does Not Exist Source: https://developer.android.com/develop/ui/compose/testing/synchronization Use `waitUntilDoesNotExist` to wait until a node matching the given matcher is no longer present on the screen within the specified timeout. This is helpful for animations or view removals. ```kotlin composeTestRule.waitUntilDoesNotExist(matcher, timeoutMs) ``` -------------------------------- ### Add Content Description to Semantics Source: https://developer.android.com/develop/ui/compose/testing/semantics Use Modifier.semantics to add a content description to a composable, providing meaning for testing and accessibility. This is useful when the default semantics are insufficient. ```kotlin MyButton( modifier = Modifier.semantics { contentDescription = "Add to favorites" } ) ``` -------------------------------- ### Fix Compose UI Test Failures with waitForIdle Source: https://developer.android.com/develop/ui/compose/testing/migrate-v2 Use `waitForIdle` to advance the virtual clock until the UI is idle, ensuring all queued coroutines have executed before proceeding with assertions. ```kotlin viewModel.loadData() // Explicitly run all queued tasks composeTestRule.waitForIdle() assertEquals(Success, viewModel.state.value) ``` -------------------------------- ### Assert Count on Node Collection Source: https://developer.android.com/develop/ui/compose/testing/apis Use `assertCountEquals` on a `SemanticsNodeInteractionCollection` to verify the exact number of nodes matched by a finder. ```kotlin // Check number of matched nodes composeTestRule .onAllNodesWithContentDescription("Beatle").assertCountEquals(4) ``` -------------------------------- ### Manually Run Current Coroutines with runCurrent Source: https://developer.android.com/develop/ui/compose/testing/migrate-v2 When auto-advancing is disabled, use `runCurrent()` to execute tasks scheduled for the current virtual time without advancing the clock. This is useful for verifying intermediate states. ```kotlin composeTestRule.mainClock.scheduler.runCurrent() ``` -------------------------------- ### General Wait for Condition in Compose Testing Source: https://developer.android.com/develop/ui/compose/testing/synchronization Use this general `waitUntil` function when a condition depends on external work like data loading or Android's measure/draw phases. Specify the timeout in milliseconds and the condition to wait for. ```kotlin composeTestRule.waitUntil(timeoutMs) { condition } ``` -------------------------------- ### Fix Compose UI Test Failures with runOnIdle Source: https://developer.android.com/develop/ui/compose/testing/migrate-v2 Use `runOnIdle` to execute a code block on the UI thread only after the UI has become idle. This is useful for performing assertions that depend on completed coroutine tasks. ```kotlin viewModel.loadData() // Run the assertion after the UI is idle composeTestRule.runOnIdle { assertEquals(Success, viewModel.state.value) } ``` -------------------------------- ### Advance Time Until Condition in Compose Tests Source: https://developer.android.com/develop/ui/compose/testing/synchronization Use `advanceTimeUntil()` to advance the test clock until a specific condition is met. The condition should check a Compose state that can be affected by the clock; it does not control Android's measure and draw passes. ```kotlin composeTestRule.mainClock.advanceTimeUntil(timeoutMs) { condition } ``` -------------------------------- ### Wait Until Exactly One Node Exists Source: https://developer.android.com/develop/ui/compose/testing/synchronization Use `waitUntilExactlyOneExists` to ensure that precisely one node matching the given matcher is present within the specified timeout. This prevents race conditions with multiple matching elements. ```kotlin composeTestRule.waitUntilExactlyOneExists(matcher, timeoutMs) ``` -------------------------------- ### Advance Time in Compose Tests Source: https://developer.android.com/develop/ui/compose/testing/synchronization Manually advance the test clock by one frame using `advanceTimeByFrame()` or by a specific duration in milliseconds using `advanceTimeBy()`. These methods are used after disabling `autoAdvance` to control the timing of UI updates and animations. ```kotlin composeTestRule.mainClock.advanceTimeByFrame() composeTestRule.mainClock.advanceTimeBy(milliseconds) ``` -------------------------------- ### Wait Until Node Count Matches Source: https://developer.android.com/develop/ui/compose/testing/synchronization Use `waitUntilNodeCount` to wait until the number of nodes matching the given matcher equals the specified count within the timeout. This is useful for verifying list or collection updates. ```kotlin composeTestRule.waitUntilNodeCount(matcher, count, timeoutMs) ``` -------------------------------- ### Assert Any Node in Collection Matches Source: https://developer.android.com/develop/ui/compose/testing/apis Use `assertAny` on a `SemanticsNodeInteractionCollection` to check if at least one node in the collection satisfies the given `SemanticsMatcher`. ```kotlin // At least one matches composeTestRule .onAllNodesWithContentDescription("Beatle").assertAny(hasTestTag("Drummer")) ``` -------------------------------- ### Wait Until At Least One Node Exists Source: https://developer.android.com/develop/ui/compose/testing/synchronization Use `waitUntilAtLeastOneExists` to wait until at least one node matching the given matcher appears within the specified timeout. This is useful for asynchronous UI updates. ```kotlin composeTestRule.waitUntilAtLeastOneExists(matcher, timeoutMs) ``` -------------------------------- ### Assert Node in Unmerged Tree Source: https://developer.android.com/develop/ui/compose/testing/apis Use `onNodeWithText` with `useUnmergedTree = true` to target a node in the unmerged semantics tree and perform assertions on it. ```kotlin composeTestRule .onNodeWithText("World", useUnmergedTree = true).assertIsDisplayed() ``` -------------------------------- ### Hierarchical Matcher Declarations Source: https://developer.android.com/develop/ui/compose/testing/apis These are the function signatures for hierarchical matchers used to navigate the Compose semantics tree. They are used to find nodes based on their parent, siblings, ancestors, or descendants. ```kotlin fun hasParent(matcher: SemanticsMatcher): SemanticsMatcher fun hasAnySibling(matcher: SemanticsMatcher): SemanticsMatcher fun hasAnyAncestor(matcher: SemanticsMatcher): SemanticsMatcher fun hasAnyDescendant(matcher: SemanticsMatcher): SemanticsMatcher ``` -------------------------------- ### Interact with Compose Element in RecyclerView Row Source: https://developer.android.com/develop/ui/compose/testing/interoperability Use Espresso to scroll to a specific RecyclerView row and then scope Compose interactions to that row's ViewInteraction. This ensures interactions target only the Compose elements within the selected row. ```kotlin @Test fun testComposeButtonInsideRecyclerViewItem() = runComposeUiTest { // Scroll to the desired position using Espresso Espresso.onView(withId(recyclerViewId)) .perform(RecyclerViewActions.scrollToPosition(3)) // Define an Espresso ViewInteraction that uniquely identifies the row val rowView = Espresso.onView( allOf( withId(rootViewId), hasDescendant(withText("Item #3")) ) ) // Scope the Compose search strictly to that specific row View onRootWithViewInteraction(rowView) .onNode(hasText("Like")) .performClick() } TestSnippets.kt ``` -------------------------------- ### Enable testTagsAsResourceId in Scaffold Source: https://developer.android.com/develop/ui/compose/testing/interoperability Enable `testTagsAsResourceId` high in your composables hierarchy to make all nested composables with `Modifier.testTag` accessible from UiAutomator. This is useful for composables without other unique handles. ```kotlin Scaffold( // Enables for all composables in the hierarchy. modifier = Modifier.semantics { testTagsAsResourceId = true } ){ // Modifier.testTag is accessible from UiAutomator for composables nested here. LazyColumn( modifier = Modifier.testTag("myLazyColumn") ){ // Content } } ``` -------------------------------- ### Resolve Ambiguity in ViewPager Fragments Source: https://developer.android.com/develop/ui/compose/testing/interoperability Scope Compose searches to a specific fragment's root View ID within a ViewPager using Espresso. This prevents ambiguity when multiple fragments contain identical Compose layouts. ```kotlin @Test fun testComposeButtonInsideViewPagerItem() = runComposeUiTest { // Swipe to the desired page using Espresso Espresso.onView(withId(viewPagerViewId)).perform(swipeLeft()) // Identify the specific container view using Espresso val fragmentB = Espresso.onView(withId(fragmentRootViewId)) // The generic text "Save" is now unique within this view scope onRootWithViewInteraction(fragmentB) .onNode(hasText("Save")) .assertIsDisplayed() } TestSnippets.kt ``` -------------------------------- ### Disable Automatic Synchronization in Compose Tests Source: https://developer.android.com/develop/ui/compose/testing/synchronization Set `autoAdvance` to `false` on the `mainClock` to disable automatic test synchronization. This allows manual control over time advancement, which is useful for capturing specific moments in animations or UI states. ```kotlin composeTestRule.mainClock.autoAdvance = false ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.