Tài nguyên về trạng thái rảnh Espresso

Tài nguyên không đồng bộ thể hiện một hoạt động không đồng bộ có kết quả ảnh hưởng đến các hoạt động tiếp theo trong kiểm thử giao diện người dùng. Bằng cách đăng ký tài nguyên ở trạng thái rảnh bằng Espresso, bạn có thể xác thực các hoạt động không đồng bộ này một cách đáng tin cậy hơn khi kiểm thử ứng dụng.

Xác định thời điểm cần tài nguyên không hoạt động

Espresso cung cấp một tập hợp khả năng đồng bộ hoá tinh vi. Tuy nhiên, đặc điểm này của khung chỉ áp dụng cho các thao tác đăng thông báo trên MessageQueue, chẳng hạn như một lớp con của View đang vẽ nội dung trên màn hình.

Do Espresso không nhận biết được bất kỳ hoạt động không đồng bộ nào khác, bao gồm cả những hoạt động chạy trên luồng trong nền, nên Espresso không thể đảm bảo việc đồng bộ hoá trong những trường hợp đó. Để giúp Espresso biết được các hoạt động diễn ra trong thời gian dài của ứng dụng, bạn phải đăng ký từng thao tác làm tài nguyên ở trạng thái rảnh.

Nếu không sử dụng tài nguyên không hoạt động khi kiểm thử kết quả công việc không đồng bộ của ứng dụng, thì có thể bạn sẽ phải dùng một trong những giải pháp không hợp lệ sau đây để cải thiện độ tin cậy của chương trình kiểm thử:

  • Thêm lệnh gọi vào Thread.sleep(). Khi bạn thêm độ trễ nhân tạo vào chương trình kiểm thử, bộ kiểm thử sẽ mất nhiều thời gian hơn để hoàn tất quá trình thực thi và đôi khi chương trình kiểm thử của bạn có thể vẫn không thành công khi được thực thi trên thiết bị chậm hơn. Ngoài ra, những độ trễ này sẽ không mở rộng hiệu quả vì ứng dụng của bạn có thể phải thực hiện công việc không đồng bộ tốn nhiều thời gian hơn trong bản phát hành sau này.
  • Triển khai trình bao bọc thử lại (dùng một vòng lặp để liên tục kiểm tra xem ứng dụng của bạn có đang thực hiện công việc không đồng bộ cho đến khi hết thời gian chờ hay không). Ngay cả khi bạn chỉ định số lần thử lại tối đa trong các lần kiểm thử, mỗi lần thực thi lại vẫn sẽ tiêu tốn tài nguyên hệ thống, đặc biệt là CPU.
  • Sử dụng các thực thể của CountDownLatch để cho phép một hoặc nhiều luồng chờ cho đến khi một số thao tác cụ thể được thực thi trong một luồng khác hoàn tất. Các đối tượng này yêu cầu bạn chỉ định khoảng thời gian chờ; nếu không, ứng dụng của bạn có thể bị chặn vô thời hạn. Các chốt cũng làm tăng độ phức tạp không cần thiết vào mã của bạn, khiến việc bảo trì trở nên khó khăn hơn.

Espresso cho phép bạn xoá các giải pháp không đáng tin cậy khỏi quy trình kiểm thử và thay vào đó, hãy đăng ký công việc không đồng bộ của ứng dụng dưới dạng tài nguyên rảnh.

Các trường hợp sử dụng phổ biến

Khi thực hiện các thao tác tương tự như các ví dụ sau trong chương trình kiểm thử, hãy cân nhắc sử dụng tài nguyên không hoạt động:

  • Tải dữ liệu từ Internet hoặc một nguồn dữ liệu cục bộ.
  • Thiết lập kết nối bằng cơ sở dữ liệu và lệnh gọi lại.
  • Quản lý dịch vụ, bằng cách sử dụng dịch vụ hệ thống hoặc thực thể của IntentService.
  • Thực hiện logic kinh doanh phức tạp, chẳng hạn như các phép biến đổi bitmap.

Điều đặc biệt quan trọng là phải đăng ký tài nguyên không hoạt động khi các thao tác này cập nhật giao diện người dùng mà sau đó quá trình kiểm thử sẽ xác thực.

Ví dụ về cách triển khai tài nguyên không hoạt động

Danh sách sau đây mô tả một số ví dụ về cách triển khai tài nguyên không hoạt động mà bạn có thể tích hợp vào ứng dụng:

