Kiểm thử UI trong ứng dụng di động: định nghĩa, loại hình và cách thực hiện

Tác giả: IT Sectr Đã đăng: 2026-04-07 Thời gian đọc: 8 phút

Kiểm thử UI kiểm tra tính chính xác của việc hiển thị và tương tác của các phần tử giao diện người dùng trong ứng dụng di động — nút bấm, trường văn bản, danh sách và thành phần điều hướng. Không giống như kiểm thử đơn vị kiểm tra logic nghiệp vụ, kiểm thử UI mô phỏng hành động của người dùng: chạm, vuốt, nhập văn bản và kiểm tra phản hồi của giao diện. Theo một nghiên cứu của Android Developers, 2024, kiểm thử UI bao phủ 70% kịch bản người dùng quan trọng và cho phép phát hiện lỗi bố cục mà các kiểm tra logic không thể phát hiện.

Những điểm chính

  • Kiểm thử UI — quy trình kiểm tra giao diện người dùng của ứng dụng thông qua mô phỏng hành động người dùng: chạm, nhập văn bản và vuốt.
  • Espresso — framework của Google để kiểm thử UI ứng dụng Android, cung cấp đồng bộ hóa với luồng UI và tự động chờ hoạt ảnh.
  • XCUITest — framework gốc của Apple để kiểm thử UI ứng dụng iOS, tích hợp trong Xcode và hoạt động qua nhãn trợ năng.
  • Appium — công cụ đa nền tảng cho phép viết kiểm thử UI bằng một ngôn ngữ cho Android và iOS sử dụng giao thức WebDriver.
  • Kiểm thử snapshot bổ sung cho kiểm thử UI bằng cách kiểm tra hình thức trực quan của màn hình — so sánh ảnh chụp trạng thái tham chiếu với kết xuất hiện tại.

Kiểm thử UI là gì?

Kiểm thử UI là một loại kiểm tra tự động trong đó mã kiểm thử tương tác với giao diện đồ họa của ứng dụng giống như người dùng thực. Kiểm thử tìm một phần tử trên màn hình — nút bấm, trường văn bản, danh sách — thực hiện hành động trên đó và kiểm tra phản hồi mong đợi của giao diện. Ví dụ, sau khi nhập mật khẩu sai, kiểm thử UI kiểm tra xem thông báo lỗi với nội dung chính xác có xuất hiện trên màn hình hay không.

Sự khác biệt chính giữa kiểm thử UI và các loại tự động hóa khác là chúng hoạt động thông qua lớp trợ năng của hệ điều hành, không phải qua API nội bộ của ứng dụng. Điều này có nghĩa là kiểm thử UI nhìn thấy giao diện chính xác như người dùng và trình đọc màn hình. Nhờ đó, kiểm thử UI không chỉ kiểm tra chức năng mà còn kiểm tra khả năng truy cập của các phần tử — tuân thủ yêu cầu WCAG.

Theo khảo sát JetBrains Developer Ecosystem 2023, 58% đội ngũ di động sử dụng kiểm thử UI trong đường ống CI/CD. Độ bao phủ kiểm thử UI trung bình trong các dự án thương mại là 30–40% số màn hình ứng dụng. Các dự án có kiểm thử UI nhận được ít hơn 25% đánh giá tiêu cực trên cửa hàng ứng dụng liên quan đến lỗi giao diện.

Kiểm thử UI khác kiểm thử đơn vị như thế nào

Sự khác biệt chính giữa kiểm thử UI và kiểm thử đơn vị là mức độ trừu tượng. Kiểm thử đơn vị làm việc với các lớp và hàm riêng lẻ, cách ly khỏi framework Android hoặc iOS. Chúng chạy trên JVM (cho Android) mà không cần khởi động trình giả lập và mất mili giây. Kiểm thử UI chạy trên thiết bị thật hoặc trình giả lập, tương tác với dịch vụ hệ thống và mất giây hoặc phút cho mỗi kịch bản.

