Giới Thiệu
Trong bối cảnh phát triển ứng dụng Android hiện nay, việc tự động hóa kiểm thử là điều cần thiết để đảm bảo chất lượng phần mềm. Tuy nhiên, với nhiều tùy chọn có sẵn, không ít nhà phát triển cảm thấy bối rối khi lựa chọn giải pháp phù hợp. Bài viết này sẽ chia sẻ hành trình của chúng tôi trong việc xây dựng một quy trình kiểm thử tự động hiệu quả cho ứng dụng Android, bao gồm các loại kiểm thử khác nhau mà chúng tôi đã sử dụng.
1. Kiểm Thử Giao Diện với Robolectric
1.1. Tại Sao Chọn Robolectric?
Robolectric cho phép chúng tôi thực hiện các bài kiểm thử giao diện người dùng (UI) mà không cần khởi động trình mô phỏng Android, giúp tiết kiệm thời gian và tài nguyên. Điều này rất hữu ích trong quá trình phát triển liên tục (CI), nơi mỗi Pull Request (PR) đều cần kiểm tra.
1.2. Ví Dụ Kiểm Thử Giao Diện
Dưới đây là ví dụ về một bài kiểm thử cho màn hình chi tiết:
kotlin
@RunWith(AndroidJUnit4::class)
@GraphicsMode(GraphicsMode.Mode.NATIVE)
@Config(application = TestApplication::class, qualifiers = MyDeviceQualifiers.MEDIUM_PHONE)
class DetailScreenTest : KoinTest {
@get:Rule
val composeTestRule = createAndroidComposeRule<MainActivity>()
@BeforeTest
fun setup() {
startKoin {
androidContext(...)
val testModule = module { single<Api> { FakeApi() } }
modules(myModules + testModule)
}
}
@Test
fun editDetailScreen() = runTest {
launchDetailScreen(composeTestRule) {
clickEdit()
} verify {
editDetailIsPresent()
}
}
}
1.3. Tạo Các Lớp Robot
Chúng tôi sử dụng các lớp Robot để trừu tượng hóa các cuộc gọi đến composeTestRule, giúp cho mã kiểm thử dễ đọc hơn. Ví dụ về lớp Robot cho bài kiểm thử trên:
kotlin
class DetailRobot(private val rule: ComposeContentTestRule) {
fun clickEdit() {
val string = RuntimeEnvironment.getApplication().getString(R.string.edit)
rule.onNodeWithText(string).performClick()
}
infix fun verify(block: DetailVerification.() -> Unit): DetailVerification {
return DetailVerification(rule).apply(block)
}
class DetailVerification(private val rule: ComposeContentTestRule) {
fun editDetailIsPresent() {
val title = RuntimeEnvironment.getApplication().getString(R.string.edit_screen_title)
rule.onNodeWithText(title).assertIsDisplayed()
}
}
}
1.4. Lợi Ích của Kiểm Thử Giao Diện
Nhờ các bài kiểm thử này, chúng tôi có thể phát hiện lỗi nhanh chóng, và Robolectric giúp chúng tôi kiểm tra giao diện mà không cần phải chạy trên thiết bị thực. Chúng tôi cũng sử dụng Roborazzi để giúp việc gỡ lỗi dễ dàng hơn.
2. Kiểm Thử ViewModel (Kiểm Thử Đơn Vị)
2.1. Mục Đích và Phương Pháp Kiểm Thử
Các ViewModel thường trả về trạng thái trong một đối tượng. Chúng tôi sử dụng thư viện cashapp/turbine để kiểm tra trạng thái của ViewModel. Việc sử dụng lớp Fake giúp đảm bảo rằng mỗi lần chạy kiểm thử đều cho kết quả giống nhau.
2.2. Ví Dụ Kiểm Thử ViewModel
kotlin
class NavigateScreenViewModelTest {
private lateinit var viewModel: NavigateViewModel
private val locationProvider = LocationProvidingFake()
@BeforeTest
fun setup() {
viewModel = NavigateViewModel(
dispatcher = UnconfinedTestDispatcher(),
locationProvider = locationProvider,
)
}
@Test
fun state_whenDoSomeAction_myFieldIsTrue() = runTest {
viewModel.state.test {
val initialState = awaitItem()
assert(initialState.myField == false)
viewModel.doSomeAction()
val state = awaitItem()
assert(state.myField == true)
}
}
}
3. Kiểm Thử Đơn Vị
3.1. Tập Trung vào Logic Kinh Doanh
Ngoài các kiểm thử giao diện và ViewModel, chúng tôi thực hiện các kiểm thử đơn vị để kiểm tra logic kinh doanh và logic mạng. Thư viện cashapp/burst giúp chúng tôi tạo các bài kiểm thử tham số hóa.
3.2. Ví Dụ Kiểm Thử Đơn Vị
kotlin
@Test
fun validateDriverLicense_whenInvalid_returnsInvalid(
license: String = burstValues("1234567890123", "ABC-123"),
) {
val result = PersonalIdentityValidator.validateDriverLicense(license)
result.shouldBeTypeOf<ValidationResult.Invalid>()
}
4. Chiến Lược Tốt Nhất cho Kiểm Thử Tự Động
- Tổ Chức Kiểm Thử: Sắp xếp các bài kiểm thử theo loại và chức năng để dễ dàng quản lý.
- Thường Xuyên Chạy Kiểm Thử: Sử dụng CI để tự động chạy kiểm thử cho mỗi PR, đảm bảo rằng mọi thay đổi đều được kiểm tra.
- Sử Dụng Fake và Mock: Thay thế các phụ thuộc thực bằng các lớp giả để dễ dàng kiểm tra mà không phụ thuộc vào hệ thống bên ngoài.
5. Những Điều Cần Tránh Khi Kiểm Thử Tự Động
- Kiểm Thử Không Đầy Đủ: Đừng bỏ qua các trường hợp có thể xảy ra. Kiểm thử nên bao gồm các tình huống biên.
- Thiếu Tài Liệu: Ghi chép rõ ràng và đầy đủ về cách thức thực hiện kiểm thử giúp tăng khả năng bảo trì.
- Không Tối Ưu Hóa Tốc Độ: Các bài kiểm thử cần được tối ưu hóa để không làm chậm quá trình phát triển.
6. Mẹo Tối Ưu Hiệu Suất Kiểm Thử
- Sử Dụng Parallel Testing: Chạy các bài kiểm thử song song để tiết kiệm thời gian.
- Giảm Thiểu Thời Gian Khởi Tạo: Tối ưu hóa quá trình khởi tạo để các bài kiểm thử có thể chạy nhanh hơn.
7. Kết Luận
Việc tự động hóa kiểm thử ứng dụng Android không chỉ giúp nâng cao chất lượng sản phẩm mà còn tối ưu hóa quy trình phát triển. Thông qua việc áp dụng các phương pháp kiểm thử như Robolectric và thiết lập CI, chúng tôi đã cải thiện đáng kể khả năng phát hiện và sửa lỗi. Hãy bắt đầu hành trình kiểm thử tự động của bạn ngay hôm nay!
Câu Hỏi Thường Gặp (FAQ)
1. Robolectric có thể thay thế hoàn toàn kiểm thử trên thiết bị thực không?
- Mặc dù Robolectric rất hữu ích, nhưng kiểm thử trên thiết bị thực vẫn cần thiết để phát hiện các vấn đề không thể tái tạo trên môi trường giả lập.
2. Làm thế nào để tối ưu hóa tốc độ kiểm thử?
- Sử dụng các kỹ thuật như kiểm thử song song và giảm tải tài nguyên trong mỗi bài kiểm thử.
3. Những công cụ nào khác có thể sử dụng cho kiểm thử tự động trên Android?
- Ngoài Robolectric, bạn có thể xem xét Espresso, Mockito và JUnit.