Get in touch
or send us a question?
CONTACT

Mobile Gesture Testing: Làm sao để Drag/Drop, Pinch-Zoom, Multi-Touch chạy ổn định?🧩📱

Test các gesture phức tạp là nơi flaky “sinh sôi” nhanh nhất: drag/drop lệch 1px, pinch-zoom lúc nhận lúc không, multi-touch bị hệ điều hành “nuốt”, chạy local thì ổn nhưng lên CI/device farm lại đỏ 🤖.

Bài này tập trung vào chiến lược thực chiến để giảm flaky khi test:

  • 🖐️ Drag / Drop (kéo-thả)

  • 🔍 Pinch-Zoom (phóng-thu)

  • 🤏 Multi-touch (2+ ngón, rotate, pan + zoom đồng thời)


1) Vì sao gesture test hay flaky? 🔍

1.1 Gesture phụ thuộc “thời gian + tọa độ + trạng thái UI”

  • ⏱️ Timing: animation, inertia, scroll physics

  • 📍 Tọa độ: scale, safe area, notch, density, orientation

  • 🧠 Trạng thái: gesture recognizer, hit-test, z-index, overlay, loading

Chỉ cần 1 trong 3 yếu tố lệch nhẹ là:

  • kéo không “bắt” đúng view

  • drop rơi sai vùng

  • pinch bị hiểu thành scroll / double tap

  • multi-touch bị mất 1 pointer

1.2 CI/device farm khác máy bạn

  • 🤖 FPS thấp hơn → animation lâu hơn

  • 📶 độ trễ input cao hơn

  • 📱 kích thước màn hình khác

  • ⚡ chạy song song làm hệ thống bận → event bị trễ


2) Nguyên tắc vàng để giảm flaky ✨

✅ Nguyên tắc A: “Chờ điều kiện” thay vì “đoán thời gian”

Không sleep(500ms) để “cho chắc”. Hãy chờ:

  • spinner/overlay biến mất

  • view stable (không layout lại)

  • drag handle “ready”

  • zoom scale đạt giá trị mong muốn (hoặc trong khoảng)

✅ Nguyên tắc B: Chạm vào thứ “testable”, không chạm vào pixel ngẫu nhiên

  • Dùng accessibilityId / testId cho:

    • drag handle

    • drop zone

    • canvas container

    • zoom indicator (nếu có)

✅ Nguyên tắc C: Assert theo “khoảng dung sai” (tolerance)

Gesture mang tính analog → đừng assert kiểu “bằng đúng 1 giá trị”.

  • ví dụ zoom scale: chấp nhận 1.95–2.05 thay vì đúng 2.00

  • vị trí drop: chấp nhận trong bounding box thay vì đúng tọa độ tuyệt đối

✅ Nguyên tắc D: Tách “gesture engine” khỏi “test case”

Tạo helper chuẩn hoá: drag(from,to), pinch(center, scale), twoFingerPan(...)
→ giảm sai khác giữa test, dễ fix tập trung.


3) Chiến lược theo từng loại gesture 🧠🛠️

3.1 Drag/Drop 🧲

🔥 Lỗi flaky thường gặp

  • drag bắt nhầm view (hit-test sai)

  • drop “không thả” do chưa hover đủ lâu

  • scroll container tự cuộn khi kéo gần mép

  • drag bị hủy bởi animation/layout update

✅ Chiến lược giảm flaky

(1) Drag từ “handle” thay vì kéo cả item

  • item có thể có vùng click/scroll; handle ổn định hơn.

(2) Chia drag thành 3 pha rõ ràng

  • press & hold (đợi “drag mode” bật: rung/alpha/ghost)

  • move theo đường đi

  • release + chờ “drop completed” (UI state thay đổi)

(3) Tránh kéo sát mép màn hình

  • mép dễ kích hoạt auto-scroll / edge gestures của OS.

(4) Xác nhận “drop zone ready” trước khi thả

  • drop zone highlight / counter / label “Drop here”.

(5) Assert theo kết quả business

  • ví dụ item xuất hiện trong list đích, count tăng, trạng thái lưu thành công
    → đừng chỉ assert “tọa độ item”.


3.2 Pinch-Zoom 🔍🤏

🔥 Lỗi flaky thường gặp

  • pinch bị hiểu thành scroll

  • hai ngón không đồng bộ → scale nhảy

  • zoom có inertia → assert quá sớm

  • zoom giới hạn min/max khác giữa device

