Compose menawarkan ComposeTestRule yang memungkinkan Anda menulis pengujian untuk animasi secara deterministik dengan kontrol penuh selama jam pengujian. Hal ini memungkinkan Anda
memverifikasi nilai animasi menengah. Selain itu, pengujian dapat berjalan lebih cepat dibandingkan durasi animasi yang sebenarnya.
ComposeTestRule menampilkan jam pengujian sebagai mainClock. Anda dapat menyetel properti autoAdvance ke false untuk mengontrol jam di kode pengujian. Setelah memulai animasi yang ingin Anda uji, jam dapat digerakkan dengan advanceTimeBy.
Satu hal yang perlu diperhatikan di sini adalah advanceTimeBy tidak menggerakkan jam persis dengan durasi yang ditentukan. Sebaliknya, ini membulatkannya ke durasi terdekat yang
merupakan pengali dari durasi frame.
@get:Rule val rule = createComposeRule() @Test fun testAnimationWithClock() { // Pause animations rule.mainClock.autoAdvance = false var enabled by mutableStateOf(false) rule.setContent { val color by animateColorAsState( targetValue = if (enabled) Color.Red else Color.Green, animationSpec = tween(durationMillis = 250) ) Box(Modifier.size(64.dp).background(color)) } // Initiate the animation. enabled = true // Let the animation proceed. rule.mainClock.advanceTimeBy(50L) // Compare the result with the image showing the expected result. // `assertAgainGolden` needs to be implemented in your code. rule.onRoot().captureToImage().assertAgainstGolden() }
Mengoptimalkan pengujian animasi
Saat menguji animasi fidelitas tinggi, Anda sering kali perlu menonaktifkan maju otomatis dan menelusuri frame secara manual untuk menegaskan status UI perantara. Untuk loop frame demi frame tertentu ini, gunakan metode runWithoutImplicitWait untuk menjalankan pernyataan Anda. Kueri node standar (seperti onNodeWithTag atau
fetchSemanticsNode) memicu sinkronisasi implisit yang berlebihan
saat Anda mengontrol clock secara manual, sehingga melewati sinkronisasi tersebut akan
mempercepat waktu proses pengujian secara signifikan.
Panduan penggunaan
- Pengelolaan clock manual: Gunakan API ini saat
mainClock.autoAdvancedisetel kefalsedan UI berada dalam status yang diketahui dan stabil untuk frame saat ini. - Eksekusi UI thread: Untuk memastikan stabilitas hierarki UI, panggil
runWithoutImplicitWaitdi UI thread, seperti denganrunOnUiThread. Menjalankannya di luar thread UI akan membuat pengujian Anda rentan terhadap kondisi race dan pembacaan status yang tidak valid. - Pernyataan hanya baca: Blok harus berisi pernyataan hanya baca. Setiap tindakan yang mengubah status harus dilakukan di luar blok ini.
Contoh
@Test fun runWithoutImplicitWaitSample() = runComposeUiTest { setContent { MainScreen() } mainClock.autoAdvance = false // Trigger an animation onNodeWithText("Start Animation").performClick() // Step through the animation frame-by-frame while (hasPendingWork()) { mainClock.advanceTimeByFrame() waitForIdle() runOnUiThread { // Suppress implicit synchronization inside this block to avoid redundant // waits on each node query, making the frame assertions execute much faster. runWithoutImplicitWait { val box1 = onNodeWithTag("Box1").fetchSemanticsNode() val box2 = onNodeWithTag("Box2").fetchSemanticsNode() val box3 = onNodeWithTag("Box3").fetchSemanticsNode() // Assert the exact intermediate state of all three properties for this frame assert(box1.boundsInRoot.right <= box2.boundsInRoot.left) assert(box2.boundsInRoot.right <= box3.boundsInRoot.left) } } } }
Direkomendasikan untuk Anda
- Catatan: teks link ditampilkan saat JavaScript nonaktif
- Menguji tata letak Compose Anda
- Pertimbangan lainnya
- Menyesuaikan animasi