Mở đầu — vì sao bài này quan trọng
Bạn đã viết test tự động, đã kiểm thử accessibility, đã đo performance. Nhưng có một sự thật phũ phàng: dù bạn kiểm thử kỹ đến đâu trên máy của mình, ứng dụng vẫn sẽ hành xử khác đi trên hàng trăm cấu hình thiết bị thật, trong tay người dùng thật, với thói quen sử dụng thật. Đó là lý do beta distribution — phân phối bản beta cho một nhóm người dùng chọn lọc trước khi phát hành chính thức — là mắt xích không thể thiếu trong quy trình QA di động.
Với vai trò QA, bạn không chỉ là người "test app rồi báo bug". Trong giai đoạn beta, bạn thường là người vận hành cả cỗ máy phân phối: build nào lên tay tester nào, ai đã cài, ai chưa mở, crash xảy ra ở build số mấy, feedback được gom về đâu. Nếu khâu này lỏng lẻo, bạn sẽ rơi vào cảnh dở khóc dở cười: dev fix bug ở build 47, nhưng tester vẫn đang report bug trên build 42 vì họ chưa cập nhật — và cả team mất nửa ngày để nhận ra điều đó.
Bài này tập trung vào hai kênh phân phối beta phổ biến và quan trọng nhất: TestFlight cho iOS và Internal Track (Google Play) cho Android. Đây là hai công cụ do chính Apple và Google cung cấp, miễn phí, tích hợp sẵn với hệ sinh thái store, và là thứ bạn gần như chắc chắn sẽ đụng tới ở bất kỳ team mobile chuyên nghiệp nào tại Việt Nam.
Khái niệm cốt lõi
Beta distribution là gì và khác gì với release chính thức
Release chính thức đưa app đến toàn bộ người dùng thông qua App Store / Google Play sau khi vượt qua review đầy đủ. Beta distribution đưa một bản build "chưa chính thức" đến một danh sách người thử nghiệm giới hạn, có kiểm soát. Mục tiêu: bắt lỗi thực địa, thu thập phản hồi UX, đo lường crash/performance trên thiết bị thật, và xác nhận app đủ "chín" để lên store.
Điểm mấu chốt mà QA phải nắm: beta không phải là bãi rác để đẩy build ẩu. Một bản beta tệ làm mất niềm tin của tester, khiến họ ngừng phản hồi. Vì vậy quy trình beta vẫn cần smoke test tối thiểu trước khi phát hành cho tester.
iOS — TestFlight
TestFlight là công cụ beta chính thức của Apple, quản lý qua App Store Connect. Có hai loại tester:
- Internal testers: là những người có vai trò trong tài khoản App Store Connect của bạn (Admin, Developer, Marketing...). Giới hạn tối đa 100 internal testers, mỗi người dùng được trên tối đa 30 thiết bị. Ưu điểm cực lớn: build không cần Apple review, có mặt gần như ngay lập tức (thường vài phút sau khi xử lý xong), rất phù hợp cho vòng lặp QA nội bộ nhanh.
- External testers: là người ngoài tổ chức — khách hàng, người dùng thực, nhóm tester thuê ngoài. Giới hạn tối đa 10.000 external testers. Điểm khác biệt quan trọng: build dành cho external cần qua Beta App Review của Apple (thường nhẹ hơn review chính thức, nhưng vẫn có thể mất vài giờ đến một ngày cho build đầu tiên của một version). Sau khi một build đã được duyệt, các build kế tiếp cùng version thường được duyệt nhanh hơn hoặc tự động nếu thay đổi nhỏ.
Android — Internal Track & các track khác
Google Play quản lý beta qua khái niệm testing tracks trong Play Console. Có ba track chính, xếp theo mức độ "công khai" tăng dần:
- Internal testing: nhanh nhất, dành cho tối đa 100 tester (theo email). Build có sẵn trong vài phút, không qua review như bản production. Đây là track tương đương gần nhất với "internal TestFlight". Rất lý tưởng cho QA cycle hàng ngày.
- Closed testing: dành cho nhóm tester lớn hơn, được kiểm soát qua danh sách email hoặc Google Group. Từ 2023, Google yêu cầu tài khoản developer cá nhân mới phải chạy closed testing với tối thiểu 20 tester trong 14 ngày trước khi được phép publish production — một điều QA cần biết khi làm với app mới.
- Open testing: ai cũng tham gia được qua link công khai, hiển thị hạn chế trên Play Store.
So sánh nhanh để định hình tư duy
| Tiêu chí | TestFlight Internal | TestFlight External | Play Internal | Play Closed |
|---|---|---|---|---|
| Số tester tối đa | 100 | 10.000 | 100 | Lớn (theo list/group) |
| Cần review? | Không | Có (Beta Review) | Không | Không (nhưng có policy) |
| Tốc độ có build | Vài phút | Vài giờ | Vài phút | Vài phút |
| File upload | IPA | IPA | AAB | AAB |
Tình huống thực tế
Tình huống 1 — Startup fintech ở TP.HCM và cái bẫy "build 90 ngày"
Một startup ví điện tử tại Quận 1, TP.HCM, đội mobile 6 người, dùng TestFlight cho vòng QA iOS. Team chạy sprint 2 tuần, mỗi sprint ra khoảng 3-4 build internal. Vấn đề xảy ra khi họ pause một tính năng lớn suốt gần 3 tháng để chờ giấy phép trung gian thanh toán. Khi resume, QA lead mở TestFlight thì phát hiện toàn bộ 8 build cũ đã hết hạn 90 ngày, tester không thể mở app để test regression.
Tệ hơn, một external tester quan trọng — đối tác ngân hàng — báo rằng họ "không mở được app" ngay trước buổi demo. Team hoảng loạn nửa buổi sáng.
Bài học rút ra: QA phải theo dõi ngày hết hạn của build TestFlight như một phần lịch làm việc. Với các đối tác external quan trọng, luôn giữ ít nhất một build "còn hạn dài" hoặc chủ động upload build mới trước mỗi mốc demo. Đừng bao giờ giả định build tháng trước vẫn còn cài được.
Tình huống 2 — App giao đồ ăn và cú "versionCode" ngớ ngẩn
Một team làm app giao đồ ăn (giả định tên FoodGo) ở Hà Nội dùng Google Play Internal testing. Dev build ra bản hotfix cho một crash ở màn hình thanh toán, gửi cho QA. QA cố upload AAB lên Internal track thì Play Console báo lỗi: "Version code 105 has already been used."
Hóa ra dev quên tăng versionCode sau khi build lại. QA mất 40 phút loay hoay vì tưởng lỗi ở tài khoản, cho tới khi đọc kỹ thông báo. Sau đó team đặt ra quy tắc: mọi build gửi QA phải đi kèm versionCode và một dòng changelog ngắn về việc "build này fix gì".
Bài học rút ra: Mỗi lần upload Android cần một versionCode duy nhất và lớn hơn lần trước. QA nên coi versionCode/build number như "biển số xe" của build — hỏi ngay khi nhận build. Việc gắn changelog vào mỗi build không chỉ giúp Android mà còn giúp cả team biết chính xác đang test cái gì.
Tình huống 3 — Nhầm build giữa tester và cơn ác mộng report sai
Một công ty outsourcing ở Đà Nẵng nhận dự án app đặt lịch spa. Họ có 12 external tester TestFlight là nhân viên phía khách hàng. Trong một tuần cao điểm, dev đẩy liên tục 5 build. Vấn đề: TestFlight mặc định không tự cập nhật app trên máy tester nếu họ tắt auto-update, nên nhiều tester vẫn mở build cũ. Kết quả: 3 bug "đã fix" tiếp tục được report, dev cãi nhau với QA rằng "tôi fix rồi mà".
QA lead cuối cùng phải thêm build number vào màn hình "About" của app (nhờ dev nhúng), và yêu cầu mỗi bug report bắt buộc kèm build number. Con số report trùng lặp giảm hẳn.
Bài học rút ra: Luôn hiển thị build number/version trong app (thường ở màn Settings/About) để tester chụp kèm khi báo lỗi. Đặt kỳ vọng rõ ràng với tester về việc cập nhật lên build mới nhất trước khi test. Một build number hiển thị rõ ràng tiết kiệm hàng giờ tranh cãi.
Hướng dẫn từng bước
A. Phát hành build lên TestFlight (iOS)
- Chuẩn bị build. Dev (hoặc CI) tạo Archive trong Xcode với đúng signing (distribution certificate + provisioning profile). Tăng build number cho mỗi lần upload cùng một version.
- Upload IPA. Chọn Distribute App → App Store Connect → Upload, hoặc export IPA rồi kéo vào Transporter. Chờ Apple "processing" (vài phút đến vài chục phút).
- Xử lý Export Compliance. App Store Connect sẽ hỏi về mã hóa (encryption). Trả lời đúng — nếu app chỉ dùng HTTPS chuẩn thì thường được miễn, nhưng đây là câu hỏi QA/PM cần thống nhất trước để không kẹt build.
- Gán tester. Vào TestFlight → chọn build → thêm Internal Testing group (có build ngay) hoặc External group (cần submit Beta App Review, điền "What to Test" — mô tả nội dung cần test).
- Mời tester. Qua email hoặc tạo Public Link. Tester cài app TestFlight từ App Store rồi accept lời mời.
- Theo dõi. Xem trạng thái Installed/Not Installed, số session, và crash reports ngay trong TestFlight.
B. Phát hành build lên Internal Track (Android)
- Chuẩn bị AAB. Dev/CI build file
.aab, ký bằng upload key. Đảm bảo versionCode tăng. - Vào Play Console → Testing → Internal testing → Create new release.
- Upload AAB, viết release notes (ghi rõ build fix gì / cần test gì).
- Quản lý tester list. Thêm email tester trực tiếp hoặc qua Google Group. Lưu ý: tester phải dùng đúng tài khoản Google đã được thêm.
- Save → Review → Rollout to Internal testing. Build sẵn sau vài phút.
- Chia sẻ opt-in link. Gửi link cho tester; họ mở link, chấp nhận, rồi cập nhật app qua Play Store.
- Theo dõi crash qua Android Vitals trong Play Console.
C. Quy trình QA bao quanh (áp dụng cho cả hai)
- Smoke test build trước khi phát hành cho tester — đừng đẩy build chưa mở được.
- Ghi changelog rõ ràng cho mỗi build: số hiệu build, bug đã fix, khu vực cần test kỹ.
- Yêu cầu tester report kèm build number.
- Đóng vòng feedback: gom bug về một nơi (Jira, Trello...), map từng bug với build number.
Lỗi thường gặp & mẹo
- Quên tăng build number/versionCode. Đây là lỗi upload phổ biến nhất. Mẹo: để CI tự tăng dựa trên số commit hoặc timestamp.
- Nhầm giữa build cần review và không cần review. iOS internal không cần review, external thì cần. Android internal không cần review như production. Lên kế hoạch thời gian dựa trên loại tester — đừng hứa với sếp "chiều nay khách external test được" nếu build chưa qua Beta Review.
- Build TestFlight hết hạn 90 ngày. Đặt reminder, hoặc coi việc kiểm tra hạn build là một mục trong checklist trước demo.
- Tester không cập nhật lên build mới. Nhắc bật auto-update trong TestFlight, và luôn hiển thị build number trong app để phát hiện ngay ai đang dùng build cũ.
- Tester Android dùng sai tài khoản Google. Rất hay gặp: người ta có 2-3 email Google trên điện thoại. Hướng dẫn họ kiểm tra đúng tài khoản đã được thêm vào tester list.
- Export Compliance làm kẹt build iOS. Thống nhất câu trả lời mã hóa với team trước, hoặc khai báo sẵn trong Info.plist để không bị hỏi lại mỗi lần.
- Không có kênh gom feedback. Tester report tứ tung qua chat, email, tin nhắn — bug thất lạc. Mẹo: dựng một form hoặc kênh duy nhất, và với iOS có thể tận dụng chức năng feedback tích hợp sẵn của TestFlight (tester chụp màn hình là gửi kèm được).
Bài tập thực hành
- Thiết kế checklist phát hành beta. Viết một checklist gồm các bước bạn sẽ làm trước khi đẩy một build lên internal tester (cả iOS và Android). Checklist phải bao gồm: smoke test, kiểm tra build number, viết changelog, và cách xác nhận tester nhận được build.
- So sánh timeline. Giả sử sếp yêu cầu bạn đưa build cho 5 nhân viên nội bộ (iOS + Android) và cho 200 khách hàng bên ngoài. Hãy phác thảo timeline dự kiến cho từng nhóm, chỉ rõ nhóm nào có build ngay và nhóm nào phải chờ review, và ước lượng thời gian.
- Xử lý sự cố. Một external tester TestFlight nhắn bạn: "App tôi mở lên báo hết hạn, không dùng được." Viết ra 3 bước bạn sẽ kiểm tra và cách khắc phục.
- Thiết kế bug report mẫu. Tạo một template bug report cho tester mobile, trong đó có trường build number/version là bắt buộc. Giải thích vì sao trường này quan trọng dựa trên tình huống 3 ở trên.
Tóm tắt
Beta distribution là cầu nối giữa "test trong phòng lab" và "phát hành cho cả thế giới". Với iOS, TestFlight cho phép internal testers (tối đa 100, không cần review, có build gần như ngay) và external testers (tối đa 10.000, cần Beta App Review), thông qua việc upload IPA bằng Xcode hoặc Transporter, và build có hạn 90 ngày. Với Android, Google Play Internal Track cho tối đa 100 tester, không cần review production, build sẵn trong vài phút qua việc upload AAB — với các track closed/open cho quy mô lớn hơn.
Là QA, giá trị của bạn ở khâu này không nằm ở việc bấm nút upload, mà ở kỷ luật quy trình: smoke test trước khi phát hành, luôn tăng build number, gắn changelog rõ ràng, hiển thị build number trong app, buộc tester report kèm build number, và đóng vòng feedback về một nơi. Ba tình huống thực tế đã cho thấy: hầu hết sự cố beta không đến từ công cụ, mà đến từ việc thiếu kỷ luật quản lý build. Nắm chắc hai kênh này và quy trình bao quanh, bạn sẽ biến giai đoạn beta từ một mớ hỗn loạn thành một chu trình phản hồi mượt mà, đáng tin cậy — nền tảng cho một bản release chất lượng.