Đồng bộ hoá chương trình kiểm thử

Các quy trình kiểm thử Compose được đồng bộ hoá theo mặc định với giao diện người dùng. Khi bạn gọi một câu nhận định hoặc một hành động bằng ComposeTestRule, quy trình kiểm thử sẽ được đồng bộ hoá trước, chờ cho đến khi cây giao diện người dùng không hoạt động.

Thông thường, bạn không phải thực hiện bất kỳ hành động nào. Tuy nhiên, có một số trường hợp phức tạp (edge case) mà bạn nên biết.

Khi một quy trình kiểm thử được đồng bộ hoá, ứng dụng Compose của bạn được đẩy nhanh thời gian bằng cách sử dụng đồng hồ ảo. Điều này có nghĩa là các quy trình kiểm thử Compose không chạy trong thời gian thực, cho nên các quy trình kiểm thử này có thể được thực hiện nhanh nhất trong khả năng.

Tuy nhiên, nếu bạn không sử dụng các phương thức đồng bộ hoá quy trình kiểm thử thì sẽ không xảy ra quá trình kết hợp lại và giao diện người dùng sẽ tạm dừng.

@Test
fun counterTest() {
    val myCounter = mutableStateOf(0) // State that can cause recompositions.
    var lastSeenValue = 0 // Used to track recompositions.
    composeTestRule.setContent {
        Text(myCounter.value.toString())
        lastSeenValue = myCounter.value
    }
    myCounter.value = 1 // The state changes, but there is no recomposition.

    // Fails because nothing triggered a recomposition.
    assertTrue(lastSeenValue == 1)

    // Passes because the assertion triggers recomposition.
    composeTestRule.onNodeWithText("1").assertExists()
}

Xin lưu ý rằng yêu cầu này chỉ áp dụng cho hệ phân cấp Compose chứ không áp dụng cho phần còn lại của ứng dụng.

Tắt tính năng tự động đồng bộ hoá

Khi bạn gọi một câu nhận định (assertion) hoặc hành động thông qua ComposeTestRule chẳng hạn như assertExists(), quy trình kiểm thử của bạn sẽ được đồng bộ hoá với giao diện người dùng Compose. Trong một số trường hợp, bạn có thể dừng quá trình đồng bộ hoá này và tự điều khiển đồng hồ. Ví dụ: bạn có thể kiểm soát thời gian để chụp ảnh màn hình chính xác của một ảnh động tại thời điểm giao diện người dùng vẫn bận. Để tắt tính năng đồng bộ hoá tự động, hãy đặt thuộc tính autoAdvance trong mainClock thành false:

composeTestRule.mainClock.autoAdvance = false

Thông thường, sau đó bạn sẽ tự chuyển đến thời gian của mình. Bạn có thể chuyển đến chính xác một khung bằng advanceTimeByFrame() hoặc chuyển đến một khoảng thời gian cụ thể bằng advanceTimeBy():

composeTestRule.mainClock.advanceTimeByFrame()
composeTestRule.mainClock.advanceTimeBy(milliseconds)

Tài nguyên rảnh

Compose có thể đồng bộ hoá các quy trình kiểm thử và giao diện người dùng để mọi hành động và câu nhận định (assertion) được thực hiện ở trạng thái rảnh, chờ hoặc đẩy nhanh đồng hồ khi cần. Tuy nhiên, một số tác vụ không đồng bộ có kết quả ảnh hưởng đến trạng thái giao diện người dùng có thể chạy ở chế độ nền và quy trình kiểm thử không nhận biết được điều này.

Tạo và đăng ký các tài nguyên không tải này trong quy trình kiểm thử để các tài nguyên này có thể được xem xét khi quyết định xem ứng dụng đang kiểm thử đang bận hay ở trạng thái rảnh. Bạn không phải làm gì, trừ trường hợp cần đăng ký tài nguyên không đồng bộ bổ sung, chẳng hạn như khi chạy công việc trong nền không được đồng bộ hoá với Espresso hoặc Compose.

API này rất giống với Tài nguyên không tải của Espresso để cho biết rằng đối tượng đang kiểm thử có đang rảnh hay bận. Sử dụng quy tắc kiểm thử Compose để đăng ký phương thức triển khai IdlingResource.

composeTestRule.registerIdlingResource(idlingResource)
composeTestRule.unregisterIdlingResource(idlingResource)

Đồng bộ hoá thủ công

Trong một số trường hợp, bạn phải đồng bộ hoá giao diện người dùng Compose với các phần khác trong quy trình kiểm thử hoặc ứng dụng đang kiểm thử.

Hàm waitForIdle() chờ Compose ở trạng thái rảnh, nhưng hàm này còn tuỳ thuộc vào thuộc tính autoAdvance:

composeTestRule.mainClock.autoAdvance = true // Default
composeTestRule.waitForIdle() // Advances the clock until Compose is idle.

composeTestRule.mainClock.autoAdvance = false
composeTestRule.waitForIdle() // Only waits for idling resources to become idle.

Xin lưu ý rằng trong cả hai trường hợp, waitForIdle() cũng sẽ đợi các lượt vẽ và bố cục đang chờ xử lý.

Ngoài ra, bạn có thể chuyển đồng hồ cho đến khi đáp ứng một điều kiện nhất định bằng advanceTimeUntil().

composeTestRule.mainClock.advanceTimeUntil(timeoutMs) { condition }

Lưu ý rằng điều kiện trên phải được kiểm tra trạng thái có thể bị ảnh hưởng bởi đồng hồ này (chỉ hoạt động với trạng thái Compose).

Chờ điều kiện

Mọi điều kiện phụ thuộc vào công việc bên ngoài, chẳng hạn như tải dữ liệu hoặc đo lường hoặc vẽ của Android (nghĩa là đo lường hoặc vẽ bên ngoài Compose), phải sử dụng khái niệm chung hơn, chẳng hạn như waitUntil():

composeTestRule.waitUntil(timeoutMs) { condition }

Bạn cũng có thể sử dụng bất kỳ trợ giúp waitUntil nào:

composeTestRule.waitUntilAtLeastOneExists(matcher, timeoutMs)

composeTestRule.waitUntilDoesNotExist(matcher, timeoutMs)

composeTestRule.waitUntilExactlyOneExists(matcher, timeoutMs)

composeTestRule.waitUntilNodeCount(matcher, count, timeoutMs)

Tài nguyên khác

  • Kiểm thử ứng dụng trên Android: Trang đích chính về kiểm thử Android cung cấp thông tin tổng quan hơn về các nguyên tắc và kỹ thuật kiểm thử.
  • Kiến thức cơ bản về kiểm thử: Tìm hiểu thêm về các khái niệm cốt lõi đằng sau việc kiểm thử ứng dụng Android.
  • Kiểm thử cục bộ: Bạn có thể chạy một số bài kiểm thử cục bộ trên máy trạm của riêng mình.
  • Kiểm thử đo lường: Bạn cũng nên chạy kiểm thử đo lường. Tức là các chương trình kiểm thử chạy trực tiếp trên thiết bị.
  • Tích hợp liên tục: Tích hợp liên tục cho phép bạn tích hợp các chương trình kiểm thử vào quy trình triển khai.
  • Kiểm thử nhiều kích thước màn hình: Khi người dùng có nhiều thiết bị, bạn nên kiểm thử nhiều kích thước màn hình.
  • Espresso: Mặc dù dành cho giao diện người dùng dựa trên Khung hiển thị, nhưng kiến thức về Espresso vẫn có thể hữu ích cho một số khía cạnh của hoạt động kiểm thử Compose.