Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Bài 17 — Network Conditions Testing

Đã đọc 0/13 mục · còn khoảng 11 phút
Cách chúng tôi ghi nhận

Một mục được tính là đã đọc khi nó nằm giữa màn hình đủ lâu so với độ dài của nó (bảng và sơ đồ tính một nửa), bạn vẫn đang cuộn hoặc bấm phím, và bạn đã thấy tới cuối mục. Lướt nhanh hoặc để tab mở không được tính. Chúng tôi chỉ lưu thời gian đọc từng mục — không lưu gì khác.

Mở đầu — vì sao bài này quan trọng

Hãy tưởng tượng bạn đang test một app đặt đồ ăn. Ở văn phòng, WiFi 100 Mbps, mọi thứ mượt như bơ: mở app, chọn món, thanh toán, xong. Bạn tick "pass" và về nhà. Sáng hôm sau, ticket đổ về ầm ầm: người dùng ở Cần Thơ mở app thấy màn hình trắng vĩnh viễn; người dùng ở Hà Nội đang thanh toán thì tàu điện chui vào hầm, app báo lỗi nhưng vẫn trừ tiền; một chị bán hàng ở chợ đầu mối mở app trên 3G chập chờn, ấn "Đặt đơn" hai lần vì lần đầu không thấy phản hồi, kết quả là hai đơn hàng trùng.

Không có bug nào trong số đó xuất hiện trên WiFi văn phòng. Tất cả đều là network conditions bug — lỗi chỉ lộ ra khi mạng chậm, chập chờn, hoặc chuyển đổi giữa các loại kết nối. Đây là loại lỗi bị bỏ sót nhiều nhất trong mobile QA, và cũng là loại gây ức chế người dùng nhất, vì nó xảy ra đúng lúc họ cần app hoạt động nhất.

Với thị trường Việt Nam, chủ đề này còn quan trọng gấp đôi. Người dùng của bạn không ngồi yên một chỗ với đường truyền ổn định. Họ di chuyển liên tục: rời WiFi quán cà phê ra đường bắt 4G, chui vào thang máy mất sóng, đi xe khách qua vùng phủ sóng yếu ở tỉnh lẻ. App của bạn phải sống sót qua tất cả những khoảnh khắc đó. Bài học này dạy bạn cách chủ động tái tạo những điều kiện mạng khắc nghiệt trong phòng test, thay vì chờ người dùng thật gặp phải rồi mới biết.

Khái niệm cốt lõi

Ba trục biến thiên của mạng

Khi nói "test điều kiện mạng", chúng ta không chỉ nói tới nhanh hay chậm. Có ba trục cần quan tâm:

  • Bandwidth (băng thông): lượng dữ liệu truyền được mỗi giây. Đây là con số marketing hay quảng cáo ("4G tốc độ cao"), nhưng thực ra ít quan trọng nhất với trải nghiệm app.
  • Latency (độ trễ): thời gian một gói tin đi từ thiết bị tới server và quay về (round-trip time - RTT). Trên 3G ở vùng phủ sóng yếu, latency có thể lên 500ms–2000ms. Đây mới là kẻ giết chết trải nghiệm: mỗi lần app gọi API là một lần chờ.
  • Packet loss / Jitter (mất gói / dao động): tỷ lệ gói tin bị rơi trên đường truyền, và độ dao động của latency. WiFi quán cà phê đông người, hay 4G trong đám đông concert, thường có packet loss cao dù bandwidth vẫn ổn.
Một QA giỏi phải test cả ba trục, không chỉ bóp bandwidth xuống rồi tưởng là đã xong.

Các profile mạng chuẩn cần test

Trong thực tế, bạn nên chuẩn hóa một bộ profile để test lặp lại. Bộ tối thiểu tôi khuyên dùng:

  • Offline: hoàn toàn mất mạng (sẽ nói kỹ ở Bài 18, ở đây chỉ test hành vi chuyển trạng thái).
  • 2G / GPRS: ~50 kbps, latency 500ms+. Nghe cổ lỗ nhưng vẫn tồn tại ở vùng sâu vùng xa Việt Nam.
  • 3G chập chờn: ~750 kbps–1.5 Mbps, latency 300–500ms, packet loss 1–5%. Đây là "vùng chết" phổ biến nhất.
  • 4G tốt: ~10–30 Mbps, latency 50–100ms.
  • WiFi không ổn định: bandwidth cao nhưng latency spike và packet loss — mô phỏng WiFi quán xá.
  • Network switching: chuyển WiFi ↔ 4G giữa chừng một thao tác.

