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 จะเสถียร การเรียกใช้ในเธรด UI จะทำให้การทดสอบของคุณเสี่ยงต่อสภาพการแข่งขันและการอ่านสถานะที่ล้าสมัย - การยืนยันแบบอ่านอย่างเดียว: บล็อกควรมีการยืนยันแบบอ่านอย่างเดียวอย่างเคร่งครัด การดำเนินการใดๆ ที่เปลี่ยนสถานะควรดำเนินการนอกบล็อกนี้
ตัวอย่าง
@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
- ข้อควรพิจารณาอื่นๆ
- ปรับแต่งภาพเคลื่อนไหว