Đối tượng mục tiêu của kiểm thử cũng khác nhau. Kiểm thử UI kiểm tra các kịch bản người dùng đầu cuối — đăng ký, đặt hàng, tìm kiếm. Kiểm thử đơn vị bao phủ logic nghiệp vụ: tính toán, xác thực, chuyển đổi dữ liệu. Kiểm thử UI không kiểm tra tính chính xác của phép tính thuế — nó kiểm tra tổng số tiền có hiển thị trên màn hình hay không. Bản thân phép tính được kiểm tra bởi kiểm thử đơn vị.

Theo Google Testing Blog (2020), tỷ lệ kiểm thử tối ưu trong một dự án tuân theo quy tắc kim tự tháp kiểm thử: 70% kiểm thử đơn vị, 20% kiểm thử tích hợp và 10% kiểm thử UI. Vi phạm tỷ lệ này theo hướng có lợi cho kiểm thử UI dẫn đến tăng thời gian chạy và độ mong manh của bộ kiểm thử, vì kiểm thử UI nhạy cảm với thay đổi trong bố cục màn hình.

Framework cho kiểm thử UI

Cho Android, framework thống trị là Espresso — thư viện của Google được tích hợp trong AndroidX Test. Espresso tự động đồng bộ hóa với luồng UI, chờ hoàn thành hoạt ảnh và tác vụ nền trước khi thực hiện kiểm tra tiếp theo. Cho Jetpack Compose, phần mở rộng Compose UI Test được sử dụng, hoạt động thông qua các nút ngữ nghĩa thay vì định danh view truyền thống.

Cho iOS, công cụ chính là XCUITest, một phần của Xcode. Các kiểm thử được viết bằng Swift và sử dụng định danh trợ năng để tìm phần tử. XCUITest hỗ trợ ghi kiểm thử qua chức năng ghi và tích hợp với hệ thống CI qua xcodebuild. Cho các dự án đa nền tảng, Appium được sử dụng, dựa trên giao thức WebDriver và cho phép chạy cùng kiểm thử trên Android và iOS với thay đổi mã tối thiểu.

Espresso và Compose UI Test

Espresso hoạt động với hệ thống View truyền thống qua onView và định danh ID tài nguyên. Compose UI Test sử dụng lớp ngữ nghĩa, làm cho kiểm thử ít phụ thuộc vào hệ thống phân cấp view. Ví dụ, tìm nút trong Espresso: onView(withId(R.id.submit)), trong Compose: onNodeWithTag(“submit”). Kiểm thử Compose tự động xử lý tái tổ hợp và không yêu cầu chờ trạng thái rõ ràng.

XCUITest cho iOS

XCUITest sử dụng XCUIApplication làm điểm vào. Mỗi phần tử giao diện được tìm qua thuộc tính trợ năng: accessibilityIdentifier cho truy cập lập trình và accessibilityLabel cho VoiceOver. Framework hỗ trợ ghi kiểm thử qua chức năng ghi của Xcode — nhà phát triển thực hiện hành động trên trình mô phỏng và Xcode tạo mã kiểm thử. Các kiểm thử sẵn sàng được chạy qua xcodebuild test.

Giải pháp đa nền tảng

Appium dựa trên giao thức WebDriver và hỗ trợ mọi ngôn ngữ: Java, Python, JavaScript. Chiến lược tìm phần tử bao gồm id, xpath, class name và accessibility id. Appium yêu cầu cài đặt máy chủ và cấu hình Desired Capabilities — platformName, deviceName, appPackage. Một giải pháp thay thế là Maestro, sử dụng kịch bản YAML và không yêu cầu biên dịch mã kiểm thử.

  • Espresso — onView(withId(R.id.button)).perform(click()).check(matches(isDisplayed()))
  • XCUITest — app.buttons[“loginButton”].tap(); XCTAssertTrue(app.staticTexts[“welcome”].exists)
  • Appium — driver.findElement(By.id(“com.example:id/button”)).click()
  • Detox — framework của Wix cho React Native, đồng bộ hóa với luồng JS
  • Maestro — công cụ hiện đại với kịch bản YAML không yêu cầu viết mã