✅ Chiến lược giảm flaky

(1) Pinch quanh một “center” ổn định

  • center = giữa canvas/container, tránh vùng có gesture khác (map, scroll).

(2) Chạy pinch theo bước nhỏ (multi-step)

  • thay vì scale x2 ngay lập tức, chia 4–6 bước
    → giảm rủi ro mất pointer.

(3) Chờ “zoom settle”

  • đợi animation/inertia kết thúc (scale ổn định trong N ms).

(4) Assert theo khoảng

  • scale trong khoảng, hoặc UI indicator hiển thị đúng mức zoom.

(5) Khóa các yếu tố gây nhiễu

  • tắt double-tap-to-zoom trong test build (nếu có)

  • tắt/giảm animation (test mode)


3.3 Multi-touch (2+ ngón): pan+zoom, rotate, gesture chồng chéo 🖐️🌀

🔥 Lỗi flaky thường gặp

  • mất 1 ngón giữa chừng (pointer drop)

  • OS gesture cạnh màn hình “cướp” input

  • UI thread bận → event delay → recognizer reset

  • rotate/pinch/scroll tranh chấp nhau

✅ Chiến lược giảm flaky

(1) Test từng gesture đơn trước, rồi mới test “kết hợp”

  • pinch riêng ✅, pan riêng ✅, rotate riêng ✅
    → sau đó mới pan+zoom, rotate+zoom.

(2) “Gesture contract” rõ ràng trong app
Nếu bạn có thể can thiệp app:

  • hiển thị debug overlay: số pointer, scale, rotation, translation

  • expose state qua accessibility label / test API
    → test assert vào state thay vì đoán bằng mắt.

(3) Giảm mức độ “cạnh tranh gesture”

  • tạm disable scroll/parent gesture khi đang thao tác trên canvas

  • ưu tiên recognizer rõ ràng (fail-fast)

(4) Tránh edge zone

  • multi-touch gần cạnh rất dễ bị OS back/home gesture.

(5) Assert theo invariants

  • ví dụ sau pan+zoom: object vẫn nằm trong viewport, scale tăng, rotation thay đổi trong khoảng hợp lý.


4) “Testability hooks” – thứ giúp giảm flaky mạnh nhất 🔧✨

Nếu team dev cho phép thêm một số hook cho build test, bạn sẽ giảm flaky rõ rệt:

  • 🏷️ Test IDs đầy đủ cho vùng tương tác (handle/zone/canvas)

  • 🧊 Disable/Reduce animations khi TEST_MODE=1

  • 📐 Expose state: scale/offset/rotation (qua label hoặc debug endpoint)

  • 🧱 Stable layout: tránh re-layout khi đang gesture

  • 🧭 Deterministic physics: giảm inertia hoặc có “snap settle” nhanh

Gesture test ổn định không chỉ là chuyện framework; 50% là “thiết kế cho test”.


5) Kỹ thuật “chẩn đoán flaky gesture” nhanh 🔍🧾

Khi fail, hãy lưu:

  • 📸 screenshot before/after

  • 🎥 video (rất quan trọng)

  • 🧠 log gesture state (pointer count, scale, velocity)

  • 📍 tọa độ start/end + bounding boxes

  • ⏱️ timeline: lúc press, lúc move, lúc release

Sau đó phân loại:

  • Fail do không vào drag mode → thiếu wait/press-hold

  • Fail do drop không nhận → thả sớm/chưa ready

  • Fail do zoom chưa settle → assert quá sớm

  • Fail do mất pointer → bước pinch quá lớn / device lag


6) Checklist giảm flaky cho gesture suite ✅

  • 🔁 Không dùng sleep() bừa bãi; luôn wait theo điều kiện

  • 🏷️ Có testId cho handle/zone/canvas

  • 🧊 Có test mode tắt animation/giảm inertia

  • 📍 Gesture tránh mép màn hình, tránh vùng scroll

  • 🪜 Pinch theo step nhỏ + chờ settle

  • 🎯 Assert theo tolerance, ưu tiên assert theo business outcome

  • 🧰 Dùng helper gesture thống nhất toàn suite

  • 📸 Bật video/screenshot/log cho CI


Kết luận 🎯

Muốn test gesture phức tạp “xanh ổn định”, hãy nhớ 3 từ khóa:
Deterministic (ổn định), Observable (đo được), Tolerant (có dung sai).