Vì sao app "chết" khi mạng yếu

Có bốn nhóm nguyên nhân kỹ thuật bạn cần hiểu để biết mình đang săn con bug gì:

  • Timeout không được xử lý: request gọi đi, mạng chậm, request treo quá lâu. Nếu code không set timeout hợp lý hoặc không catch lỗi timeout, app sẽ đứng hình hoặc crash.
  • Không có retry / retry sai: request thất bại nhưng app không thử lại, hoặc thử lại vô tội vạ gây trùng lặp dữ liệu (như ví dụ đặt đơn hai lần ở đầu bài).
  • UI không phản hồi trạng thái loading: người dùng ấn nút, không thấy gì, ấn tiếp — vì app không hiện spinner hoặc không disable nút.
  • Race condition khi network switching: đang tải dở trên WiFi thì mất WiFi, request cũ trả về muộn ghi đè lên dữ liệu mới, gây hiển thị sai.

Tình huống thực tế

Ví dụ 1 — App gọi xe và cú "đặt trùng chuyến" trên 3G

Một công ty gọi xe công nghệ tại Đông Nam Á (gọi là "RideX" cho tiện) nhận nhiều phản ánh: tài xế thỉnh thoảng nhận được hai cuốc xe giống hệt nhau từ cùng một khách. Đội QA ban đầu không tái hiện được vì họ test trên WiFi văn phòng.

Khi họ bật profile 3G latency 800ms trên Charles Proxy để mô phỏng, bug lộ ra ngay. Kịch bản: khách ấn "Đặt xe", app gửi request tạo chuyến. Vì latency 800ms, khách chờ gần 2 giây không thấy phản hồi, tưởng app treo nên ấn "Đặt xe" lần nữa. App gửi request thứ hai. Server nhận cả hai, tạo hai chuyến. Nút "Đặt xe" không hề bị disable sau lần ấn đầu.

Bài học rút ra có hai tầng. Tầng UI: sau khi ấn nút gửi request, phải disable nút và hiện loading indicator ngay lập tức — không chờ server trả lời. Tầng backend: request tạo đơn cần một idempotency key (mã định danh duy nhất do client sinh ra) để server nhận diện và loại bỏ request trùng. QA phải viết test case kiểm tra cả hai lớp bảo vệ này dưới điều kiện latency cao. Đây là con bug bạn chỉ thấy khi test với latency, không phải bandwidth.

Ví dụ 2 — App ngân hàng và màn hình trắng khi chuyển WiFi sang 4G

Một ngân hàng số ở Việt Nam gặp tình huống: khách hàng phản ánh app hay bị "màn hình trắng" phải force-close mở lại. Log crash không rõ ràng vì app không thực sự crash — nó chỉ đứng.

QA tái hiện bằng kịch bản network switching: mở app trên WiFi nhà, đang load danh sách giao dịch thì tắt WiFi (điện thoại tự nhảy sang 4G). Request đang chạy trên WiFi bị hủy giữa chừng, nhưng code chỉ có onSuccess handler mà không có onFailure. Kết quả: màn hình mãi ở trạng thái loading, spinner biến mất nhưng nội dung không bao giờ tới, để lại màn hình trắng.

Đội QA dùng công cụ Network Link Conditioner (iOS) và bật/tắt WiFi thủ công để tái hiện. Fix là thêm error handling đầy đủ cho mọi request, kèm nút "Thử lại" khi request thất bại. Bài học: mọi request phải có đường xử lý lỗi, và QA phải chủ động test kịch bản network switching giữa chừng thao tác, chứ không chỉ test ở trạng thái mạng ổn định. Với app tài chính, một màn hình trắng lúc khách đang chuyển tiền là mất niềm tin nghiêm trọng.

