@TestfuncounterTest(){valmyCounter=mutableStateOf(0)// State that can cause recompositions.varlastSeenValue=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()}
composeTestRule.mainClock.autoAdvance=true// DefaultcomposeTestRule.waitForIdle()// Advances the clock until Compose is idle.composeTestRule.mainClock.autoAdvance=falsecomposeTestRule.waitForIdle()// Only waits for idling resources to become idle.
[[["容易理解","easyToUnderstand","thumb-up"],["確實解決了我的問題","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["缺少我需要的資訊","missingTheInformationINeed","thumb-down"],["過於複雜/步驟過多","tooComplicatedTooManySteps","thumb-down"],["過時","outOfDate","thumb-down"],["翻譯問題","translationIssue","thumb-down"],["示例/程式碼問題","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["上次更新時間:2025-08-21 (世界標準時間)。"],[],[],null,["# Synchronize your tests\n\nCompose tests are synchronized by default with your UI. When you call an\nassertion or an action with the [`ComposeTestRule`](/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule), the test is synchronized\nbeforehand, waiting until the UI tree is idle.\n\nNormally, you don't have to take any action. However, there are some edge cases\nyou should know about.\n\nWhen a test is synchronized, your Compose app is advanced in time using a\nvirtual clock. This means Compose tests don't run in real time, so they can pass\nas fast as possible.\n\nHowever, if you don't use the methods that synchronize your tests, no\nrecomposition will occur and the UI will appear to be paused. \n\n @Test\n fun counterTest() {\n val myCounter = mutableStateOf(0) // State that can cause recompositions.\n var lastSeenValue = 0 // Used to track recompositions.\n composeTestRule.setContent {\n Text(myCounter.value.toString())\n lastSeenValue = myCounter.value\n }\n myCounter.value = 1 // The state changes, but there is no recomposition.\n\n // Fails because nothing triggered a recomposition.\n assertTrue(lastSeenValue == 1)\n\n // Passes because the assertion triggers recomposition.\n composeTestRule.onNodeWithText(\"1\").assertExists()\n }\n\nNote that this requirement only applies to Compose hierarchies and not to the\nrest of the app.\n\n### Disable automatic synchronization\n\nWhen you call an assertion or action through the `ComposeTestRule` such as\n`assertExists()`, your test is synchronized with the Compose UI. In some cases\nyou might want to stop this synchronization and control the clock yourself. For\nexample, you can control time to take accurate screenshots of an animation at a\npoint where the UI would still be busy. To disable automatic synchronization,\nset the `autoAdvance` property in the `mainClock` to `false`: \n\n composeTestRule.mainClock.autoAdvance = false\n\nTypically you will then advance the time yourself. You can advance exactly one\nframe with `advanceTimeByFrame()` or by a specific duration with\n`advanceTimeBy()`: \n\n composeTestRule.mainClock.advanceTimeByFrame()\n composeTestRule.mainClock.advanceTimeBy(milliseconds)\n\n| **Note:** [`MainTestClock`](/reference/kotlin/androidx/compose/ui/test/MainTestClock) is responsible for driving all the recompositions, animations, and gestures. The API doesn't control [Android's measure and draw\n| passes](/guide/topics/ui/how-android-draws).\n\n### Idle resources\n\nCompose can synchronize tests and the UI so that every action and assertion is\ndone in an idle state, waiting or advancing the clock as needed. However, some\nasynchronous operations whose results affect the UI state can be run in the\nbackground while the test is unaware of them.\n\nCreate and register these *idling resources* in your test so that they're taken\ninto account when deciding whether the app under test is busy or idle. You don't\nhave to take action unless you need to register additional idling resources, for\nexample, if you run a background job that is not synchronized with Espresso or\nCompose.\n\nThis API is very similar to Espresso's [Idling Resources](/training/testing/espresso/idling-resource) to indicate whether\nthe subject under test is idle or busy. Use the Compose test rule to register\nthe implementation of the [`IdlingResource`](/reference/kotlin/androidx/compose/ui/test/IdlingResource). \n\n composeTestRule.registerIdlingResource(idlingResource)\n composeTestRule.unregisterIdlingResource(idlingResource)\n\n### Manual synchronization\n\nIn certain cases, you have to synchronize the Compose UI with other parts of\nyour test or the app you're testing.\n\nThe [`waitForIdle()`](/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitForIdle()) function waits for Compose to be idle, but the function\ndepends on the `autoAdvance` property: \n\n composeTestRule.mainClock.autoAdvance = true // Default\n composeTestRule.waitForIdle() // Advances the clock until Compose is idle.\n\n composeTestRule.mainClock.autoAdvance = false\n composeTestRule.waitForIdle() // Only waits for idling resources to become idle.\n\nNote that in both cases, `waitForIdle()` also waits for pending [draw and layout\npasses](/guide/topics/ui/how-android-draws#:%7E:text=When%20an%20Activity%20receives%20focus,and%20draw%20the%20layout%20tree.).\n\nAlso, you can advance the clock until a certain condition is met with\n[`advanceTimeUntil()`](/reference/kotlin/androidx/compose/ui/test/MainTestClock#advanceTimeUntil(kotlin.Long,kotlin.Function0)). \n\n composeTestRule.mainClock.advanceTimeUntil(timeoutMs) { condition }\n\nNote that the given condition should be checking the state that can be affected\nby this clock (it only works with Compose state).\n\n### Wait for conditions\n\nAny condition that depends on external work, such as data loading or Android's\nmeasure or draw (that is, measure or draw external to Compose), should use a\nmore general concept such as [`waitUntil()`](/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntil(kotlin.Long,kotlin.Function0)): \n\n composeTestRule.waitUntil(timeoutMs) { condition }\n\nYou can also use any of the\n[`waitUntil` helpers](/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilAtLeastOneExists(androidx.compose.ui.test.SemanticsMatcher,kotlin.Long)): \n\n composeTestRule.waitUntilAtLeastOneExists(matcher, timeoutMs)\n\n composeTestRule.waitUntilDoesNotExist(matcher, timeoutMs)\n\n composeTestRule.waitUntilExactlyOneExists(matcher, timeoutMs)\n\n composeTestRule.waitUntilNodeCount(matcher, count, timeoutMs)\n\n| **Warning:** In some cases, using mechanisms in a test like an external `CountDownLatch` instead of the `waitUntil` APIs could behave unexpectedly, since the test clock won't be advanced.\n\nAdditional Resources\n--------------------\n\n- **[Test apps on Android](/training/testing)**: The main Android testing landing page provides a broader view of testing fundamentals and techniques.\n- **[Fundamentals of testing](/training/testing/fundamentals):** Learn more about the core concepts behind testing an Android app.\n- **[Local tests](/training/testing/local-tests):** You can run some tests locally, on your own workstation.\n- **[Instrumented tests](/training/testing/instrumented-tests):** It is good practice to also run instrumented tests. That is, tests that run directly on-device.\n- **[Continuous integration](/training/testing/continuous-integration):** Continuous integration lets you integrate your tests into your deployment pipeline.\n- **[Test different screen sizes](/training/testing/different-screens):** With some many devices available to users, you should test for different screen sizes.\n- **[Espresso](/training/testing/espresso)**: While intended for View-based UIs, Espresso knowledge can still be helpful for some aspects of Compose testing."]]