Quy mô và hiệu năng
Test app lifecycle thế nào
Bài kiểm thử đặc thù mobile nói phải test những trạng thái lifecycle nào. Bài này nói ép app vào từng trạng thái bằng lệnh gì, vì sao Don't keep activities cho kết quả xanh giả, và quy trình kiểm một flow rủi ro cao.
Nội dung bài
Kiểm thử đặc thù mobile liệt kê tám kịch bản lifecycle phải test và bốn flow phải test kỹ nhất. Bài đó dừng ở phải làm gì. Bài này là phần làm bằng cách nào — lệnh ép từng trạng thái, cái bẫy làm test xanh mà app vẫn hỏng, và ranh giới giữa việc máy chạy được với việc người phải ngồi làm.
Ép app vào từng trạng thái bằng lệnh gì
Không trạng thái nào trong bảng này cần chờ hệ điều hành tự làm. Chờ là cách chắc chắn nhất để không bao giờ test được.
adb shell input keyevent KEYCODE_HOMEadb shell am kill <package> — chỉ giết tiến trình đang ở background, đúng thứ cầnxcrun simctl terminate <device> <bundle-id> trên simulator, rồi mở lại từ springboardadb shell am send-trim-memory <package> COMPLETEadb shell input keyevent 26adb shell settings put global low_power 1adb rebootadb emu gsm call 5551234 trên emulatorDon't keep activities cho kết quả xanh giả
Đây là cái bẫy đắt nhất của nhóm này, vì nó làm test xanh chứ không làm test đỏ — không có tín hiệu nào báo động.
Don't keep activities — chỉ huỷ activity
- Bật trong Developer options, huỷ activity ngay khi rời màn hình
- Tiến trình vẫn sống: biến static, singleton, cache trong bộ nhớ còn nguyên
- App đọc lại state từ singleton, khôi phục đúng, test xanh
- Nhưng OS kill thật thì giết cả tiến trình, singleton về rỗng, app hỏng
am kill — giết cả tiến trình
- Giết đúng cái OS sẽ giết khi thiếu bộ nhớ
- Singleton, biến static, cache bộ nhớ đều mất
- Chỉ còn lại thứ đã ghi xuống đĩa trước khi mất quyền chạy
- Đây mới là phép đo trả lời đúng câu hỏi
Kiểm một flow rủi ro cao, bảy bước
Chạy cho từng flow trong bốn flow rủi ro cao, không chạy một lần cho cả app.
Ghi ra state kỳ vọng trước khi bắt đầu
Viết ra giấy: mở lại thì phải thấy màn hình nào, ô nào còn chữ gì. Không viết trước thì lúc mở lại sẽ tự thuyết phục mình rằng cái đang thấy là đúng.
Nhập dữ liệu dở dang
Dừng ở đúng giữa flow — OTP nhập ba trên sáu số, file upload được nửa, đơn hàng đã bấm thanh toán chưa có kết quả.
Đẩy xuống background
Nút Home, không phải nút Back. Back là user chủ động thoát, đó là kịch bản khác.
Giết tiến trình
adb shell am kill <package>. Kiểm lại bằngadb shell ps | grep <package>— không còn dòng nào mới là giết thật.Mở lại từ launcher
Bấm icon trên màn hình chính. Không mở lại bằng nút Run của IDE — Run cài đè bản mới và xoá mất đúng cái trạng thái vừa dựng.
So với state kỳ vọng đã viết ở bước 1
Khác một chữ cũng là không đạt. Màn trắng, hoặc nhảy về màn hình chủ, đều là không đạt.
Đếm số request app gửi sau khi mở lại
Xem qua proxy. Khôi phục state không được kéo theo một loạt API gọi lại từ đầu — ở 500.000 user, mỗi request thừa lúc mở app là 500.000 request thừa mỗi lần.
Cái gì máy chạy được
Chạy máy, mỗi pull request
Unit test cho lớp lưu và khôi phục state. Ghi state ra, dựng lại object từ số không, đọc vào, so sánh. Tính bằng mili giây, không cần thiết bị.
Chạy máy, mỗi pull request đụng màn hình
Instrumented test gọi thẳng hàm tái tạo activity của framework test, chạy trên emulator. Bắt được lỗi huỷ và dựng lại activity, không bắt được lỗi chết tiến trình.
Chạy người, trước mỗi release
Bảy bước ở trên cho bốn flow rủi ro cao. Video quay màn hình đính vào pull request, vì người duyệt không dựng lại được trạng thái đó trong đầu.
Không tự động hoá
Cuộc gọi đến, restart device, battery saver. Chi phí dựng cao hơn giá trị bắt lỗi — để trong checklist release, đừng để trong CI.
Giới hạn
Emulator không phải máy thật
Emulator gần như không bao giờ thiếu bộ nhớ, nên nó không tự sinh ra kịch bản OS kill. Mọi lần kill trên emulator đều là kill do mình gọi — nó chứng minh app chịu được kill, không chứng minh app bị kill đúng như ngoài đời.
Máy yếu mới là nơi lộ lỗi
Chọn máy cấu hình thấp nhất trong Ma trận thiết bị để chạy bảy bước ở trên, không chọn máy mạnh nhất.