Ví dụ mã cho kiểm thử UI

Hãy xem kiểm thử UI cho cùng một kịch bản — đăng nhập vào ứng dụng — trên ba framework khác nhau: Espresso cho Android, XCUITest cho iOS và Appium cho phương pháp đa nền tảng. Kịch bản: nhập tên đăng nhập và mật khẩu, nhấn nút đăng nhập, kiểm tra hiển thị thông báo chào mừng.

Android: Espresso

Kiểm thử Espresso sử dụng onView để tìm phần tử theo định danh và perform để thực hiện hành động. Phương thức check với bộ so khớp isDisplayed xác nhận phần tử hiển thị trên màn hình.

kotlin
@RunWith(AndroidJUnit4::class)
class LoginUiTest {

    @Rule
    @JvmField
    val composeTestRule = createComposeRule()

    @Test
    fun login_withValidCredentials_showsWelcome() {
        composeTestRule
            .onNodeWithTag("emailField")
            .performTextInput("user@example.com")
        composeTestRule
            .onNodeWithTag("passwordField")
            .performTextInput("secret123")
        composeTestRule
            .onNodeWithTag("loginButton")
            .performClick()
        composeTestRule
            .onNodeWithText("Chào mừng, Người dùng!")
            .assertIsDisplayed()
    }
}

iOS: XCUITest

XCUITest sử dụng XCUIApplication để truy cập phần tử giao diện qua định danh trợ năng. Các phương thức tap() và exists cung cấp tương tác và kiểm tra.

swift
class LoginUITests: XCTestCase {
    let app = XCUIApplication()

    override func setUp() {
        continueAfterFailure = false
        app.launch()
    }

    func testLogin_withValidCredentials_showsWelcome() {
        app.textFields["emailField"].tap()
        app.textFields["emailField"].typeText("user@example.com")
        app.secureTextFields["passwordField"].tap()
        app.secureTextFields["passwordField"].typeText("secret123")
        app.buttons["loginButton"].tap()
        XCTAssertTrue(app.staticTexts["Welcome, User!"].exists)
    }
}

Thực hành tốt nhất cho kiểm thử UI

Nguyên tắc đầu tiên — sử dụng định danh trợ năng thay vì nhãn văn bản để tìm phần tử. Văn bản nút có thể thay đổi khi bản địa hóa, trong khi định danh vẫn ổn định. Trong Android, đây là thuộc tính contentDescription; trong iOS — accessibilityIdentifier. Cách tiếp cận này làm cho kiểm thử độc lập với ngôn ngữ giao diện và giảm chi phí bảo trì khi thay đổi nội dung.

Tránh sleep() và độ trễ cố định — sử dụng cơ chế chờ tích hợp của framework. Espresso tự động chờ hoàn thành hoạt ảnh và tác vụ nền. XCUITest cung cấp XCTAssertTrue với thời gian chờ. Tạm dừng rõ ràng làm cho kiểm thử chậm hơn và không ổn định, đặc biệt trên thiết bị chậm trong môi trường CI.

Nhóm kiểm thử theo mức độ quan trọng: kiểm thử khói (3–5 kịch bản chính) chạy mỗi lần commit, bộ kiểm thử UI đầy đủ chạy trước khi phát hành. Theo Google Testing Blog (2022), kiểm thử UI mất hơn 30 phút trong CI giảm tần suất chạy 40%, làm giảm hiệu quả như công cụ phát hiện hồi quy sớm.

Hạn chế của kiểm thử UI và cách khắc phục

Kiểm thử UI có một số hạn chế. Nhạy cảm với thay đổi bố cục: thay đổi định danh, hệ thống phân cấp hoặc loại phần tử làm hỏng kiểm thử ngay cả khi chức năng không thay đổi. Giải pháp là sử dụng mẫu Page Object, tập trung bộ chọn phần tử trong các lớp riêng biệt. Khi bố cục thay đổi, chỉ một tệp Page Object được sửa, không phải hàng chục kiểm thử.

