Mỗi lần bàn chuyện làm automation UI cho kênh App ngân hàng, câu hỏi đầu tiên mình hay nghe là dùng tool gì, viết ngôn ngữ nào, hay có nên đưa AI vào tự chấm màn hình không.

Nhưng nhìn xuống phòng máy và quy trình đang chạy hàng ngày, bài toán thật sự lại nằm ở chỗ khác. Trước khi vẽ ra mô hình mới, mình muốn bày nguyên hiện trạng đang có lên bàn trước đã.

Tiền đề: Chúng ta đang có gì trong tay?

Ở điểm xuất phát hiện tại, đội ngũ không phải bắt đầu từ con số không. Về cơ bản, có ba thứ đã thành hình và chạy đều qua các đợt phát hành:

  1. Kiểm thử API theo tính năng dựa trên yêu cầu phát triển (YCPT): Mỗi khi làm tính năng mới hoặc sửa nghiệp vụ, QA bám theo tài liệu phân tích và thiết kế chi tiết để kiểm tra các API liên quan, đối chiếu request, response, mã lỗi và dữ liệu ghi xuống Database.
  2. Kiểm thử tải (Load Test): Phần chịu tải phía sau đã có kịch bản và hạ tầng tạo tải riêng (dùng k6) để bắn vào các API mới hoặc những chỗ thay đổi kiến trúc trước khi lên môi trường cao hơn.
  3. Hạ tầng Mobile Device Farm nội bộ: Đội đã dựng một dàn điện thoại thật phục vụ kiểm thử di động. Tuy nhiên, dàn máy này đang giao tiếp qua tầng API của hệ thống farm chứ không mở kết nối ADB trực tiếp cho kịch bản test. Bản thân các máy trên kệ vẫn để nguyên màn hình và viên pin zin, cắm cáp nguồn nuôi liên tục ngày này qua tháng khác. Đến hiện tại, một số máy đã có dấu hiệu phồng chai pin, còn khi chạy lâu thì nóng ran và xuống sức thấy rõ.
Minh họa hiện trạng dàn thiết bị kiểm thử cắm sạc liên tục với màn hình sáng, pin có dấu hiệu phồng và giao tiếp qua lớp API thay vì ADB trực tiếp
Minh họa hiện trạng dàn thiết bị kiểm thử cắm sạc liên tục với màn hình sáng, pin có dấu hiệu phồng và giao tiếp qua lớp API thay vì ADB trực tiếp

Nhìn trên báo cáo thì ba gạch đầu dòng này khá đủ: API có test, tải có đo, máy thật có farm. Vậy tại sao tới lúc cần đẩy mạnh kiểm thử giao diện (UI) và chạy hồi quy liên tục cho kênh App, guồng máy lại khựng lại?

Nhược điểm của hiện trạng: Chỗ nào đang làm khổ anh em vận hành?

Nếu chỉ chạy vài kịch bản ngắn để quay video demo thì thiết lập trên vẫn sống tốt. Nhưng đặt vào nhịp phát hành liên tục của một app ngân hàng với hàng chục miền nghiệp vụ từ mở tài khoản, chuyển tiền, thanh toán hóa đơn tới thẻ và tiết kiệm, những vết nứt lộ ra rất cụ thể.

1. Pin phồng, màn hình sáng và cơn ác mộng nhiệt độ

Điện thoại thương mại được thiết kế cho người dùng cầm đi làm rồi tối về cắm sạc, không phải để làm server chạy 24/7 trong tủ rack. Khi giữ nguyên viên pin trong máy, cắm nguồn nuôi suốt ngày đêm lại thêm màn hình bật sáng trưng mỗi ca test, nhiệt lượng tích tụ cực nhanh. Pin bị ép đầy điện áp liên tục cộng với nhiệt độ cao thì phồng rộp chỉ là vấn đề thời gian. Nhẹ thì bung nắp lưng, đội màn hình làm lệch cảm ứng; nặng thì mất an toàn cháy nổ ngay trong phòng máy.

Chưa cần đợi tới lúc pin hỏng, chỉ riêng chuyện máy nóng lên sau vài chục phút chạy liên tục đã đủ làm hệ điều hành tự hạ xung nhịp (thermal throttling). Lúc đó thao tác vuốt chạm trễ hẳn đi, chuyển trang giật cục, kéo theo kịch bản tự động hóa fail hàng loạt vì chờ phần tử không kịp — dù code ứng dụng chẳng có lỗi gì mới.

2. Farm giao tiếp qua API làm cụt tay khi cần điều khiển sâu