Ví dụ 3 — App thương mại điện tử và ảnh sản phẩm "ăn" hết băng thông ở tỉnh

Một sàn TMĐT nhận thấy tỷ lệ chuyển đổi ở các tỉnh miền Tây thấp bất thường. Đội QA bật profile 2G/GPRS 50 kbps để trải nghiệm như người dùng vùng phủ sóng yếu. Họ phát hiện trang danh mục tải về ảnh sản phẩm độ phân giải full (mỗi ảnh 1–2 MB) ngay cả trên màn hình chỉ hiển thị thumbnail nhỏ. Trên 2G, một trang danh mục mất gần 90 giây để load xong ảnh — người dùng bỏ đi từ lâu.

Bài học: đây không phải bug logic, mà là bug về performance dưới điều kiện mạng thực tế. QA phát hiện ra thì dev mới bổ sung việc tải ảnh theo kích thước phù hợp (thumbnail nhẹ trước, ảnh lớn khi cần), lazy-load ảnh ngoài màn hình, và hiện placeholder trong lúc chờ. Điểm mấu chốt: bạn sẽ không bao giờ thấy vấn đề này nếu chỉ test trên WiFi. Việc bóp băng thông xuống mức người dùng thật đang chịu là cách duy nhất để "cảm" được nỗi đau của họ.

Hướng dẫn từng bước

Dưới đây là quy trình test điều kiện mạng bạn có thể áp dụng ngay.

Bước 1 — Chọn công cụ theo nền tảng.

  • Trên iOS Simulator và thiết bị iOS thật: dùng Network Link Conditioner (cài qua Additional Tools for Xcode, hoặc bật trên Settings > Developer trên máy thật). Nó cho phép chọn profile 3G, Edge, 100% Loss, hoặc tự định nghĩa bandwidth/latency/packet loss.
  • Trên Android: dùng emulator với lệnh telnet để set network speed/delay, hoặc dùng developer options. Thực tế hơn, đa số team dùng Charles Proxy hoặc Proxyman làm proxy để bóp băng thông (Throttle Settings) cho cả iOS lẫn Android qua cùng một máy.
  • Với Appium/automation: có thể set network condition qua Chrome DevTools Protocol (cho webview) hoặc dùng driver.set_network_connection để bật/tắt WiFi/data trên Android trong test tự động.
Bước 2 — Chuẩn hóa bộ profile. Định nghĩa sẵn 5–6 profile như phần khái niệm (2G, 3G chập chờn, 4G, WiFi không ổn định, offline, switching). Lưu chúng thành preset trong công cụ để cả team dùng chung, đảm bảo test lặp lại được.

Bước 3 — Xác định các flow rủi ro cao. Không cần test mọi màn hình với mọi profile. Ưu tiên: đăng nhập, thanh toán, đặt đơn/gửi form, upload ảnh, và bất kỳ thao tác nào ghi dữ liệu (write operation). Đây là nơi bug mạng gây thiệt hại thực sự.

Bước 4 — Chạy từng flow qua từng profile và quan sát ba câu hỏi. Với mỗi thao tác, luôn hỏi: (a) App có hiện trạng thái loading rõ ràng không? (b) Khi request thất bại, có thông báo lỗi và đường phục hồi (nút thử lại) không? (c) Thao tác ghi dữ liệu có bị lặp/trùng khi người dùng thao tác lại không?

Bước 5 — Test kịch bản chuyển đổi mạng. Cố tình tắt WiFi giữa lúc một request đang chạy, hoặc bật chế độ máy bay 2 giây rồi tắt. Quan sát app có phục hồi được không, hay đứng hình.

Bước 6 — Ghi lại số liệu, không chỉ pass/fail. Ghi rõ "trên 2G, trang chủ load 45 giây" — con số cụ thể thuyết phục dev và PM hơn nhiều so với "chậm".