Thời gian thực thi: chạy trên thiết bị thật hoặc trình giả lập mất nhiều hơn 10–50 lần so với kiểm thử đơn vị. Giải pháp là chạy kiểm thử UI song song trên nhiều thiết bị qua Firebase Test Lab hoặc AWS Device Farm. Sự không ổn định (flakiness) là vấn đề phổ biến trong CI, do hoạt ảnh, độ trễ mạng hoặc trạng thái trình giả lập. Để chống flakiness, sử dụng tự động chạy lại kiểm thử thất bại và phân tích độ ổn định của từng kịch bản kiểm thử.

Câu hỏi thường gặp

Cần bao nhiêu kiểm thử UI cho một màn hình?

Cho một màn hình trung bình, 3–5 kiểm thử UI là đủ: happy path, xác thực lỗi, trạng thái rỗng, thay đổi hướng và kiểm tra trợ năng. Màn hình phức tạp với nhiều trạng thái — biểu mẫu đặt hàng, cài đặt — có thể yêu cầu 10–15 kiểm thử để bao phủ đầy đủ các kịch bản chính.

Có thể sử dụng một framework cho Android và iOS không?

Có, Appium và Maestro cho phép chạy cùng kịch bản trên cả hai nền tảng. Tuy nhiên, framework gốc — Espresso và XCUITest — cung cấp độ ổn định, tốc độ và truy cập tốt hơn vào các tính năng nền tảng không có sẵn qua proxy WebDriver.

Làm thế nào để kiểm thử UI trong Jetpack Compose?

Cho Compose, thư viện Compose UI Test với bộ so khớp ngữ nghĩa được sử dụng: onNodeWithText, onNodeWithTag, onNodeWithContentDescription. Lớp ngữ nghĩa của Compose trừu tượng hóa hệ thống phân cấp view, làm cho kiểm thử ít mong manh hơn so với Espresso truyền thống cho hệ thống View.

Có cần kiểm thử UI trên thiết bị vật lý không?

Chạy kiểm thử UI cơ bản được thực hiện trên trình giả lập trong CI — nhanh và rẻ. Xác minh cuối cùng trước khi phát hành nên được thực hiện trên thiết bị vật lý qua Firebase Test Lab để tính đến đặc điểm phần cứng thực: độ phân giải khác nhau, phiên bản OS và hiệu suất.

Làm thế nào để giảm thời gian chạy kiểm thử UI?

Sử dụng thực thi song song trên nhiều thiết bị, tắt hoạt ảnh trên trình giả lập qua Tùy chọn nhà phát triển, xây dựng kiến trúc kiểm thử mô-đun và chạy bộ khói mỗi lần commit, chạy hồi quy đầy đủ theo lịch hoặc trước khi phát hành.

Tổng kết

  • Kiểm thử UI kiểm tra giao diện bằng cách mô phỏng hành động người dùng — chạm, nhập văn bản, vuốt.
  • Espresso và Compose UI Test là framework chính cho Android; XCUITest cho iOS; Appium cho dự án đa nền tảng.
  • Kim tự tháp kiểm thử khuyến nghị tỷ lệ 70/20/10: kiểm thử đơn vị, tích hợp và UI tương ứng.
  • Định danh trợ năng làm cho kiểm thử UI kháng cự với bản địa hóa và thay đổi bố cục.
  • Mẫu Page Object tập trung bộ chọn phần tử, giảm chi phí bảo trì khi giao diện thay đổi.
  • Kiểm thử khói (3–5 kịch bản) chạy mỗi lần commit, bộ đầy đủ trước khi phát hành.
  • Thực thi song song trên trình giả lập và tắt hoạt ảnh giảm thời gian chạy kiểm thử UI trong CI.

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm