Danh sách kiểm thử và bộ chuyển đổi

1. Trước khi bắt đầu

Trong các lớp học lập trình trước đây, bạn đã tìm hiểu cách viết và chạy cả phương thức kiểm thử đơn vị và phương thức kiểm thử đo lường. Lớp học lập trình này giới thiệu một số phương pháp hay nhất khi viết mã nguồn kiểm thử cũng như cách thêm một số phần phụ thuộc Gradle cụ thể để kiểm thử. Bạn cũng sẽ được luyện tập viết thêm một số mã nguồn kiểm thử đơn vị và kiểm thử đo lường.

Điều kiện tiên quyết

  • Bạn đã mở một dự án hiện có trong Android Studio.
  • Bạn đã viết mã nguồn kiểm thử đơn vị và kiểm thử đo lường trong Android Studio.
  • Bạn có một số kinh nghiệm về việc điều hướng các dự án trong Android Studio.
  • Bạn có một số kinh nghiệm xử lý các tệp build.gradle trong Android Studio.

Kiến thức bạn sẽ học được

  • Các nguyên tắc cơ bản về việc viết mã nguồn kiểm thử.
  • Cách thêm phần phụ thuộc Gradle cụ thể theo loại kiểm thử.
  • Cách kiểm thử danh sách bằng kiểm thử đo lường.

Bạn cần có

  • Một máy tính đã cài đặt Android Studio.
  • Mã nguồn giải pháp cho ứng dụng Affirmations (Châm ngôn).

Tải mã khởi đầu xuống cho lớp học lập trình này

Trong lớp học lập trình này, bạn sẽ thêm các bài kiểm thử đo lường vào mã nguồn giải pháp cho ứng dụng Affirmations.

  1. Chuyển đến trang kho lưu trữ GitHub được cung cấp cho dự án.
  2. Xác minh rằng tên nhánh khớp với tên nhánh được chỉ định trong lớp học lập trình. Ví dụ: trong ảnh chụp màn hình sau đây, tên nhánh là main.

1e4c0d2c081a8fd2.png

  1. Trên trang GitHub cho dự án này, nhấp vào nút Code (Mã). Thao tác này sẽ khiến một cửa sổ bật lên.

1debcf330fd04c7b.png

  1. Trong cửa sổ bật lên, nhấp vào nút Download ZIP (Tải tệp ZIP xuống) để lưu dự án vào máy tính. Chờ quá trình tải xuống hoàn tất.
  2. Xác định vị trí của tệp trên máy tính (thường nằm trong thư mục Downloads (Tệp đã tải xuống)).
  3. Nhấp đúp vào tệp ZIP để giải nén. Thao tác này sẽ tạo một thư mục mới chứa các tệp dự án.

Mở dự án trong Android Studio

  1. Khởi động Android Studio.
  2. Trong cửa sổ Welcome to Android Studio (Chào mừng bạn đến với Android Studio), hãy nhấp vào Open (Mở).

d8e9dbdeafe9038a.png

Lưu ý: Nếu Android Studio đã mở thì chuyển sang chọn tuỳ chọn File (Tệp) > Open (Mở) trong trình đơn.

8d1fda7396afe8e5.png

  1. Trong trình duyệt tệp, hãy chuyển đến vị trí của thư mục dự án chưa giải nén (thường nằm trong thư mục Downloads (Tệp đã tải xuống)).
  2. Nhấp đúp vào thư mục dự án đó.
  3. Chờ Android Studio mở dự án.
  4. Nhấp vào nút Run (Chạy) 8de56cba7583251f.png để xây dựng và chạy ứng dụng. Đảm bảo ứng dụng được xây dựng như mong đợi.

2. Tổng quan về ứng dụng khởi động

Ứng dụng Affirmations bao gồm một màn hình cho người dùng thấy một danh sách hình ảnh được ghép nối với các châm ngôn.

3. Những phương pháp hay nhất

Theo thiết kế, mã nguồn kiểm thử có vẻ khác với logic kinh doanh của một ứng dụng. Lý do là các bài kiểm thử không được chứa logic; người dùng chỉ nên kiểm thử logic đó. Do đó, mã nguồn kiểm thử không nên có các câu lệnh có điều kiện như if hoặc when hoặc câu lệnh luồng kiểm soát như for hoặc while. Ngoài ra, các bài kiểm thử không được sửa đổi các giá trị hoặc tiến hành tính toán thực sự.

Đôi khi, bài kiểm thử của bạn có thể cần đến một vài yếu tố trong số này, nhưng nhìn chung bạn nên tránh. Vì đây là loại logic mà chúng ta muốn kiểm thử trong ứng dụng của mình, nên nếu chúng ta có loại mã đó trong một bài kiểm thử, thì có thể mã đó cũng bị lỗi tương tự như cách mã ứng dụng của chúng ta có thể bị lỗi.

Trong kiểm thử đơn vị, bạn chỉ nên gọi đoạn mã trong ứng dụng cần thiết cho việc kiểm thử rồi kiểm thử giá trị hoặc trạng thái của mã có được từ quá trình gọi mã đó. Các bài kiểm thử giao diện người dùng chỉ nên kiểm thử trạng thái dự kiến của giao diện người dùng. Có thể phải mất một thời gian thì bạn mới làm quen được với ý tưởng này, nhưng không sao! Có một số chủ đề giúp giải thích ý tưởng này mà chúng tôi sẽ đề cập đến trong các lớp học lập trình sau này. Còn bây giờ, vì chúng ta phải viết nhiều bài kiểm thử hơn nên hãy chú ý thật kỹ đến phương pháp dùng để viết mã nguồn kiểm thử.

4. Tạo thư mục kiểm thử

Trong một lớp học lập trình trước, bạn đã tìm hiểu cách tạo thư mục androidTest phục vụ kiểm thử đo lường. Hãy lặp lại quá trình đó trong dự án này cho cả thư mục androidTest và thư mục test. Quy trình này như nhau cho cả hai, điểm khác biệt duy nhất là đối với thư mục test, bạn phải chọn test/java trong trình đơn thả xuống New Directory (Thư mục mới) thay vì androidTest/java. Tạo một gói mới cho mỗi thư mục mới với tên gọi com.example.affirmations.

d762ecd8950e97b2.png

5. Tạo lớp kiểm thử đo lường

Tạo một lớp mới trong androidTest -> com.example.affirmations với tên gọi AffirmationsListTests.kt.

Giống như ứng dụng Dice Roller (Xúc xắc), Affirmations cũng chỉ có một hoạt động duy nhất. Để kiểm thử giao diện người dùng của hoạt động này, chúng ta phải nêu rõ rằng chúng ta muốn chạy hoạt động này. Hãy xem liệu bạn có nhớ được cách tự thực hiện việc này hay không!

  1. Thêm trình chạy kiểm thử vào lớp mới tạo.
@RunWith(AndroidJUnit4::class)
  1. Tạo một quy tắc tình huống hoạt động cho hoạt động chính.
@get:Rule
val activity = ActivityScenarioRule(MainActivity::class.java)
  1. Affirmations thể hiện một danh sách hình ảnh và châm ngôn tích cực tương ứng. Giao diện người dùng không cho phép tương tác với các mục (chẳng hạn như nhấp hoặc vuốt). Vì vậy, đối với ứng dụng này, kiểm thử đo lường chỉ kiểm thử dữ liệu tĩnh. Tạo một phương thức kiểm thử có tên là scroll_to_item(). Hãy nhớ rằng bạn phải chú thích thẻ bằng @Test.

Bài kiểm thử này sẽ cuộn đến một mục cụ thể có trong danh sách. Chúng tôi chưa đề cập đến phương pháp này vì phương pháp này cần đến một phương thức mà dự án của chúng ta chưa dẫn chiếu đến. Trước khi tiếp tục kiểm thử, chúng ta cần thêm một số phần phụ thuộc kiểm thử.

6. Thêm các phần phụ thuộc cho kiểm thử đo lường

Bạn đã nắm rõ cách thêm phần phụ thuộc Gradle để sử dụng trong mã nguồn ứng dụng. Gradle cũng cho phép chúng ta thêm các phần phụ thuộc dành riêng cho kiểm thử đơn vị và kiểm thử đo lường. Mở tệp build.gradle ở cấp ứng dụng tại app -> build.gradle. Trong mục phần phụ thuộc, có 3 cách triển khai cho phần phụ thuộc implementation, testImplementation, và androidTestImplementation.

implementation dùng cho những phần phụ thuộc sẽ được dùng trong chính ứng dụng, testImplementation cho những phần phụ thuộc dùng trong kiểm thử đơn vị và androidTestImplementation cho những phần phụ thuộc dùng trong kiểm thử đo lường.

  1. Thêm một phần phụ thuộc để cho phép tương tác với RecyclerView trong kiểm thử đo lường. Thêm thư viện sau làm androidTestImplementation:
androidx.test.espresso:espresso-contrib:3.4.0

Các phần phụ thuộc có dạng như sau:

dependencies {
    ...
    androidTestImplementation
'androidx.test.espresso:espresso-contrib:3.4.0'
}
  1. Giờ hãy đồng bộ hoá dự án.