Giao tiếp với dàn máy qua lớp API bọc ngoài nghe thì gọn, nhưng vào làm UI automation thật mới thấy bí. Mất kết nối ADB trực tiếp là mất đi cái "ống nghe" cắm thẳng vào ruột thiết bị. Khi kịch bản chuyển tiền bị treo ở màn hình xác nhận, thứ Developer cần ngay là client log, stack trace và luồng gói tin mạng tại đúng giây phút đó. Qua lớp API farm hạn chế, việc rút log tức thời hay dọn dẹp trạng thái ứng dụng (clear data, cấp quyền, tắt popup hệ thống) trở nên chậm chạp và phập phù.

3. Bó tay trước các thao tác đặc thù của ngân hàng

Đi hết một luồng nghiệp vụ ngân hàng trên điện thoại, bạn liên tục đụng những chốt chặn gắn với phần cứng: xác thực sinh trắc học (vân tay), mở Camera quét mã VietQR hoặc chụp giấy tờ tùy thân (eKYC), và lấy tọa độ GPS.

Trên dàn máy chỉ mở cổng API cơ bản, làm sao bấm vân tay hay đưa tấm ảnh căn cước vào camera một cách tự động? Chẳng lẽ mỗi lần chạy regression tới bước quét QR lại cử người chạy vào phòng máy giơ tờ giấy trước từng cái điện thoại? Còn nếu định "root máy" để can thiệp sâu thì lại tự bắn vào chân: app ngân hàng có cơ chế chống root (Root Detection), thấy máy root là chặn đứng ngay từ cửa.

4. Test API từng tính năng không đồng nghĩa người dùng chạy được App

Khi test API đơn lẻ theo từng yêu cầu phát triển, tester tự chuẩn bị bộ dữ liệu đầu vào sạch từ DB rồi bắn thẳng vào API đang sửa. Trả về 200 OK là xong.

Nhưng trên App thực tế chạy kiến trúc Microservices, đầu vào của API bước sau lại lấy từ kết quả trả về của API bước trước thuộc miền nghiệp vụ khác, hoặc đọc từ cache dưới máy. Chỉ cần một dịch vụ trung gian trả thiếu dữ liệu là cả chuỗi phía sau gãy theo. Tệ hơn là cảnh khách đang ở màn hình chuyển tiền, một API chạy ngầm lấy thông tin khuyến mãi bị lỗi rồi ném thẳng cái popup báo lỗi hệ thống ra giữa màn hình. Gọi riêng API chuyển tiền thì vẫn xanh mượt, nhưng trải nghiệm người dùng trên App thì toang.

5. Backend chịu tải tốt chưa chắc App trên tay khách đã mượt

Công cụ như k6 chỉ đóng vai hàng vạn request đập vào cổng server, chứ không có màn hình để vẽ giao diện hay thanh RAM vài gigabyte của chiếc điện thoại tầm trung. Có những bản cập nhật mà API phản hồi trong tích tắc, nhưng bấm mở App phải chờ hơn 4 giây mới thấy ô đăng nhập; cuộn lịch sử giao dịch dài một chút là tụt khung hình; hoặc lặp lại vài chục giao dịch thì rò rỉ bộ nhớ (memory leak) gây văng ứng dụng (Crash / ANR). Nhìn biểu đồ tải phía server thì những lỗi này hoàn toàn vô hình.

Phân tích mô hình kiểm thử mới: Xếp lại từ gốc tới ngọn

Nhìn thẳng vào đống nhược điểm trên thì thấy ngay: nếu chỉ cắm đầu viết thêm script UI nhồi vào dàn farm cũ, kết quả sẽ là một đống kịch bản lúc xanh lúc đỏ (flaky) chạy trên những chiếc điện thoại đang phồng pin. Muốn giải quyết tận gốc, mình cần xếp lại mô hình kiểm thử: cái gì chặn được ở tầng dưới thì chặn thật sớm, phần nào đưa lên UI thì phần cứng và cơ chế bảo mật phải mở đường đúng chuẩn.

Ưu tiên theo rủi ro: Giữ tiền và giữ cổng trước

App ngân hàng có hàng trăm tính năng từ mở tài khoản, tiết kiệm, thẻ tới mua sắm. Đòi tự động hóa UI 100% ngay từ đầu là cách nhanh nhất biến dự án thành gánh nặng bảo trì. Nguồn lực cần dồn theo ba tiêu chí rủi ro: tác động tài chính trực tiếp (hạch toán, số dư, đối soát), tần suất sử dụng hàng ngày, và tuân thủ quy định pháp lý từ Ngân hàng Nhà nước (như xác thực sinh trắc học, hạn mức giao dịch).