CountingIdlingResource
Duy trì bộ đếm số tác vụ đang hoạt động. Khi bộ đếm bằng 0, tài nguyên liên kết sẽ được coi là không hoạt động. Chức năng này gần giống với chức năng của Semaphore. Trong hầu hết các trường hợp, phương thức triển khai này là đủ để quản lý công việc không đồng bộ của ứng dụng trong quá trình kiểm thử.
UriIdlingResource
Tương tự như CountingIdlingResource, nhưng bộ đếm cần phải bằng 0 trong một khoảng thời gian cụ thể trước khi tài nguyên được coi là ở trạng thái rảnh. Thời gian chờ bổ sung này sẽ tính đến các yêu cầu mạng liên tiếp, trong đó ứng dụng trong luồng có thể thực hiện một yêu cầu mới ngay sau khi nhận được phản hồi cho yêu cầu trước đó.
IdlingThreadPoolExecutor
Cách triển khai tuỳ chỉnh của ThreadPoolExecutor theo dõi tổng số tác vụ đang chạy trong nhóm luồng đã tạo. Lớp này sử dụng CountingIdlingResource để duy trì bộ đếm các tác vụ đang hoạt động.
IdlingScheduledThreadPoolExecutor
Cách triển khai tuỳ chỉnh của ScheduledThreadPoolExecutor. Lớp này cung cấp chức năng và chức năng giống như lớp IdlingThreadPoolExecutor, nhưng cũng có thể theo dõi các tác vụ được lên lịch trong tương lai hoặc được lên lịch thực thi định kỳ.

Tạo tài nguyên không hoạt động của riêng bạn

Khi sử dụng tài nguyên không hoạt động trong các kiểm thử của ứng dụng, bạn có thể cần cung cấp tính năng ghi nhật ký hoặc quản lý tài nguyên tuỳ chỉnh. Trong những trường hợp đó, cách triển khai được liệt kê trong phần trước có thể là chưa đủ. Trong trường hợp đó, bạn có thể mở rộng một trong các phương thức triển khai tài nguyên không hoạt động này hoặc tự tạo phương thức triển khai của riêng mình.

Nếu bạn triển khai chức năng tài nguyên không hoạt động của riêng mình, hãy lưu ý các phương pháp hay nhất sau đây, đặc biệt là phương pháp đầu tiên:

Gọi các lượt chuyển đổi sang trạng thái rảnh bên ngoài các bước kiểm tra ở trạng thái rảnh.
Sau khi ứng dụng chuyển sang trạng thái rảnh, hãy gọi onTransitionToIdle() bên ngoài mọi phương thức triển khai isIdleNow(). Nhờ đó, Espresso không thực hiện bước kiểm tra thứ hai không cần thiết để xác định xem một tài nguyên rảnh nhất định có đang rảnh hay không.

Đoạn mã sau đây minh hoạ đề xuất này:

Kotlin

fun isIdle() {
    // DON'T call callback.onTransitionToIdle() here!
}

fun backgroundWorkDone() {
    // Background work finished.
    callback.onTransitionToIdle() // Good. Tells Espresso that the app is idle.

    // Don't do any post-processing work beyond this point. Espresso now
    // considers your app to be idle and moves on to the next test action.
}

Java

public void isIdle() {
    // DON'T call callback.onTransitionToIdle() here!
}

public void backgroundWorkDone() {
    // Background work finished.
    callback.onTransitionToIdle() // Good. Tells Espresso that the app is idle.

    // Don't do any post-processing work beyond this point. Espresso now
    // considers your app to be idle and moves on to the next test action.
}
Đăng ký tài nguyên ở trạng thái rảnh trước khi bạn cần đến.

Các lợi ích đồng bộ hoá liên quan đến tài nguyên ở trạng thái rảnh chỉ có hiệu lực sau lệnh gọi đầu tiên của Espresso cho phương thức isIdleNow() của tài nguyên đó.

Danh sách sau đây trình bày một số ví dụ về tài sản này:

  • Nếu bạn đăng ký tài nguyên không hoạt động trong phương thức được chú giải bằng @Before, thì tài nguyên đang rảnh sẽ có hiệu lực ở dòng đầu tiên của mỗi lượt kiểm thử.
  • Nếu bạn đăng ký một tài nguyên đang rảnh bên trong quy trình kiểm thử, thì tài nguyên đó sẽ có hiệu lực trong thao tác tiếp theo dựa trên Espresso. Hành vi này vẫn xảy ra ngay cả khi hành động tiếp theo nằm trong cùng một bài kiểm thử với câu lệnh đăng ký tài nguyên không hoạt động.
Huỷ đăng ký tài nguyên ở trạng thái rảnh sau khi sử dụng xong.

