Chuyển tới nội dung chính

UI test: hành vi người dùng và đồng bộ đúng nguồn

Espresso làm việc với View hierarchy; Compose testing API tìm node theo semantics. Trên Android, createComposeRule() vẫn dùng cơ chế host/instrumentation tương ứng: “không phải chỉ định Activity riêng” không đồng nghĩa “không có Activity” hoặc một JVM test thuần.

1. Chọn test rule​

  • createComposeRule() phù hợp đặt content cần kiểm tra mà không chọn Activity sản phẩm cụ thể.
  • createAndroidComposeRule<YourActivity>() phù hợp cần Activity cụ thể và integration của nó.
  • createEmptyComposeRule() không tự cung cấp host/content; test phải tổ chức môi trường riêng theo contract API.

Thiết lập dependencies/source set theo phiên bản Compose đang dùng. Không trộn giả định của local JVM tests với instrumented UI tests.

Nguồn: Compose testing setup.

2. Ví dụ kiểm tra state/action của một button​

class SubmitButtonTest {
@get:Rule
val compose = createComposeRule()

@Test
fun disabledButtonDoesNotSubmit() {
var submissions = 0
compose.setContent {
Button(onClick = { submissions++ }, enabled = false) {
Text("Submit")
}
}
compose.onNodeWithText("Submit").assertIsNotEnabled()
compose.runOnIdle { assertEquals(0, submissions) }
}
}

Ví dụ dùng Compose Material và UI test JUnit4. Đây là kiểm tra UI nhỏ; test thành công phải có case button enabled, click và callback/behavior được kích hoạt. Trong UI nhiều node cùng text, dùng matcher có semantics đủ phân biệt thay vì dựa vào thứ tự node.

Test tag hữu ích khi cần định danh kỹ thuật, nhưng không thay accessible label/role/action. Semantics merge có thể làm cây test khác layout tree; chỉ dùng unmerged tree khi thực sự kiểm tra boundary đó.

3. Idle của UI chưa chắc network đã hoàn tất​

Framework đồng bộ các nguồn nó biết, không tự hiểu mọi request Retrofit, external callback hoặc background job. Inject fake cho screen tests; với integration thực, đăng ký IdlingResource hoặc chờ điều kiện bounded theo API test. Không đăng ký resource luôn “busy” hay dùng sleep để che race.

Compose test clock giúp điều khiển animation/recomposition theo API; nó không tự tiến server clock hoặc mọi coroutine dispatcher ngoài Compose. Kiểm tra boundary của clock đang dùng trước khi kết luận một delay được skip.

Nguồn: Compose synchronization, Espresso Idling Resources.

4. Ma trận UI đủ sát sản phẩm​

Trường hợpCần kiểm tra
Loading/error/retryCó trạng thái rõ, không submit lặp ngoài contract
Font scale/thiết bị nhỏNội dung và action chính vẫn dùng được
TalkBack/keyboardTên, role, focus và action phù hợp
Rotation/back stackInput/selection phục hồi đúng owner
Network hoàn tất lúc STOPPEDKhông truy cập View cũ; state quan trọng vẫn tồn tại
Process deathTest riêng, không đánh đồng recreate

Đọc tiếp: state recovery, custom View accessibility, test strategy.