Sau khi dựng Page ObjectComponent Object, test nhìn sạch hơn nhưng hạ tầng Android vẫn có thể nổi loạn. Mobile automation có một kiểu lỗi rất mất dạy: Robot Framework báo Element not found, nhưng nguyên nhân có thể là điện thoại vừa mất ADB, app chưa mở đúng activity, permission dialog đang che màn hình hoặc locator thật sự sai. Cùng một message ở trên mặt, bên dưới có thể là tám tầng nguyên nhân.

Vì thế bài này không sắp theo “50 câu lệnh sửa lỗi Appium”. Mình sẽ đi theo thứ tự từ tầng thấp lên tầng cao. Tầng dưới chưa sống thì sửa tầng trên chỉ là múa quạt trước máy lạnh.

Android Studio hiển thị source code và một thiết bị Android trong Running Devices
Android Studio hiển thị source code và một thiết bị Android trong Running Devices

Running Devices nhìn thấy điện thoại mới chỉ chứng minh Android Studio đang giao tiếp được với target; nó chưa chứng minh Appium session hay locator đang khỏe. Ảnh: Android Developers, sử dụng theo Content License.

Diagnostic ladder

1. Toolchain PATH2. ADB server3. Target device4. Appium serverdriver5. Sessioncapabilities6. App packageactivity7. Page sourcelocator8. Action trạng tháiUI
// Mermaid diagram

Đừng nhảy tầng. Nếu adb devices -l còn trống thì chưa có lý do gì mở Appium Inspector, thay XPath hoặc tăng timeout lên 120 giây.

Tầng 1: máy đang chạy đúng executable chưa?

Triệu chứng thường gặp:

Kiểm tra:

where.exe python
where.exe node
where.exe java
where.exe adb
where.exe appium

python --version
node --version
java -version
adb version
appium --version

where.exe adb mà trả về hai hoặc ba đường dẫn thì cần chú ý. Android Studio có thể dùng ADB trong SDK A, còn terminal lại gọi ADB cũ trong SDK B. Hai ADB server/client khác version có thể đá nhau hoặc nhìn target không giống nhau.

Kiểm tra biến:

$env:JAVA_HOME
$env:ANDROID_HOME
$env:ANDROID_SDK_ROOT
Test-Path "$env:JAVA_HOME\bin\java.exe"
Test-Path "$env:ANDROID_HOME\platform-tools\adb.exe"

Cách sửa là dọn PATH để một bộ Android SDK được ưu tiên, mở terminal mới và chạy lại doctor:

appium driver doctor uiautomator2

Tầng 2: đọc đúng trạng thái ADB

adb devices -l
Trạng tháiNó thực sự nói gì?Việc tiếp theo
Không có dòng targetADB chưa nhìn thấy thiết bị/emulatorKiểm tra cáp, driver, AVD và đúng adb.exe
unauthorizedMáy tính chưa được thiết bị cấp quyền debugMở khóa màn hình, chấp nhận RSA hoặc revoke rồi kết nối lại
offlineTarget có record nhưng không trả lời ADBKhởi động lại kết nối/target, kiểm tra cáp và SDK
deviceADB đã kết nốiVới emulator vẫn phải kiểm tra Android boot xong

Có thể restart ADB server:

adb kill-server
adb start-server
adb devices -l

Lệnh này ngắt các kết nối ADB hiện tại. Đừng chạy giữa một test suite rồi ngạc nhiên vì session Appium chết theo.

Nhánh USB: không thấy thiết bị thật

Cáp và chế độ USB

Điện thoại vẫn sạc không chứng minh cáp có dây data. Thử một cáp đã biết chắc truyền file được, đổi cổng USB và tránh hub kém ổn định. Trên điện thoại, thử chọn chế độ File Transfer nếu OEM không expose debugging ở chế độ charge-only.

OEM driver trên Windows

Mở Device Manager. Nếu target nằm trong Other devices, có dấu chấm than hoặc chỉ nhận như thiết bị media, cài OEM USB driver từ nhà sản xuất. Google USB Driver không phải thần dược cho mọi hãng.

Sau khi cài, kiểm tra lại:

adb devices -l

RSA authorization

Nếu hiện unauthorized, mở khóa thiết bị và chấp nhận hộp thoại RSA. Nếu hộp thoại không còn hiện:

  1. vào Developer Options;
  2. chọn Revoke USB debugging authorizations;
  3. tắt rồi bật USB debugging;
  4. rút cắm lại cáp;
  5. chấp nhận khóa RSA mới.

Thao tác revoke sẽ xóa các máy tính đã được tin cậy cho USB debugging, nên thực hiện có chủ đích.

Kết nối lúc được lúc mất

Chạy theo dõi:

adb track-devices

Nếu target nhảy liên tục giữa device, offline và biến mất, nghi ngờ cáp/cổng/driver trước. Appium không thể giữ UiAutomator2 session trên một đường truyền lúc có lúc không.

Một số OEM có battery optimization hoặc security setting giết io.appium.uiautomator2.server/io.appium.settings. Chỉ thay đổi policy sau khi Appium log hoặc logcat cho thấy process bị dừng; không tắt sạch bảo mật điện thoại theo một comment vô danh trên forum.

Nhánh Android Studio: AVD không chạy hoặc không sẵn sàng

Liệt kê AVD và emulator đang chạy:

emulator -list-avds
adb devices -l

Nếu AVD không có trong danh sách đầu, system image hoặc cấu hình AVD chưa được tạo đúng trong Device Manager. Nếu có tên nhưng không khởi động, kiểm tra hardware acceleration:

emulator -accel-check

Emulator còn cần đủ disk, RAM và pagefile. Android Emulator kiểm tra dung lượng trống khi boot; máy gần đầy ổ mà cứ đổi capability Appium thì sai địa chỉ.

ADB thấy emulator nhưng test vẫn fail

device không có nghĩa Android đã boot xong. Kiểm tra:

adb -s emulator-5554 shell getprop sys.boot_completed

Kỳ vọng:

1

Nếu trống, chờ boot. Trong script chuẩn bị môi trường có thể polling có giới hạn:

$serial = 'emulator-5554'
$deadline = (Get-Date).AddMinutes(3)

do {
    [string]$booted = adb -s $serial shell getprop sys.boot_completed 2>$null
    if ($booted.Trim() -eq '1') { break }
    Start-Sleep -Seconds 2
} while ((Get-Date) -lt $deadline)

if ($booted.Trim() -ne '1') {
    throw "AVD $serial did not finish booting within 3 minutes"
}

Đây là polling cho precondition boot, không phải Sleep 180s bất kể máy nhanh hay chậm.

Cold Boot và Wipe Data không giống nhau

Thử Cold Boot trước khi snapshot lỗi. Wipe Data là thao tác phá hủy dữ liệu test trong emulator; chỉ dùng khi bạn chấp nhận cài và chuẩn bị lại mọi thứ. Reset tất cả để chữa một lỗi locator là cách rất hiệu quả để vừa mất dữ liệu vừa giữ nguyên lỗi.

Nếu lỗi render/GPU, thử cấu hình graphics khác trong AVD hoặc khởi động chẩn đoán bằng software rendering theo tài liệu Android Emulator. Đây là phương án debug, không nên mặc định ép software GPU cho cả team vì tốc độ sẽ giảm.

Tầng 4: Appium và UiAutomator2 có thực sự hoạt động?

appium driver list --installed
appium driver doctor uiautomator2
appium --log-level debug

Server log phải liệt kê UiAutomator2 là available. Nếu session startup lỗi sau khi vừa nâng major driver, thiết bị có thể còn APK server cũ. UiAutomator2 cung cấp lệnh dọn cache:

appium driver run uiautomator2 reset

Lệnh này dọn binary UiAutomator2 đã cache trên các thiết bị đang kết nối. Chỉ dùng khi log chỉ về mismatch/cached server hoặc sau upgrade; không chạy sau mọi test fail.

Với socket hang up, lấy logcat liên quan:

adb -s $env:ANDROID_UDID logcat -d |
    Select-String -Pattern 'io.appium.uiautomator2.server|AndroidRuntime|FATAL EXCEPTION'

Nếu là AVD, thay serial bằng emulator-5554. Cần phân biệt server UiAutomator2 crash, app under test crash và USB mất kết nối; cả ba đều có thể làm command từ Appium thất bại.

Tầng 5: session có trỏ đúng target không?

UiAutomator2 không dùng deviceName để chọn thiết bị. Kiểm tra udid thật:

adb devices -l
$env:ANDROID_UDID

Trong Robot Framework:

${session_id}=    Get Appium SessionId
${platform}=      Get Capability    platformName
${udid}=          Get Capability    appium:udid
Log Many    ${session_id}    ${platform}    ${udid}

Khi có một điện thoại và một emulator cùng nối, capability thiếu udid/avd có thể khiến driver chọn target đầu tiên. Bạn nhìn điện thoại không thấy action, trong khi emulator phía sau đang bấm khí thế.

