Mở đầu — vì sao bài này quan trọng
Nếu bạn đã đi qua sáu bài đầu tiên, bạn hiểu bức tranh lớn: iOS khác Android ra sao, khi nào dùng real device thay vì emulator, và Kim tự tháp kiểm thử mobile bảo bạn nên đầu tư sức lực ở đâu. Bây giờ là lúc chúng ta chạm tay vào công cụ automation phổ biến nhất trong nghề Mobile QA — Appium.
Tại sao Appium lại quan trọng đến mức được dành riêng bốn bài liên tiếp (Bài 7 đến Bài 10)? Vì nó là công cụ mở đường cho phần lớn QA Việt Nam bước vào thế giới automation mobile. Trong hàng chục buổi phỏng vấn Mobile QA mà tôi từng dự với các công ty như FPT Software, VNG hay Momo, câu hỏi "Bạn đã dùng Appium chưa? Giải thích kiến trúc của nó?" gần như luôn xuất hiện. Người trả lời được rành mạch phần kiến trúc thường được đánh giá cao hơn hẳn người chỉ biết "em từng chạy vài test".
Bài 7 này có một nhiệm vụ rất cụ thể và tôi muốn bạn ghi nhớ ranh giới đó: hiểu Appium là gì, kiến trúc bên trong hoạt động thế nào, và dựng được môi trường chạy phiên Appium đầu tiên. Chúng ta chưa viết test login (đó là Bài 9), chưa bàn sâu về locator (Bài 8), chưa xử lý flaky test (Bài 10). Bài này giống như bạn lắp ráp và nổ máy chiếc xe lần đầu — chưa lái đi đâu cả, nhưng nếu máy không nổ thì mọi bài sau đều vô nghĩa. Rất nhiều bạn học automation bỏ cuộc ngay ở khâu setup vì gặp lỗi mà không hiểu bản chất. Học chắc kiến trúc ở bài này chính là tấm bảo hiểm giúp bạn tự gỡ lỗi về sau.
Khái niệm cốt lõi
Appium là gì
Appium là một công cụ automation mã nguồn mở, miễn phí, cho phép bạn tự động hóa thao tác trên ứng dụng di động: native app (viết bằng Swift/Kotlin), hybrid app (webview nhúng trong native), và cả mobile web. Triết lý cốt lõi của Appium được gói trong một câu: "Write once, run anywhere" — viết test một lần, chạy được trên iOS, Android, thậm chí Windows desktop.
Điều làm nên sức mạnh này là Appium không bắt bạn phải học lại từ đầu. Nếu bạn từng dùng Selenium để test web, bạn sẽ thấy Appium quen thuộc đến kỳ lạ. Lý do: Appium xây dựng trên nền WebDriver protocol — đúng chuẩn W3C WebDriver mà Selenium cũng dùng. Bạn gửi các lệnh dạng "tìm phần tử này", "click vào đây", "nhập text kia", và Appium dịch chúng thành thao tác thật trên thiết bị.
Một điểm quan trọng cần phân biệt ngay: Appium không phải là framework test. Nó là một automation server. Bạn vẫn viết test bằng ngôn ngữ và framework quen thuộc của mình — Java + JUnit/TestNG, Python + pytest, JavaScript + WebdriverIO, C# + NUnit — rồi các test đó "nói chuyện" với Appium server qua giao thức HTTP. Chính sự tách bạch này khiến Appium linh hoạt: một team backend quen Python và một team khác quen Java vẫn có thể dùng chung một Appium server.
Kiến trúc client–server
Đây là phần trái tim của bài, và cũng là phần hay bị hỏi nhất khi phỏng vấn. Appium hoạt động theo mô hình client–server.
Appium Client là code test của bạn. Bạn dùng một thư viện client (ví dụ Appium-Python-Client, java-client) để gói các lệnh của mình thành các HTTP request đúng chuẩn WebDriver. Ví dụ khi bạn viết driver.find_element(...), thư viện client sẽ biến nó thành một request POST /session/{id}/element.
Appium Server là một chương trình Node.js chạy ngầm (thường ở địa chỉ http://127.0.0.1:4723). Nó nhận request từ client, hiểu ý bạn muốn gì, rồi chuyển tiếp lệnh xuống thiết bị. Bản thân Appium server không tự biết cách điều khiển iPhone hay Android — nó ủy quyền việc đó cho các driver chuyên biệt.
Driver là lớp then chốt mà nhiều bạn học Appium bỏ qua. Từ Appium 2.0 (bản hiện đại bạn nên dùng), Appium server chỉ là một cái lõi mỏng, còn mọi khả năng thật sự đến từ các driver cài thêm:
- UiAutomator2 driver — điều khiển Android, dựa trên framework UiAutomator2 của Google.
- XCUITest driver — điều khiển iOS, dựa trên XCUITest của Apple (chính là framework bạn sẽ học riêng ở Bài 11).
- Espresso driver — một lựa chọn khác cho Android (liên quan Bài 12).
Code test (client) → HTTP request → Appium server → UiAutomator2 driver → UiAutomator2 framework trên thiết bị → thao tác thật lên UI → kết quả trả ngược lại theo đúng con đường đó.
Hiểu chuỗi này giúp bạn debug cực nhanh. Khi test lỗi, bạn sẽ biết ngay cần soi ở tầng nào: lỗi kết nối client–server, hay lỗi driver không cài đúng, hay lỗi thiết bị không nhận.
Desired Capabilities — tấm "hộ chiếu" của phiên test
Khi client muốn bắt đầu một phiên (session), nó phải gửi cho server một bộ thông tin gọi là capabilities (viết tắt caps). Đây là cách bạn nói với Appium: "Tôi muốn test trên nền tảng nào, thiết bị nào, app nào, dùng driver gì". Ví dụ những cap quan trọng nhất:
platformName:AndroidhayiOS.appium:automationName: tên driver, ví dụUiAutomator2hoặcXCUITest.appium:deviceName: tên thiết bị/emulator.appium:app: đường dẫn tới file.apk(Android) hoặc.app/.ipa(iOS).appium:platformVersion: phiên bản OS.
appium:. Đây là lỗi vướng phổ biến nhất khi bạn chuyển từ tài liệu cũ (Appium 1.x) sang, nên tôi nhấn mạnh ngay từ đầu.Appium Inspector — người bạn đồng hành
Có một công cụ đi kèm bạn nên biết ngay từ bài này: Appium Inspector. Đây là ứng dụng GUI giúp bạn "soi" cây phần tử (element tree) của app đang chạy, giống DevTools của trình duyệt vậy. Nó không bắt buộc để chạy test, nhưng cực kỳ hữu ích để tìm locator (nội dung Bài 8). Ở bài này, ta chỉ cần biết nó tồn tại và dùng nó để xác nhận môi trường đã kết nối được với app.
Tình huống thực tế
Tình huống 1 — Fintech Đông Nam Á chọn Appium để test hai nền tảng bằng một bộ code
Một công ty fintech giả định tên PayNhanh ở TP.HCM có app ví điện tử chạy cả iOS lẫn Android, phục vụ khoảng 800.000 người dùng. Trước đây họ có hai đội automation tách biệt: một đội dùng XCUITest thuần cho iOS, một đội dùng Espresso thuần cho Android. Kết quả là mỗi tính năng mới (ví dụ luồng "nạp tiền") phải viết test hai lần, hai ngôn ngữ, hai người bảo trì. Chi phí bảo trì phình to.
Họ chuyển sang Appium với chiến lược viết test bằng Java + TestNG. Nhờ kiến trúc client–server, cùng một kịch bản test "mở app → đăng nhập → nạp tiền → kiểm tra số dư" chỉ khác nhau ở bộ capabilities: đổi platformName và automationName, còn logic test gần như dùng lại 80%. Sau ba tháng, họ giảm một nửa số dòng test code trùng lặp.
Bài học rút ra: Sức mạnh lớn nhất của Appium không phải "chạy nhanh hơn", mà là tái sử dụng logic test qua nhiều nền tảng. Nếu app của bạn chỉ có một nền tảng, lợi thế này giảm đi và bạn nên cân nhắc kỹ giữa Appium và công cụ native.
Tình huống 2 — Bạn QA mới vào nghề và cú sốc "cài mãi không chạy"
Minh, một bạn QA vừa vào một studio game mobile ở Đà Nẵng, được giao task đầu tiên: "Chạy thử một test Appium trên emulator Android". Minh cài Appium, viết vài dòng, và nhận về lỗi An unknown server-side error occurred... Could not find a driver for automationName 'UiAutomator2'.
Minh loay hoay hai ngày. Vấn đề nằm ở chỗ bạn ấy học theo một video Appium 1.x cũ, nơi driver được cài sẵn trong server. Còn Appium 2.0 mà bạn ấy cài lại tách driver ra — phải chạy riêng lệnh appium driver install uiautomator2. Chỉ một dòng lệnh thiếu, mất hai ngày.
Bài học rút ra: Trước khi viết bất kỳ dòng test nào, hãy chạy appium driver list --installed để xác nhận driver đã có mặt. 90% lỗi "Appium không chạy" của người mới đến từ việc không hiểu Appium 2.0 tách driver khỏi core server.
Tình huống 3 — Vì sao một tập đoàn outsourcing lớn vẫn chuộng Appium
Một trung tâm kiểm thử của một công ty outsourcing lớn tại Hà Nội (kiểu FPT Software) nhận dự án cho khách hàng Nhật, yêu cầu automation cho một app bán lẻ chạy cả iOS lẫn Android, và team gồm người quen Java, người quen Python. Họ chọn Appium chính vì tính agnostic về ngôn ngữ: mỗi thành viên viết bằng ngôn ngữ mình mạnh nhất, tất cả cùng trỏ vào một Appium server tiêu chuẩn. Khách hàng cũng yên tâm vì Appium là chuẩn W3C mở, không khóa họ vào một nhà cung cấp thương mại nào.
Bài học rút ra: Trong môi trường team đa dạng và dự án dài hạn, tính mở và chuẩn hóa của Appium là một tài sản chiến lược, không chỉ là chuyện kỹ thuật.
Hướng dẫn từng bước
Dưới đây là quy trình dựng môi trường và chạy phiên Appium đầu tiên trên Android (dễ bắt đầu nhất vì không cần máy Mac). Hãy làm tuần tự.
Bước 1 — Cài Node.js. Appium là chương trình Node.js, nên bạn cần Node phiên bản LTS. Kiểm tra bằng node -v.
Bước 2 — Cài Appium server. Chạy npm install -g appium, rồi kiểm tra appium -v để chắc chắn đang dùng bản 2.x.
Bước 3 — Cài driver. Đây là bước hay bị quên. Chạy appium driver install uiautomator2. Sau đó xác nhận bằng appium driver list --installed, bạn phải thấy uiautomator2 trong danh sách.
Bước 4 — Cài Android SDK. Cài Android Studio để có sẵn SDK, adb, và trình tạo emulator. Đặt biến môi trường ANDROID_HOME trỏ tới thư mục SDK. Điều này bắt buộc — driver Android không tìm được thiết bị nếu thiếu.
Bước 5 — Chuẩn bị thiết bị. Mở một emulator Android trong Android Studio, hoặc cắm điện thoại thật đã bật USB debugging. Chạy adb devices — bạn phải thấy thiết bị của mình liệt kê ở đó. Nếu danh sách trống, mọi bước sau vô nghĩa.
Bước 6 — Kiểm tra sức khỏe môi trường. Chạy appium-doctor (hoặc appium driver doctor uiautomator2). Công cụ này quét và báo cho bạn thiếu gì: thiếu ANDROID_HOME, thiếu Java, v.v.
Bước 7 — Khởi động Appium server. Chỉ cần gõ appium. Bạn sẽ thấy dòng Appium REST http interface listener started on http://0.0.0.0:4723. Server đang lắng nghe. Để cửa sổ này chạy.
Bước 8 — Chạy phiên đầu tiên. Ở đây bạn viết một đoạn client tối giản. Ví dụ bằng Python với Appium-Python-Client, bạn khai báo capabilities (platformName=Android, automationName=UiAutomator2, deviceName, và app trỏ tới một file .apk mẫu), rồi khởi tạo webdriver.Remote('http://127.0.0.1:4723', options=...). Nếu app tự mở trên emulator — chúc mừng, phiên đầu tiên của bạn đã sống. Nhớ đóng lại bằng driver.quit() để giải phóng session.
Bước 9 — Xác nhận bằng Appium Inspector. Mở Appium Inspector, điền cùng bộ capabilities, nhấn Start Session. Nếu bạn thấy màn hình app và cây phần tử hiện ra, môi trường của bạn hoàn chỉnh.
Đến đây, mục tiêu của Bài 7 đã đạt: bạn hiểu kiến trúc và đã nổ máy được Appium. Việc tìm locator và viết test thực chất sẽ đến ở các bài kế tiếp.
Lỗi thường gặp & mẹo
Lỗi 1 — Quên cài driver. Triệu chứng: Could not find a driver for automationName.... Nhớ Appium 2.0 tách driver; luôn chạy appium driver install ... và kiểm tra bằng --installed.
Lỗi 2 — Thiếu tiền tố appium: trong capabilities. Bạn copy caps từ tài liệu Appium 1.x cũ, thiếu appium: trước các cap không chuẩn W3C, và session bị từ chối. Mẹo: mọi cap ngoài platformName, browserName đều nên có tiền tố appium:.
Lỗi 3 — ANDROID_HOME/JAVA_HOME chưa được đặt. Đây là nguyên nhân số một của "cài xong mà không nổ máy". Chạy appium driver doctor uiautomator2 để phát hiện sớm thay vì đoán mò.
Lỗi 4 — adb devices trống. Nếu Appium không tìm thấy thiết bị, kiểm tra emulator đã boot xong chưa, hoặc điện thoại thật đã cho phép USB debugging chưa. Đừng đổ lỗi cho Appium khi vấn đề nằm ở tầng thiết bị.
Lỗi 5 — Nhầm Appium là framework test. Nhiều bạn cố tìm "cách viết assert trong Appium". Appium không lo phần assert; framework test của bạn (pytest, TestNG...) mới làm việc đó. Hiểu đúng ranh giới này giúp bạn không đi tìm nhầm chỗ.
Mẹo vàng: Luôn giữ cửa sổ log của Appium server mở khi test. Log server nói cho bạn biết chính xác request nào tới, driver phản hồi ra sao — nó là bản đồ debug quý giá hơn mọi lời đoán.
Bài tập thực hành
- Vẽ lại kiến trúc. Không nhìn tài liệu, hãy tự vẽ sơ đồ luồng của một lệnh "click" đi từ code test đến thiết bị Android, đủ 5 tầng: client → HTTP → server → driver → device. Đây chính là câu hỏi phỏng vấn kinh điển.
- Dựng môi trường và nổ máy. Làm theo 9 bước ở trên để chạy một phiên Appium trên emulator Android. Ghi lại đúng dòng log
listener started on...và ảnh chụp app tự mở làm bằng chứng.
- Cố tình gây lỗi để học. Gỡ biến
ANDROID_HOMErồi chạy lại, đọc kỹ thông báo lỗi. Sau đó đặt lại và quan sát nó biến mất. Việc chủ động tạo lỗi giúp bạn nhận diện chúng nhanh gấp nhiều lần khi gặp thật.
- Viết bộ capabilities. Soạn hai bộ caps: một cho Android (UiAutomator2), một cho iOS (XCUITest). So sánh xem cap nào giữ nguyên, cap nào đổi. Đây là nền tảng cho tư duy "một bộ test, nhiều nền tảng".
Tóm tắt
Bài 7 đặt viên gạch đầu tiên cho hành trình automation mobile của bạn với Appium. Ba điều cốt lõi cần khắc ghi: Một, Appium là một automation server mã nguồn mở dựa trên chuẩn W3C WebDriver, cho phép "viết một lần, chạy nhiều nền tảng" và không khóa bạn vào một ngôn ngữ nào. Hai, kiến trúc client–server–driver là xương sống — code test (client) gửi HTTP request đến Appium server, server ủy quyền cho driver chuyên biệt (UiAutomator2 cho Android, XCUITest cho iOS) để điều khiển thiết bị thật; hiểu chuỗi này là chìa khóa để tự debug. Ba, từ Appium 2.0, driver được tách khỏi core server và mọi capability ngoài chuẩn W3C cần tiền tố appium: — hai chi tiết nhỏ này là nguồn gốc của phần lớn lỗi setup ở người mới.
Bạn giờ đã nổ được máy. Ở Bài 8, chúng ta sẽ học cách "nhìn thấy" và định danh chính xác từng phần tử trên màn hình bằng các locator strategy — bước đầu tiên để thực sự điều khiển app.