Nguyên tắc cơ bản về việc kiểm thử ứng dụng Android

Trang này trình bày nguyên lý cốt lõi của việc kiểm thử ứng dụng Android, bao gồm cả các phương pháp hay nhất tập trung và lợi ích của các phương pháp đó.

Lợi ích của việc kiểm thử

Kiểm thử là một phần quan trọng trong quá trình phát triển ứng dụng. Bằng cách chạy các quy trình kiểm thử cho ứng dụng một cách nhất quán, bạn có thể xác minh độ chính xác, hành vi chức năng và khả năng hữu dụng của ứng dụng trước khi phát hành chính thức.

Bạn có thể kiểm thử ứng dụng theo cách thủ công bằng cách di chuyển trong ứng dụng. Bạn có thể sử dụng các thiết bị và trình mô phỏng khác nhau, thay đổi ngôn ngữ hệ thống và cố gắng tạo mọi lỗi người dùng hoặc truyền tải mọi luồng người dùng.

Tuy nhiên, quy trình kiểm thử thủ công sẽ có quy mô kém và bạn có thể dễ dàng bỏ qua sự hồi quy trong hành vi của ứng dụng. Kiểm thử tự động bao gồm việc sử dụng các công cụ giúp thực hiện kiểm thử cho bạn, phương pháp này nhanh hơn, có thể lặp lại nhiều hơn và thường cung cấp cho bạn ý kiến phản hồi hữu ích hơn về ứng dụng trước đó trong quá trình phát triển.

Các loại hình kiểm thử trong Android

Ứng dụng dành cho thiết bị di động rất phức tạp và phải hoạt động tốt trong nhiều môi trường. Do đó, sẽ có nhiều loại kiểm thử.

Tiêu đề

Ví dụ: có nhiều loại thử nghiệm tuỳ thuộc vào chủ đề:

  • Kiểm thử chức năng: ứng dụng của tôi có làm những việc mong muốn không?
  • Thử nghiệm hiệu suất: thử nghiệm có thực hiện nhanh chóng và hiệu quả không?
  • Kiểm tra khả năng hỗ trợ tiếp cận: có hoạt động tốt với các dịch vụ hỗ trợ tiếp cận không?
  • Kiểm tra tính tương thích: thử nghiệm có hoạt động tốt trên mọi thiết bị và cấp độ API không?

Phạm vi

Các thử nghiệm cũng khác nhau tuỳ thuộc vào kích thước hoặc mức độ tách biệt:

  • Kiểm thử đơn vị hoặc kiểm thử nhỏ chỉ xác minh một phần rất nhỏ của ứng dụng, chẳng hạn như một phương thức hoặc lớp.
  • Các hoạt động kiểm thử từ đầu đến cuối hoặc kiểm thử lớn sẽ xác minh các phần lớn hơn của ứng dụng cùng một lúc, chẳng hạn như toàn bộ màn hình hoặc luồng người dùng.
  • Kiểm thử trung bình nằm ở giữa và kiểm tra việc tích hợp giữa hai đơn vị trở lên.
Các thử nghiệm có thể có quy mô nhỏ, trung bình hoặc lớn.
Hình 1: Phạm vi kiểm thử trong một ứng dụng thông thường.

Có nhiều cách để phân loại bài kiểm thử. Tuy nhiên, điểm khác biệt quan trọng nhất đối với nhà phát triển ứng dụng là nơi chạy kiểm thử.

Kiểm thử đo lường so với kiểm thử cục bộ

Bạn có thể chạy kiểm thử trên thiết bị Android hoặc trên một máy tính khác:

  • Kiểm thử đo lường sẽ chạy trên một thiết bị Android, cả thiết bị thực hoặc thiết bị mô phỏng. Ứng dụng này được xây dựng và cài đặt cùng với một ứng dụng kiểm thử chèn lệnh và đọc trạng thái. Các hoạt động kiểm thử được đo lường thường là kiểm thử giao diện người dùng, khởi chạy một ứng dụng, sau đó tương tác với ứng dụng đó.
  • Kiểm thử cục bộ thực thi trên máy phát triển hoặc máy chủ của bạn, vì vậy, các bài kiểm thử này còn được gọi là kiểm thử phía máy chủ. Chúng thường có kích thước nhỏ và nhanh, tách biệt đối tượng kiểm thử với phần còn lại của ứng dụng.
Các kiểm thử có thể chạy dưới dạng kiểm thử đo lường trên một thiết bị hoặc kiểm thử cục bộ trên máy phát triển của bạn.
Hình 2: Các loại kiểm thử tuỳ thuộc vào nơi chạy.

Không phải bài kiểm thử đơn vị nào cũng là cục bộ và không phải bài kiểm thử toàn diện nào cũng chạy trên một thiết bị. Ví dụ:

  • Kiểm thử cục bộ lớn: Bạn có thể sử dụng trình mô phỏng Android chạy cục bộ, chẳng hạn như Robolectric.
  • Kiểm thử đo lường nhỏ: Bạn có thể xác minh rằng mã của mình hoạt động tốt với một tính năng khung, chẳng hạn như cơ sở dữ liệu SQLite. Bạn có thể chạy bài kiểm thử này trên nhiều thiết bị để kiểm tra việc tích hợp với nhiều phiên bản SQLite.

Ví dụ

Các đoạn mã sau đây minh hoạ cách tương tác với giao diện người dùng trong quy trình kiểm thử giao diện người dùng được đo lường. Quy trình này nhấp vào một phần tử và xác minh rằng một phần tử khác sẽ hiển thị.