InvalidSessionIdException nghĩa là session đã đóng, timeout hoặc driver chết. Không thể hồi sinh session cũ bằng tăng wait; tạo session mới sau khi xử lý nguyên nhân.

Tầng 6: app package và activity

Kiểm tra app đã cài:

adb -s $env:ANDROID_UDID shell pm list packages |
    Select-String 'io.appium.android.apis'

Kiểm tra activity đang foreground:

adb -s $env:ANDROID_UDID shell dumpsys activity activities |
    Select-String 'mResumedActivity|topResumedActivity'

Thử mở activity độc lập khỏi Appium:

adb -s $env:ANDROID_UDID shell am start -W `
    -n io.appium.android.apis/.app.SearchInvoke

Nếu am start -W cũng fail, sửa appPackage, appActivity, APK hoặc manifest trước. Appium không thể mở một activity không tồn tại chỉ vì capability được viết rất tự tin.

Tầng 7: element không thấy

Tại đúng thời điểm lỗi, lấy source và screenshot:

${source}=    Get Source
Log    ${source}    level=DEBUG
Capture Page Screenshot    locator-failure.png

Sau đó hỏi lần lượt:

  1. Element có xuất hiện trong XML không?
  2. Page source có đúng màn hình đang nhìn không?
  3. Có permission dialog, keyboard hoặc overlay che phía trên không?
  4. Locator có phụ thuộc text/ngôn ngữ hoặc index không?
  5. Element xuất hiện muộn và cần explicit wait không?
Wait Until Element Is Visible    ${SEARCH_BUTTON}    timeout=10s
Click Element    ${SEARCH_BUTTON}

Không chữa race condition bằng XPath khác. Locator đúng nhưng hỏi quá sớm vẫn fail.

Tầng 8: Appium báo click thành công nhưng UI không đổi

Đây là nhóm “gửi hành động không ghi nhận” mà nhìn log rất dễ cáu. Kiểm tra:

Kiểm tra context:

${context}=     Get Current Context
@{contexts}=    Get Contexts
Log Many    ${context}    ${contexts}

Native element không thể đưa thẳng vào action của WebView và ngược lại. Với gesture theo tọa độ, lấy kích thước hiện tại:

${width}=     Get Window Width
${height}=    Get Window Height
Log Many    width=${width}    height=${height}

Đừng hard-code tọa độ từ Pixel 7 rồi chạy trên một máy Samsung tỷ lệ khác và gọi đó là flaky.

Khi action chậm 10 giây trở lên

UiAutomator2 chờ accessibility event stream idle trước một số tương tác. Ứng dụng có animation chạy liên tục có thể khiến mỗi lệnh chờ gần hết waitForIdleTimeout.

Setting này có thể đổi qua Appium Settings API; giá trị 0 tắt hoàn toàn việc chờ idle. Lấy session ID bằng Get Appium SessionId, rồi từ PowerShell gọi:

$sessionId = 'SESSION_ID_TU_ROBOT'
$body = @{
    settings = @{
        waitForIdleTimeout = 0
    }
} | ConvertTo-Json -Depth 3

Invoke-RestMethod `
    -Method Post `
    -Uri "http://127.0.0.1:4723/session/$sessionId/appium/settings" `
    -ContentType 'application/json' `
    -Body $body

Chỉ áp dụng sau khi log/timing chứng minh idle wait là nguyên nhân. Tắt nó có thể khiến action chạy quá sớm và bấm sai trạng thái. Phương án tốt hơn vẫn là sửa animation/event stream của build test hoặc dùng wait thể hiện đúng trạng thái UI.

Một flow chẩn đoán ngắn

Giả sử Click Element pass nhưng điện thoại không đổi:

  1. adb devices -l: target còn device không?
  2. Get Capability appium:udid: session có đúng serial không?
  3. Get Current Context: có đúng NATIVE_APP không?
  4. Get Source + screenshot: element và overlay trông thế nào?
  5. Appium debug log: command click trả gì?
  6. logcat: app hay UiAutomator2 có crash không?

Đi hết sáu bước này, bạn ít nhất sẽ biết lỗi thuộc lớp nào. Còn restart máy, wipe AVD, đổi XPath và cài lại Appium cùng lúc có thể làm test chạy lại, nhưng bạn không biết cái gì đã sửa nó. Lần sau lỗi quay lại thì cả đội tiếp tục cúng máy.

Nguồn tham khảo