Để tiết kiệm tài nguyên hệ thống, bạn nên huỷ đăng ký các tài nguyên ở trạng thái rảnh ngay khi không cần đến nữa. Ví dụ: nếu đăng ký một tài nguyên không hoạt động trong một phương thức được chú thích bằng @Before, tốt nhất là bạn nên huỷ đăng ký tài nguyên này bằng một phương thức tương ứng được chú thích bằng @After.

Sử dụng sổ đăng ký không hoạt động để đăng ký và huỷ đăng ký các tài nguyên không hoạt động.

Bằng cách sử dụng vùng chứa này cho các tài nguyên đang rảnh của ứng dụng, bạn có thể đăng ký và huỷ đăng ký các tài nguyên đang rảnh nhiều lần nếu cần mà vẫn tuân thủ hành vi nhất quán.

Chỉ duy trì trạng thái ứng dụng đơn giản trong các tài nguyên đang rảnh.

Ví dụ: các tài nguyên không hoạt động mà bạn triển khai và đăng ký không được chứa thông tin tham chiếu đến các đối tượng View.

Đăng ký tài nguyên không hoạt động

Espresso cung cấp một lớp vùng chứa để bạn có thể đặt các tài nguyên đang rảnh của ứng dụng. Lớp này có tên là IdlingRegistry, là một cấu phần phần mềm độc lập giúp ứng dụng của bạn giảm thiểu hao tổn. Lớp này cũng cho phép bạn thực hiện các bước sau đây để cải thiện khả năng bảo trì của ứng dụng:

  • Tạo tham chiếu đến IdlingRegistry thay vì các tài nguyên trạng thái rảnh có trong đó, trong các chương trình kiểm thử của ứng dụng.
  • Duy trì sự khác biệt trong việc thu thập tài nguyên ở trạng thái rảnh mà bạn dùng cho từng biến thể bản dựng.
  • Xác định các tài nguyên không hoạt động trong các dịch vụ của ứng dụng, thay vì trong các thành phần giao diện người dùng tham chiếu đến các dịch vụ đó.

Tích hợp các tài nguyên không hoạt động vào ứng dụng

Mặc dù bạn có thể thêm các tài nguyên không hoạt động vào ứng dụng theo nhiều cách, nhưng có một phương pháp cụ thể sẽ duy trì việc đóng gói cho ứng dụng của bạn trong khi vẫn cho phép bạn chỉ định một thao tác cụ thể mà một tài nguyên không hoạt động nhất định đại diện.

Khi thêm các tài nguyên không hoạt động vào ứng dụng của mình, bạn nên đặt logic tài nguyên rảnh trong chính ứng dụng đó và chỉ thực hiện các thao tác đăng ký và huỷ đăng ký trong các chương trình kiểm thử.

Mặc dù bạn tạo ra tình huống bất thường khi sử dụng giao diện chỉ dành cho kiểm thử trong mã sản xuất bằng cách làm theo phương pháp này, nhưng bạn có thể gói các tài nguyên không hoạt động xung quanh mã mà bạn đã có, duy trì kích thước APK và số lượng phương thức của ứng dụng.

Phương pháp thay thế

Nếu bạn không muốn có logic tài nguyên không hoạt động trong mã phát hành chính thức của ứng dụng, có một số chiến lược tích hợp khả thi khác:

  • Tạo các biến thể bản dựng, chẳng hạn như phiên bản sản phẩm của Gradle và chỉ sử dụng tài nguyên không hoạt động trong bản gỡ lỗi của ứng dụng.
  • Sử dụng một khung chèn phần phụ thuộc như Dagger để chèn biểu đồ phần phụ thuộc tài nguyên đang không hoạt động của ứng dụng vào chương trình kiểm thử của bạn. Nếu bạn đang sử dụng Dagger 2, thì quá trình chèn phải bắt nguồn từ một thành phần phụ.
  • Triển khai tài nguyên không hoạt động trong các chương trình kiểm thử của ứng dụng và hiển thị phần triển khai của ứng dụng cần được đồng bộ hoá trong các chương trình kiểm thử đó.

    Thận trọng: Mặc dù quyết định thiết kế này có vẻ như tạo ra dữ liệu tham chiếu độc lập đến các tài nguyên ở trạng thái rảnh, nhưng nó cũng phá vỡ hoạt động đóng gói trong tất cả ứng dụng, trừ những ứng dụng đơn giản nhất.

Tài nguyên khác

Để biết thêm thông tin về cách sử dụng Espresso trong kiểm thử Android, hãy tham khảo các tài nguyên sau.

Mẫu