Việc tự động hoá các bài kiểm thử điều hướng bằng tiêu điểm giúp đảm bảo ứng dụng của bạn mang lại trải nghiệm người dùng nhất quán và dễ đoán trên bàn phím phần cứng, d-pad và công cụ hỗ trợ tiếp cận. Compose cung cấp các API kiểm thử tích hợp sẵn để mô phỏng hoạt động nhập bằng phím và xác minh trạng thái tiêu điểm.
Thiết lập thử nghiệm tập trung
Để viết mã kiểm thử tiêu điểm, hãy sử dụng createComposeRule() trong thư viện kiểm thử Compose:
@RunWith(AndroidJUnit4::class) class FocusNavigationTest { @get:Rule val composeTestRule = createComposeRule()
Xác minh mục tiêu lấy tiêu điểm
Bạn có thể xác minh xem một phần tử trên giao diện người dùng có thể nhận tiêu điểm hay không bằng cách nhấp hoặc yêu cầu tiêu điểm, sau đó xác nhận trạng thái của phần tử đó bằng assertIsFocused() và assertIsNotFocused().
@Test fun interactiveElement_isFocusTarget() { composeTestRule.setContent { AppTheme { CardListScreen() } } val firstCard = composeTestRule.onNodeWithTag("card_1") val secondCard = composeTestRule.onNodeWithTag("card_2") // Focus the first element firstCard.performClick() firstCard.assertIsFocused() secondCard.assertIsNotFocused() }
Kiểm thử tính năng duyệt qua tiêu điểm theo một chiều
Mô phỏng thao tác nhấn phím Tab và Shift+Tab bằng performKeyInput để xác minh rằng tiêu điểm di chuyển qua giao diện người dùng theo thứ tự xuất hiện. Tốt nhất là bạn nên xác minh cả thao tác di chuyển tiến (Key.Tab) và di chuyển lùi (Key.Tab khi nhấn giữ Key.ShiftLeft) để đảm bảo tính toàn vẹn của thao tác di chuyển hai chiều:
@Test fun tabKey_navigatesInAppearanceOrder() { composeTestRule.setContent { AppTheme { CardListScreen() } } val firstCard = composeTestRule.onNodeWithTag("card_1") val secondCard = composeTestRule.onNodeWithTag("card_2") val thirdCard = composeTestRule.onNodeWithTag("card_3") firstCard.performClick() firstCard.assertIsFocused() // Press Tab -> Moves to second card firstCard.performKeyInput { pressKey(Key.Tab) } secondCard.assertIsFocused() firstCard.assertIsNotFocused() // Press Tab -> Moves to third card secondCard.performKeyInput { pressKey(Key.Tab) } thirdCard.assertIsFocused() // Press Shift + Tab -> Moves backward to second card thirdCard.performKeyInput { withKeyDown(Key.ShiftLeft) { pressKey(Key.Tab) } } secondCard.assertIsFocused() }
Kiểm thử thao tác duyệt qua theo hướng hai chiều
Mô phỏng các phím mũi tên hoặc phím chỉ hướng D-pad bằng cách sử dụng Key.DirectionDown, Key.DirectionUp, Key.DirectionRight và Key.DirectionLeft.
@Test fun arrowKeys_moveFocusTwoDimensionallyWithoutWrap() { composeTestRule.setContent { AppTheme { GridLayoutScreen() } } val topLeftButton = composeTestRule.onNodeWithTag("btn_top_left") val bottomLeftButton = composeTestRule.onNodeWithTag("btn_bottom_left") topLeftButton.performClick() topLeftButton.assertIsFocused() // Down arrow moves focus downward to bottom-left button topLeftButton.performKeyInput { pressKey(Key.DirectionDown) } bottomLeftButton.assertIsFocused() // Directional keys do not wrap around: pressing Down on bottom element stays focused bottomLeftButton.performKeyInput { pressKey(Key.DirectionDown) } bottomLeftButton.assertIsFocused() }
Kiểm thử hành vi lấy tiêu điểm của trường văn bản
Xác minh rằng các trường văn bản một dòng sẽ chuyển tiêu điểm khi nhấn phím Tab, trong khi các trường văn bản nhiều dòng vẫn giữ tiêu điểm:
@Test fun textField_handlesTabAccordingToLineLimits() { composeTestRule.setContent { AppTheme { FormScreen() } } val singleLineNode = composeTestRule.onNodeWithTag("single_line_field") val multiLineNode = composeTestRule.onNodeWithTag("multi_line_field") val submitButtonNode = composeTestRule.onNodeWithTag("submit_button") // Single-line field advances focus on Tab singleLineNode.performClick() singleLineNode.assertIsFocused() singleLineNode.performKeyInput { pressKey(Key.Tab) } multiLineNode.assertIsFocused() // Multi-line field keeps focus and inserts '\t' multiLineNode.performKeyInput { pressKey(Key.Tab) } multiLineNode.assertIsFocused() submitButtonNode.assertIsNotFocused() // Shift + Tab escapes multi-line field to previous target multiLineNode.performKeyInput { withKeyDown(Key.ShiftLeft) { pressKey(Key.Tab) } } singleLineNode.assertIsFocused() }
Đề xuất cho bạn
- Lưu ý: văn bản có đường liên kết sẽ hiện khi JavaScript tắt
- Mục tiêu lấy tiêu điểm
- Thứ tự duyệt qua tiêu điểm
- Tiêu điểm trong trường văn bản
- Nhóm mục tiêu lấy tiêu điểm