7. Kiểm thử RecyclerView

  1. Sau khi dự án được đồng bộ hoá, hãy quay trở lại tệp AffirmationsListTests.kt. Cung cấp một ViewInteraction để thực hiện một thao tác với onView(). Phương thức onView() yêu cầu phải có ViewMatcher để được truyền vào. Hãy sử dụng withId() và nhớ truyền mã nhận dạng của RecyclerView (dùng cho các câu châm ngôn). Bây giờ, hãy gọi perform() trên ViewInteraction. Đây là khi phần phụ thuộc mới thêm có tác dụng! Bây giờ bạn có thể truyền RecyclerViewActions.scrollToPosition<RecyclerView.Viewholder>(9) ViewAction.
onView(withId(R.id.recycler_view)).perform(
   RecyclerViewActions
       .scrollToPosition<RecyclerView.ViewHolder>(9)
)

Bạn không nhất thiết phải hiểu cú pháp của dòng này nhưng rất đáng tìm hiểu. Tên RecyclerViewActions mang đúng ý nghĩa của nó: một lớp cho phép các bài kiểm thử thao tác trên RecyclerView. scrollToPosition() là một phương thức tĩnh thuộc lớp RecyclerViewActions mà sẽ cuộn đến một vị trí cụ thể. Phương thức này trả về một giá trị được gọi là Generic (Chung). Giá trị Generic (Chung) nằm ngoài phạm vi của lớp học lập trình này, nhưng trong trường hợp này, bạn có thể coi đây là phương thức scrollToPosition() trả về mục bất kỳ trong RecyclerView.

Trong ứng dụng, các mục trong RecyclerView của chúng ta là ViewHolder, do đó, chúng ta đặt một cặp dấu ngoặc nhọn sau lệnh gọi phương thức và trong đó chúng ta chỉ định RecyclerView.ViewHolder. Cuối cùng, hãy truyền vào vị trí cuối cùng trong danh sách (9).

  1. Giờ đây, khi đã bật tính năng cuộn đến vị trí mong muốn của RecyclerView, hãy xác nhận để đảm bảo rằng giao diện người dùng đang thể hiện thông tin như dự kiến. Đảm bảo rằng sau khi bạn cuộn đến mục cuối cùng, văn bản được liên kết với câu châm ngôn cuối cùng sẽ xuất hiện. Bắt đầu với ViewInteraction, nhưng lần này sẽ chuyển sang một ViewMatcher mới (trong trường hợp này là withText()). Với phương thức đó, hãy truyền tài nguyên chuỗi chứa văn bản của câu châm ngôn cuối cùng. Phương thức withText() xác định một thành phần giao diện người dùng dựa trên văn bản mà thành phần đó thể hiện. Đối với thành phần này, tất cả những gì bạn cần làm là kiểm tra để chắc chắn rằng thành phần này hiện đúng văn bản bạn muốn. Bạn có thể thực hiện việc này bằng cách gọi check() trên ViewInteraction. check() cần phải có ViewAssertion. Bạn có thể sử dụng phương thức matches() này. Cuối cùng, hãy khẳng định rằng thành phần giao diện người dùng sẽ xuất hiện bằng cách truyền phương thức isDisplayed().
onView(withText(R.string.affirmation10))
    .check(matches(isDisplayed()))

Quay lại phần lưu ý về việc mã hoá cứng một vị trí để cuộn đến, bạn có thể khắc phục vấn đề này bằng cách sử dụng RecyclerViewActions. Khi không chắc chắn về độ dài danh sách, bạn có thể sử dụng thao tác scrollTo. Hàm scrollTo cần có Matcher<View!>! để tìm một mục cụ thể. Có thể là một số mục, nhưng để phục vụ mục đích của kiểm thử này, hãy sử dụng withText. Áp dụng vào mã nguồn kiểm thử bạn vừa viết, mã nguồn này sẽ có dạng như sau:

onView(withId(R.id.recycler_view)).perform(
   RecyclerViewActions
       .scrollTo<RecyclerView.ViewHolder>(
           withText(R.string.affirmation10)
       )
)

onView(withText(R.string.affirmation10))
    .check(matches(isDisplayed())
)

Giờ đây, bạn đã chuẩn bị xong mọi thứ để chạy kiểm thử. Bạn sẽ thấy thiết bị hoặc trình mô phỏng cuộn xuống cuối danh sách, cuối cùng thì kiểm thử cũng đạt. Nếu bạn muốn đảm bảo rằng kết quả kiểm thử là chính xác, hãy thay thế mã chuỗi bằng R.string.affirmation1. Sau khi cuộn, tài nguyên chuỗi này sẽ không xuất hiện và kiểm thử sẽ không đạt.

Có một số phương thức có sẵn trong lớp RecyclerViewActions và bạn nên xem qua các phương thức hiện có.

8. Tạo một lớp kiểm thử cục bộ

Tạo một lớp mới trong test -> com.example.affirmations với tên gọi AffirmationsAdapterTests.kt.

