คุณทดสอบแอป Compose ได้ด้วยแนวทางและรูปแบบที่ได้รับการยอมรับ
ทดสอบแบบแยก
ComposeTestRule ช่วยให้คุณเริ่มกิจกรรมที่แสดง Composable ใดก็ได้ ไม่ว่าจะเป็น
แอปพลิเคชันทั้งหมด หน้าจอเดียว หรือองค์ประกอบขนาดเล็ก นอกจากนี้ การตรวจสอบว่า Composable ได้รับการแคปซูลอย่างถูกต้องและทำงานได้อย่างอิสระยังเป็นแนวทางปฏิบัติที่ดี ซึ่งจะช่วยให้การทดสอบ UI ง่ายขึ้นและมีประสิทธิภาพมากขึ้น
แต่ไม่ได้หมายความว่าคุณควรสร้างการทดสอบ UI ระดับหน่วยเท่านั้น การกำหนดขอบเขตการทดสอบ UI ส่วนที่ใหญ่ขึ้นของ UI ก็มีความสำคัญมากเช่นกัน
เข้าถึงกิจกรรมและแหล่งข้อมูลหลังจากตั้งค่าเนื้อหาของคุณเอง
บ่อยครั้งที่คุณต้องตั้งค่าเนื้อหาภายใต้การทดสอบโดยใช้
composeTestRule.setContent และคุณยังต้องเข้าถึงทรัพยากรกิจกรรมด้วย เช่น
เพื่อยืนยันว่าข้อความที่แสดงตรงกับทรัพยากรสตริง อย่างไรก็ตาม คุณจะเรียก setContent ในกฎที่สร้างด้วย createAndroidComposeRule() ไม่ได้หากกิจกรรมเรียกกฎนั้นอยู่แล้ว
รูปแบบทั่วไปในการดำเนินการนี้คือการสร้าง AndroidComposeTestRule โดยใช้
กิจกรรมที่ว่างเปล่า เช่น ComponentActivity
class MyComposeTest {
@get:Rule
val composeTestRule = createAndroidComposeRule<ComponentActivity>()
@Test
fun myTest() {
// Start the app
composeTestRule.setContent {
MyAppTheme {
MainScreen(uiState = exampleUiState, /*...*/)
}
}
val continueLabel = composeTestRule.activity.getString(R.string.next)
composeTestRule.onNodeWithText(continueLabel).performClick()
}
}
โปรดทราบว่าคุณต้องเพิ่ม ComponentActivity ลงในไฟล์
AndroidManifest.xml ของแอป โดยเปิดใช้ได้ด้วยการเพิ่มทรัพยากร Dependency นี้ลงในโมดูล
debugImplementation("androidx.compose.ui:ui-test-manifest:$compose_version")
พร็อพเพอร์ตี้ความหมายที่กำหนดเอง
คุณสามารถสร้างพร็อพเพอร์ตี้ความหมายที่กำหนดเองเพื่อแสดงข้อมูลในการทดสอบ
โดยกำหนด SemanticsPropertyKey ใหม่และทำให้พร้อมใช้งานโดยใช้
SemanticsPropertyReceiver
// Creates a semantics property of type Long.
val PickedDateKey = SemanticsPropertyKey<Long>("PickedDate")
var SemanticsPropertyReceiver.pickedDate by PickedDateKey
ตอนนี้ให้ใช้พร็อพเพอร์ตี้นั้นในตัวแก้ไข semantics ดังนี้
val datePickerValue by remember { mutableStateOf(0L) }
MyCustomDatePicker(
modifier = Modifier.semantics { pickedDate = datePickerValue }
)
จากการทดสอบ ให้ใช้ SemanticsMatcher.expectValue เพื่อยืนยันค่าของพร็อพเพอร์ตี้
composeTestRule
.onNode(SemanticsMatcher.expectValue(PickedDateKey, 1445378400)) // 2015-10-21
.assertExists()
ยืนยันการคืนค่าสถานะ
ตรวจสอบว่าระบบได้กู้คืนสถานะขององค์ประกอบ Compose อย่างถูกต้องเมื่อสร้างกิจกรรมหรือกระบวนการขึ้นมาใหม่ ทำการตรวจสอบดังกล่าวโดยไม่ต้องอาศัย
การสร้างกิจกรรมใหม่ด้วยคลาส StateRestorationTester
คลาสนี้ช่วยให้คุณจำลองการสร้าง Composable ขึ้นมาใหม่ได้ โดยเฉพาะอย่างยิ่งเมื่อต้องการยืนยันการติดตั้งใช้งาน rememberSaveable
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.
}
}
ทดสอบการกำหนดค่าอุปกรณ์ต่างๆ
แอป Android ต้องปรับให้เข้ากับเงื่อนไขที่เปลี่ยนแปลงไปมากมาย เช่น ขนาดหน้าต่าง ภาษา
ขนาดแบบอักษร ธีมมืดและสว่าง และอื่นๆ เงื่อนไขส่วนใหญ่เหล่านี้ได้มาจากค่าระดับอุปกรณ์ที่ผู้ใช้ควบคุมและแสดงด้วยอินสแตนซ์ Configuration ปัจจุบัน การทดสอบการกำหนดค่าที่แตกต่างกัน
โดยตรงในการทดสอบเป็นเรื่องยากเนื่องจากการทดสอบต้องกำหนดค่าพร็อพเพอร์ตี้
ระดับอุปกรณ์
DeviceConfigurationOverride เป็น API สำหรับการทดสอบเท่านั้นที่ช่วยให้คุณจำลอง
การกำหนดค่าอุปกรณ์ต่างๆ ในลักษณะที่แปลแล้วสำหรับเนื้อหา @Composable
ที่อยู่ระหว่างการทดสอบ
ออบเจ็กต์คู่ของ DeviceConfigurationOverride มีฟังก์ชันส่วนขยายต่อไปนี้ ซึ่งจะลบล้างพร็อพเพอร์ตี้การกำหนดค่าระดับอุปกรณ์
DeviceConfigurationOverride.DarkMode(): ลบล้างระบบเป็นธีมมืด หรือธีมสว่างDeviceConfigurationOverride.FontScale(): ลบล้างสเกล แบบอักษรของระบบDeviceConfigurationOverride.FontWeightAdjustment(): ลบล้างการปรับน้ำหนักแบบอักษรของระบบDeviceConfigurationOverride.ForcedSize(): บังคับให้ใช้พื้นที่ จำนวนหนึ่งโดยไม่คำนึงถึงขนาดอุปกรณ์DeviceConfigurationOverride.LayoutDirection(): ลบล้างlayout direction (จากซ้ายไปขวาหรือจากขวาไปซ้าย)DeviceConfigurationOverride.Locales(): ลบล้างภาษาDeviceConfigurationOverride.RoundScreen(): ลบล้างหากหน้าจอ เป็นวงกลม
หากต้องการใช้การลบล้างที่เฉพาะเจาะจง ให้รวมเนื้อหาภายใต้การทดสอบไว้ในการเรียกฟังก์ชันระดับบนสุดของ DeviceConfigurationOverride() โดยส่งการลบล้าง
ที่จะใช้เป็นพารามิเตอร์
ตัวอย่างเช่น โค้ดต่อไปนี้ใช้การลบล้าง DeviceConfigurationOverride.ForcedSize() เพื่อเปลี่ยนความหนาแน่น
ในเครื่อง ซึ่งบังคับให้แสดงผล MyScreen ที่ใช้ร่วมกันได้ในหน้าต่างแนวนอนขนาดใหญ่
แม้ว่าอุปกรณ์ที่ใช้ทดสอบจะไม่รองรับขนาดหน้าต่างนั้นโดยตรงก็ตาม
composeTestRule.setContent { DeviceConfigurationOverride( DeviceConfigurationOverride.ForcedSize(DpSize(1280.dp, 800.dp)) ) { MyScreen() // Will be rendered in the space for 1280dp by 800dp without clipping. } }
หากต้องการใช้การลบล้างหลายรายการพร้อมกัน ให้ใช้
DeviceConfigurationOverride.then() ดังนี้
composeTestRule.setContent { DeviceConfigurationOverride( DeviceConfigurationOverride.FontScale(1.5f) then DeviceConfigurationOverride.FontWeightAdjustment(200) ) { Text(text = "text with increased scale and weight") } }
แหล่งข้อมูลเพิ่มเติม
- ทดสอบแอปใน Android: หน้า Landing Page หลักของการทดสอบ Android จะให้มุมมองที่กว้างขึ้นเกี่ยวกับพื้นฐานและเทคนิคการทดสอบ
- หลักพื้นฐานของการทดสอบ: ดูข้อมูลเพิ่มเติม เกี่ยวกับแนวคิดหลักเบื้องหลังการทดสอบแอป Android
- การทดสอบในเครื่อง: คุณสามารถเรียกใช้การทดสอบบางอย่าง ในเครื่องบนเวิร์กสเตชันของคุณเองได้
- การทดสอบแบบมีเครื่องควบคุม: คุณควรเรียกใช้การทดสอบแบบมีเครื่องควบคุมด้วย กล่าวคือ การทดสอบที่ทำงานโดยตรง ในอุปกรณ์
- การรวมอย่างต่อเนื่อง: การรวมอย่างต่อเนื่องช่วยให้คุณผสานรวมการทดสอบเข้ากับไปป์ไลน์การติดตั้งใช้งานได้
- ทดสอบขนาดหน้าจอต่างๆ: เนื่องจากผู้ใช้มีอุปกรณ์ให้เลือกมากมาย คุณจึงควรทดสอบขนาดหน้าจอต่างๆ
- Espresso: แม้ว่าจะมีไว้สำหรับ UI ที่อิงตาม View แต่ความรู้เกี่ยวกับ Espresso ก็ยังเป็นประโยชน์สำหรับบางแง่มุมของการทดสอบ Compose