Theo ba thước đo này, nhóm tính năng sống còn (Tier-1) phải bảo vệ kỹ nhất luôn là bốn luồng: Chuyển tiền, Thanh toán, Xác thực đăng nhập/sinh trắc học và OTP / Smart OTP.

Kim tự tháp kiểm thử 5 tầng cho kênh App

Thay vì để API đơn lẻ và UI đứng rời rạc, mô hình mới chia công việc thành 5 tầng rõ ràng (ngoài Unit Test thuộc trách nhiệm của đội Dev trên pipeline build):

Mô hình kim tự tháp kiểm thử 5 tầng cho ứng dụng ngân hàng từ API theo yêu cầu phát triển, API theo luồng người dùng, UI Appium đến kiểm thử tải và hiệu năng phía thiết bị
Mô hình kim tự tháp kiểm thử 5 tầng cho ứng dụng ngân hàng từ API theo yêu cầu phát triển, API theo luồng người dùng, UI Appium đến kiểm thử tải và hiệu năng phía thiết bị

Ở đáy tháp (Tầng 1), mình giữ nguyên phần kiểm thử API và Database theo yêu cầu phát triển đang làm tốt trên UAT. Tầng này tiếp tục gác cổng đầu vào, đầu ra và dữ liệu ghi xuống DB của từng API mới sửa.

Ngay phía trên là Tầng 2 — kiểm thử API theo luồng người dùng (User-flow API). Đây là mảnh ghép nối khoảng trống giữa Backend và App. Thay vì gọi từng API rời rạc, QA thu thập chuỗi log gọi API thực tế phát sinh khi thao tác trên App rồi dựng kịch bản bằng Playwright BDD bám sát tỷ lệ 1-1 với chuỗi gọi đó. Tầng này chạy nhanh trên CI mà không cần điện thoại, bắt sống lỗi lệch dữ liệu liên miền và chặn sớm chuyện dịch vụ phụ trả lỗi làm nhảy popup vô duyên trên màn hình chính.

Lên tới Tầng 3 mới là kiểm thử giao diện trên thiết bị thật. Những màn hình mới trong Sprint vẫn do QA test tay; còn phần hồi quy tự động dùng một lớp Appium gọn nhẹ (Thin Framework) để giữ bộ Smoke Test và các luồng tiền trọng yếu đã ổn định. Ngoài thao tác trên màn hình, kịch bản ở tầng này kiểm tra cả cách App ứng xử khi mạng chập chờn hoặc timeout, cũng như đối chiếu nội dung Push Notification, SMS và Email sau giao dịch. Những chỗ bắt buộc phải nhìn bằng mắt như biên lai chuyển tiền hay mã VietQR thì mới ghép thêm nhận diện ảnh (OCR / Computer Vision) có chọn lọc, tránh lạm dụng tràn lan.

Hai tầng còn lại chia nhau bài toán hiệu năng ở hai đầu. Tầng 4 mở rộng phần kiểm thử hiệu năng API hiện hữu bằng k6: ngoài tải thường ngày còn mô phỏng tải đỉnh dịp trả lương (Payday), sát Tết hoặc các cú vọt tải đột biến (Spike Test) khi bắn thông báo khuyến mãi. Quan trọng nhất ở tầng này là bài kiểm tra chuyển đổi dự phòng (Failover) — khi dịch vụ đứt giữa chừng lúc đang chuyển tiền, hệ thống phải xử lý Idempotency chuẩn để tuyệt đối không trừ tiền hai lần (No Double-charge).

Cuối cùng, Tầng 5 đo hiệu năng ngay trên thiết bị của người dùng (Client-side App Performance) với những ngưỡng chặn phát hành (Fail Gate) cụ thể: thời gian mở ứng dụng từ đầu (Cold Start P90) không quá 2,5 giây và quá 4 giây là chặn; chuyển màn hình dưới 300 ms; cuộn lịch sử giao dịch giữ từ 55 FPS trở lên; lặp 20 vòng giao dịch liên tiếp không tăng quá 15% RAM; và không chấp nhận bất kỳ lỗi Crash hay ANR nào trên các luồng Tier-1.

Cải tổ Device Farm: Tháo pin, tháo màn, chuyển sang ADB không root

