Compose มอบ ComposeTestRule ที่ช่วยให้คุณเขียนการทดสอบสำหรับภาพเคลื่อนไหวในลักษณะที่กำหนดโดยมีการควบคุมนาฬิกาทดสอบได้อย่างเต็มที่ ซึ่งช่วยให้คุณ
ยืนยันค่าภาพเคลื่อนไหวระดับกลางได้ นอกจากนี้ การทดสอบยังสามารถทำงานได้เร็วกว่า
ระยะเวลาจริงของภาพเคลื่อนไหว
ComposeTestRule จะแสดงนาฬิกาทดสอบเป็น mainClock คุณตั้งค่า
autoAdvance เป็น false เพื่อควบคุมนาฬิกาในโค้ดทดสอบได้ หลังจาก
เริ่มภาพเคลื่อนไหวที่ต้องการทดสอบแล้ว คุณจะเลื่อนเวลาไปข้างหน้าได้ด้วย
advanceTimeBy
สิ่งหนึ่งที่ควรทราบไว้คือ advanceTimeBy ไม่ได้เลื่อนนาฬิกาตามระยะเวลาที่ระบุอย่างแม่นยำ แต่จะปัดเศษขึ้นเป็นระยะเวลาที่ใกล้เคียงที่สุดซึ่งเป็น
ตัวคูณของระยะเวลาเฟรม
@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() }
เพิ่มประสิทธิภาพการทดสอบภาพเคลื่อนไหว
เมื่อทดสอบแอนิเมชันที่มีความสมจริงสูง คุณมักจะต้องปิดใช้การเลื่อนไปข้างหน้าอัตโนมัติและเลื่อนดูเฟรมทีละเฟรมด้วยตนเองเพื่อยืนยันสถานะ UI ระหว่างกลาง สำหรับลูปทีละเฟรมที่เฉพาะเจาะจงเหล่านี้
ให้ใช้เมธอด runWithoutImplicitWait เพื่อ
ดำเนินการยืนยัน การค้นหาโหนดมาตรฐาน (เช่น onNodeWithTag หรือ
fetchSemanticsNode) จะทริกเกอร์การซิงโครไนซ์โดยนัยซึ่งซ้ำซ้อน
เมื่อคุณควบคุมนาฬิกาด้วยตนเอง ดังนั้นการข้ามการค้นหาเหล่านี้จะช่วยเพิ่มความเร็วในการรันการทดสอบได้อย่างมาก
หลักเกณฑ์การใช้งาน
- การจัดการนาฬิกาด้วยตนเอง: ใช้ API นี้เมื่อตั้งค่า
mainClock.autoAdvanceเป็นfalseและ UI อยู่ในสถานะที่ทราบและเสถียรสำหรับ เฟรมปัจจุบัน - การดำเนินการในเธรด UI: เรียก
runWithoutImplicitWaitในเธรด UI เช่น ด้วยrunOnUiThreadเพื่อให้มั่นใจว่าต้นไม้ UI มีความเสถียร การเรียกใช้ใน Thread อื่นที่ไม่ใช่ UI Thread จะทำให้การทดสอบของคุณเสี่ยงต่อสภาวะการแข่งขันและการอ่านสถานะที่ล้าสมัย - การยืนยันแบบอ่านอย่างเดียว: บล็อกควรมีการยืนยันแบบอ่านอย่างเดียว เท่านั้น การดำเนินการใดๆ ที่เปลี่ยนแปลงสถานะควรทำนอกบล็อกนี้
ตัวอย่าง
@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) } } } }
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- การทดสอบเลย์เอาต์ Compose
- ข้อควรพิจารณาอื่นๆ
- ปรับแต่งภาพเคลื่อนไหว