Espresso

// When the Continue button is clicked
onView(withText("Continue"))
    .perform(click())

// Then the Welcome screen is displayed
onView(withText("Welcome"))
    .check(matches(isDisplayed()))

Giao diện người dùng Compose

// When the Continue button is clicked
composeTestRule.onNodeWithText("Continue").performClick()

// Then the Welcome screen is displayed
composeTestRule.onNodeWithText("Welcome").assertIsDisplayed()

Đoạn mã này cho thấy một phần của quy trình kiểm thử đơn vị cho ViewModel (kiểm thử cục bộ, phía máy chủ):

// Given an instance of MyViewModel
val viewModel = MyViewModel(myFakeDataRepository)

// When data is loaded
viewModel.loadData()

// Then it should be exposing data
assertTrue(viewModel.data != null)

Xác định chiến lược kiểm thử

Lý tưởng nhất là bạn nên kiểm thử mọi dòng mã trong ứng dụng trên mọi thiết bị tương thích với ứng dụng. Thật không may, phương pháp này quá chậm và chi phí để áp dụng vào thực tế.

Một chiến lược kiểm thử hiệu quả sẽ tìm được sự cân bằng phù hợp giữa độ chân thực của bài kiểm thử, tốc độ và độ tin cậy của bài kiểm thử đó. Mức độ tương đồng của môi trường kiểm thử với thiết bị thực tế sẽ xác định độ trung thực của kiểm thử. Các bài kiểm thử độ chân thực cao hơn chạy trên các thiết bị được mô phỏng hoặc trên chính thiết bị thực. Các phép kiểm thử độ trung thực thấp hơn có thể chạy trên JVM của máy trạm cục bộ. Các hoạt động kiểm thử độ chân thực cao thường chậm hơn và đòi hỏi nhiều tài nguyên hơn. Vì vậy, không phải mọi kiểm thử đều phải là kiểm thử độ chân thực cao.

Kiểm thử không ổn định

Lỗi xảy ra ngay cả trong những lần chạy kiểm thử được thiết kế và triển khai chính xác. Ví dụ: khi chạy kiểm thử trên một thiết bị thực tế, quá trình cập nhật tự động có thể bắt đầu ở giữa quá trình kiểm thử và khiến quá trình kiểm thử không thành công. Những điều kiện tranh đấu nhỏ trong mã của bạn có thể chỉ xảy ra trong một tỷ lệ nhỏ. Các bài kiểm thử không vượt qua 100% thời gian sẽ bị không ổn định.

Cấu trúc có thể kiểm thử

Với cấu trúc ứng dụng có thể kiểm thử, mã tuân theo một cấu trúc cho phép bạn dễ dàng kiểm thử nhiều phần của mã một cách riêng biệt. Các cấu trúc có thể kiểm thử có các ưu điểm khác như dễ đọc, dễ bảo trì, có thể mở rộng và khả năng tái sử dụng cao hơn.

Một cấu trúc không kiểm thử được tạo ra:

  • Các kiểm thử lớn hơn, chậm hơn và dễ ngắt hơn. Các lớp không thể kiểm thử đơn vị có thể phải nằm trong các chương trình kiểm thử tích hợp hoặc kiểm thử giao diện người dùng lớn hơn.
  • Có ít cơ hội thử nghiệm nhiều tình huống. Các kiểm thử lớn hơn sẽ chậm hơn, vì vậy, việc kiểm thử mọi trạng thái có thể có của ứng dụng có thể không thực tế.

Để tìm hiểu thêm về nguyên tắc về cấu trúc, hãy xem hướng dẫn về cấu trúc ứng dụng.

Các phương pháp phân tách

Nếu bạn có thể trích xuất một phần của hàm, lớp hoặc mô-đun từ phần còn lại, thì việc kiểm thử sẽ dễ dàng và hiệu quả hơn. Phương pháp này được gọi là phân tách và là khái niệm quan trọng nhất đối với cấu trúc có thể kiểm thử.

Sau đây là các kỹ thuật phân tách phổ biến:

  • Chia ứng dụng thành các lớp như Bản trình bày, Miền và Dữ liệu. Bạn cũng có thể chia một ứng dụng thành các mô-đun cho mỗi tính năng.
  • Tránh thêm logic vào các thực thể có phần phụ thuộc lớn, chẳng hạn như hoạt động và mảnh. Sử dụng các lớp này làm điểm truy cập vào khung và di chuyển logic kinh doanh và giao diện người dùng sang nơi khác, chẳng hạn như đến Thành phần kết hợp, ViewModel hoặc lớp miền.
  • Tránh trực tiếp các phần phụ thuộc khung trực tiếp trong các lớp chứa logic nghiệp vụ. Ví dụ: không sử dụng Ngữ cảnh Android trong ViewModel.
  • Giúp bạn dễ dàng thay thế phần phụ thuộc. Ví dụ: sử dụng giao diện thay vì các phương thức triển khai cụ thể. Bạn có thể sử dụng tính năng Chèn phần phụ thuộc ngay cả khi bạn không sử dụng khung DI.

Các bước tiếp theo

Bây giờ, bạn đã biết lý do nên kiểm thử và hai loại kiểm thử chính, bạn có thể đọc bài viết Nội dung cần kiểm thử.

Ngoài ra, nếu bạn muốn tạo chương trình kiểm thử đầu tiên và học hỏi bằng cách thực hiện, hãy xem Lớp học lập trình kiểm thử.