Để Tầng 3 và Tầng 5 chạy bền bỉ mỗi ngày, dàn thiết bị nội bộ cần làm lại từ phần cứng tới giao thức điều khiển. Trước hết là chuyện phần cứng cho vận hành 24/7: mình vẫn dùng cụm điện thoại Android thật nhưng tháo bỏ viên pin, cấp nguồn trực tiếp để triệt tiêu nguy cơ phồng pin, đồng thời tháo luôn màn hình vật lý để giảm nhiệt và giữ máy chạy mát suốt ca regression dài.

Song song với phần cứng, kết nối vào dàn máy được chuyển từ lớp API đóng kín sang ADB Gateway trực tiếp. Nhờ mở đường ADB, mỗi khi kịch bản Appium trên Jenkins bị fail, hệ thống tự động rút luôn client log và vết mạng (network trace) đính kèm thẳng vào báo cáo lỗi cho Developer xử lý ngay, khỏi phải đoán mò.

Khi đã có đường ADB và Appium chuẩn trên UAT, cả ba bài toán hóc búa của app ngân hàng đều giải quyết được bằng phần mềm mà không cần đụng tới chuyện root máy: giả lập chạm vân tay qua ADB/Appium, bơm ảnh (image injection) trực tiếp vào luồng quét mã QR hoặc chụp giấy tờ eKYC, và dùng lệnh cmd location set-location để đặt tọa độ GPS. Còn nhu cầu kiểm tra tương thích trên nhiều đời iPhone/iOS hay các dòng Android phân mảnh trước đợt phát hành lớn thì thuê Cloud Device Farm bên ngoài theo giờ cho nhẹ gánh vận hành.

Tường kỹ thuật UAT và lộ trình triển khai

Mở đường bắt gói tin và đọc log qua ADB trên UAT giúp gỡ lỗi nhanh, nhưng khi ra môi trường thực tế, app ngân hàng bắt buộc phải khóa chặt SSL/TLS Certificate Pinning và đi qua nhánh Pentest (theo chuẩn OWASP MASVS/MASTG) độc lập trước khi lên Store. Để hai nhu cầu này không giẫm chân nhau, quy trình đóng gói cần dựng một bức tường kỹ thuật 5 lớp: tách gói cài đặt .uat riêng, chỉ bật cờ biên dịch ALLOW_DEBUG_PROXY=true ở nhánh UAT, khóa cứng SSL Pinning và tắt log ADB trên bản Pilot/Live, dùng khóa ký UAT keystore tách biệt, và đặt chốt chặn tự động trên CI (CI Pinning Gate) để quét mọi gói cài đặt — hễ thấy sót cờ debug, hậu tố .uat hay thiếu Pinning trên nhánh Pilot/Live là đánh Fail ngay lập tức.

Để đưa toàn bộ mô hình này vào guồng mà không làm đứt nhịp phát hành hiện tại, lộ trình triển khai nên chia làm ba chặng nối tiếp nhau. Ở giai đoạn đầu, đội tập trung chuẩn hóa kịch bản cho bốn luồng trọng yếu (Chuyển tiền, Thanh toán, Xác thực, OTP), xin cấp quyền có kiểm soát để QA chủ động dựng và reset dữ liệu test trên UAT, đồng thời mở rộng bộ kiểm thử sang tầng API theo luồng người dùng bám sát tỷ lệ 1-1 với log từ App.

Khi tầng dữ liệu và API theo luồng đã vững, giai đoạn hai mới bắt đầu dựng bức tường bảo mật .uat cùng chốt chặn CI Pinning Gate, song song với việc đưa bộ khung Appium mỏng lên chạy Smoke Test và các luồng tiền trên cụm ADB Farm đã tháo pin, tháo màn hình — đi kèm cơ chế giả lập vân tay, camera và GPS không cần root.

Sang giai đoạn ba, hệ thống mới lắp thêm các ngưỡng đo hiệu năng phía thiết bị (Tầng 5), tích hợp OCR có chọn lọc cho những màn hình biên lai hoặc mã QR, thuê thêm thiết bị trên cloud khi cần phủ rộng trước các đợt release lớn, và khép kín vòng lặp biến mỗi sự cố thực tế (RCA) thành kịch bản hồi quy tự động.

Khi tháo được cục pin đang phồng ra khỏi chiếc điện thoại trong tủ rack, mở được đường ADB tử tế có chốt chặn CI Pinning Gate gác cổng, và đẩy phần lớn gánh nặng kiểm tra tích hợp xuống tầng API User-flow 1-1, lúc đó tầng kiểm thử giao diện mới thực sự nhẹ gánh để làm đúng việc của nó.