9. Thêm các phần phụ thuộc kiểm thử cục bộ

  1. Trước đó, trong lớp học lập trình này, chúng tôi đã thảo luận về ba hình thức triển khai phần phụ thuộc và bạn cũng đã thêm một phần phụ thuộc cho các kiểm thử đo lường. Bây giờ, hãy thêm phần phụ thuộc cho các kiểm thử cục bộ. Chuyển đến app -> build.gradle rồi thêm nội dung sau dưới dạng phần phụ thuộc kiểm thử đơn vị:
org.mockito:mockito-core:3.12.4

Các phần phụ thuộc sẽ có dạng như sau:

dependencies {
    ...
    testImplementation 'org.mockito:mockito-core:3.12.4'
}
  1. Giờ hãy đồng bộ hoá dự án.

10. Kiểm thử bộ chuyển đổi

Ứng dụng cụ thể này không hỗ trợ kiểm thử đơn vị vì không có nhiều logic để kiểm thử. Tuy nhiên, chúng ta có thể có thêm một số kinh nghiệm về việc kiểm thử nhiều thành phần, chuẩn bị cho những bài kiểm thử trong tương lai.

  1. Đặt dòng sau vào lớp kiểm thử đơn vị:
private val context = mock(Context::class.java)

Phương thức mock() đến từ thư viện mà chúng ta vừa triển khai trong dự án. Mô phỏng là một phần không tách rời kiểm thử đơn vị, nhưng lại nằm ngoài phạm vi của lớp học lập trình này. Chúng ta sẽ xem xét hoạt động mô phỏng một cách chi tiết hơn trong một lớp học lập trình khác. Trên Android, Context là ngữ cảnh của trạng thái hiện tại trong ứng dụng. Tuy nhiên, hãy nhớ rằng các kiểm thử đơn vị chạy trên JVM chứ không phải trên thiết bị thực tế, vì vậy không có Context. Phương thức mô phỏng cho phép chúng ta tạo phiên bản "mô phỏng" của Context. Nó không có chức năng thực nào, nhưng có thể được dùng để kiểm thử các phương thức cần có ngữ cảnh.

  1. Tạo một hàm có tên là adapter_size() rồi chú thích việc hàm đó là một hàm kiểm thử. Mục tiêu của kiểm thử này là đảm bảo rằng kích thước của bộ chuyển đổi là kích thước của danh sách đã được chuyển tới bộ chuyển đổi. Để thực hiện việc này, hãy tạo một phiên bản của ItemAdapter rồi chuyển vào danh sách trả về bằng phương thức loadAffirmations() trong lớp Datasource. Ngoài ra, bạn có thể tạo một danh sách mới rồi kiểm thử danh sách đó. Đối với kiểm thử đơn vị, phương pháp hay nhất là tạo dữ liệu riêng của chúng ta cho bài kiểm thử, vì vậy, chúng ta sẽ tạo một danh sách tuỳ chỉnh cho bài kiểm thử này.
val data = listOf(
   Affirmation(R.string.affirmation1, R.drawable.image1),
   Affirmation(R.string.affirmation2, R.drawable.image2)
)
  1. Bây giờ, hãy tạo một phiên bản của ItemAdapter, truyền vào các biến contextdata đã tạo ở các bước trước đó.
val adapter = ItemAdapter(context, data)

Bộ chuyển đổi RecyclerView có một phương thức trả về kích thước của bộ chuyển đổi với tên gọi getItemCount(). Đối với ứng dụng này, phương thức có dạng như sau:

/**
* Return the size of your dataset (invoked by the layout manager)
*/
override fun getItemCount() = dataset.size
  1. Đây là phương thức cần được kiểm thử. Hãy đảm bảo rằng giá trị trả về qua phương thức này khớp với kích thước của danh sách mà bạn đã tạo ở bước 2. Sử dụng phương thức assertEquals() và so sánh các giá trị của kích thước danh sách và kích thước bộ chuyển đổi.
assertEquals("ItemAdapter is not the correct size", data.size, adapter.itemCount)

Bạn đã quen với phương thức assertEquals(). Tuy nhiên, bạn nên kiểm tra kỹ lưỡng dòng lệnh. Thông số đầu tiên là một chuỗi xuất hiện trong kết quả kiểm thử nếu lượt kiểm thử không đạt. Tham số thứ hai là giá trị dự kiến. Tham số thứ ba là giá trị thực tế. Lớp kiểm thử của bạn sẽ có dạng như sau:

f81a27f5c1cf055e.png

  1. Bây giờ, hãy chạy kiểm thử!

11. Mã nguồn giải pháp

12. Xin chúc mừng

Trong lớp học lập trình này, bạn đã:

  • Tìm hiểu cách thêm các phần phụ thuộc cụ thể theo loại kiểm thử.
  • Tìm hiểu cách tương tác với một RecyclerView bằng các bài kiểm thử đo lường.
  • Thảo luận về một số phương pháp cơ bản hay nhất để kiểm thử.