Lỗi thường gặp & mẹo

  • Chỉ test bandwidth, quên latency và packet loss. Nhiều bug tệ nhất (như đặt đơn trùng) đến từ latency cao chứ không phải bandwidth thấp. Luôn test riêng một profile "bandwidth cao nhưng latency cao và packet loss" để mô phỏng WiFi quán xá.
  • Test trên mạng "hoàn hảo giả tạo". WiFi văn phòng ổn định là kẻ thù của QA. Hãy coi việc test trên mạng yếu là mặc định, không phải ngoại lệ.
  • Quên trạng thái trung gian. Bug hay ẩn ở khoảnh khắc đang chuyển đổi — đang load dở thì mất mạng. Đừng chỉ test trạng thái tĩnh (mạng tốt hoặc mất hẳn), hãy test cả lúc giao thoa.
  • Không phân biệt lỗi client-timeout và server-error. App nên hiển thị thông báo khác nhau: "Mạng chậm, đang thử lại" khác với "Máy chủ gặp sự cố". Người dùng cần biết vấn đề ở đâu.
  • Mẹo — dùng "airplane mode toggle" nhanh. Bật/tắt chế độ máy bay là cách rẻ và nhanh nhất để test mất mạng đột ngột trên thiết bị thật, không cần công cụ gì.
  • Mẹo — test với pin yếu. Nhiều điện thoại giảm hiệu năng mạng khi vào chế độ tiết kiệm pin. Kết hợp test mạng yếu + pin yếu để mô phỏng người dùng thật ngoài đường.
  • Mẹo — kết hợp proxy để xem cả nội dung request. Charles/Proxyman vừa bóp băng thông vừa cho bạn thấy request nào chậm, request nào retry, giúp báo cáo bug chính xác hơn.

Bài tập thực hành

  • Dựng bộ profile. Cài Network Link Conditioner (iOS) hoặc bật Throttle trong Charles/Proxyman. Tạo và lưu 4 profile: 2G, 3G chập chờn (thêm packet loss 3%), 4G, và WiFi không ổn định (bandwidth cao, latency 400ms).
  • Săn bug đặt trùng. Chọn một app có thao tác gửi form hoặc đặt đơn (có thể là app demo của bạn). Bật profile 3G latency cao, thực hiện thao tác gửi và cố tình ấn nút hai lần. Ghi lại: nút có bị disable không? Có hiện loading không? Dữ liệu có bị trùng không? Viết một bug report hoàn chỉnh nếu phát hiện vấn đề.
  • Test network switching. Mở một màn hình cần tải dữ liệu từ server. Ngay khi đang load, tắt WiFi (để máy nhảy sang 4G) hoặc bật chế độ máy bay 2 giây. Quan sát và ghi lại app phản ứng thế nào: phục hồi được, đứng hình, hay màn hình trắng.
  • Đo performance dưới 2G. Chọn một trang nhiều hình ảnh. Bật profile 2G, dùng đồng hồ bấm giờ đo thời gian trang load xong. Ghi con số cụ thể và đề xuất ít nhất hai cải tiến (ví dụ: ảnh thumbnail, lazy-load, placeholder).

Tóm tắt

Network conditions testing là kỹ năng phân biệt một QA mobile hời hợt với một QA thực thụ. Điểm cốt lõi cần nhớ:

  • Mạng biến thiên trên ba trục: bandwidth, latency, và packet loss/jitter — phải test cả ba, đừng chỉ bóp bandwidth.
  • Chuẩn hóa một bộ profile (2G, 3G chập chờn, 4G, WiFi không ổn định, offline, switching) để test lặp lại được.
  • Bug mạng tệ nhất thường đến từ latency cao (đặt đơn trùng) và network switching giữa chừng (màn hình trắng), không phải bandwidth thấp.
  • Với mỗi flow rủi ro, luôn kiểm tra ba điều: trạng thái loading rõ ràng, xử lý lỗi có đường phục hồi, và không lặp/trùng dữ liệu khi thao tác lại.
  • Bối cảnh Việt Nam đòi hỏi bạn coi mạng yếu và di chuyển liên tục là mặc định, không phải trường hợp hiếm.
Công cụ chính: Network Link Conditioner cho iOS, Charles/Proxyman cho cả hai nền tảng, và chế độ máy bay để test mất mạng đột ngột. Khi bạn quen với việc "sống trong mạng yếu" lúc test, bạn sẽ bắt được cả một lớp bug mà đội dev không ngờ tới — và đó chính là giá trị bạn mang lại.

Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi