Mở đầu — vì sao bài này quan trọng
Hãy tưởng tượng bạn vừa đăng ký một ví điện tử. Bạn nhập số điện thoại, hệ thống báo "Mã OTP đã được gửi". Bạn chờ. 30 giây. 1 phút. 2 phút. Không có tin nhắn nào. Bạn bực bội bấm "Gửi lại", rồi bỏ cuộc và gỡ ứng dụng. Với sản phẩm, đó không chỉ là một người dùng khó chịu — đó là một khách hàng vừa rời đi ngay ở bước đầu tiên, và không ai trong đội ngũ biết chuyện gì đã xảy ra.
Notification (thông báo) là kênh giao tiếp mỏng manh nhất giữa sản phẩm và người dùng. Nó đi qua vô số hệ thống bạn không kiểm soát: máy chủ SMTP, nhà mạng viễn thông, dịch vụ push của Apple và Google, bộ lọc spam của Gmail. Chỉ cần một mắt xích trục trặc là thông báo biến mất âm thầm — không lỗi, không cảnh báo, không ai hay. Đây chính là loại lỗi nguy hiểm nhất với một QA: lỗi im lặng.
Bài này tập trung riêng vào việc kiểm thử bốn kênh thông báo phổ biến nhất tại Việt Nam và Đông Nam Á: Email, SMS, Push Notification và Telegram. Chúng ta sẽ không bàn về nội dung của tin nhắn theo góc độ marketing, mà tập trung vào câu hỏi kỹ thuật của tester: thông báo có được gửi đi không, có đến nơi không, đến đúng người không, đúng lúc không, hiển thị đúng không, và không bị gửi trùng hay gửi sai. Đây là kỹ năng thực chiến mà hầu như dự án nào cũng cần đến — từ OTP đăng nhập, xác nhận đơn hàng, đến nhắc lịch học.
Khái niệm cốt lõi
Bốn kênh, bốn cơ chế, bốn kiểu lỗi khác nhau
Điều quan trọng đầu tiên phải hiểu: mỗi kênh thông báo đi qua một hạ tầng khác nhau, nên cách nó "hỏng" cũng khác nhau. Bạn không thể kiểm thử cả bốn theo cùng một checklist.
Email đi qua máy chủ SMTP của bạn, rồi qua các nhà cung cấp trung gian (SendGrid, Amazon SES, Mailgun), sau đó tới máy chủ nhận (Gmail, Outlook, Yahoo). Rủi ro lớn nhất: rơi vào Spam/Junk, bị cắt subject trên mobile, HTML render sai trên các mail client khác nhau, và delay hàng phút.
SMS đi qua một SMS gateway (Twilio, Stringee, SpeedSMS, eSMS ở Việt Nam) rồi qua nhà mạng (Viettel, Vinaphone, Mobifone). Rủi ro: giới hạn 160 ký tự (tin nhắn dài bị chia thành nhiều phần hoặc bị cắt), tiếng Việt có dấu làm giảm giới hạn xuống còn 70 ký tự (do dùng bảng mã Unicode UCS-2), brandname (tên người gửi) hiển thị sai, và độ trễ khi tải mạng cao.
Push Notification đi qua APNs (Apple) hoặc FCM (Firebase Cloud Messaging của Google). Rủi ro: device token hết hạn, người dùng tắt quyền thông báo, app đang ở foreground/background/killed cho hành vi khác nhau, deep link bấm vào không mở đúng màn hình.
Telegram đi qua Bot API. Rủi ro: chat_id sai, bot bị người dùng block, giới hạn rate limit (30 tin/giây tới các user khác nhau), và định dạng Markdown/HTML bị lỗi cú pháp làm cả tin không gửi được.
Vòng đời một thông báo — nơi các checkpoint kiểm thử nằm
Với bất kỳ kênh nào, hãy chia vòng đời thành các trạm kiểm soát rõ ràng:
- Trigger — sự kiện gì kích hoạt thông báo? (đơn hàng thành công, OTP, nhắc lịch). Kiểm thử: đúng điều kiện mới gửi, sai điều kiện thì không gửi.
- Compose — nội dung được ghép đúng chưa? Kiểm thử biến động (dynamic placeholder): tên người dùng, số tiền, link.
- Send — hệ thống gọi API gửi có thành công không? Kiểm thử response code, retry khi thất bại.
- Deliver — thông báo có tới thiết bị/inbox không? Đây là checkpoint hay bị bỏ sót nhất.
- Display — hiển thị đúng không? Subject, nội dung, hình ảnh, nút bấm.
- Action — người dùng bấm vào thì đi đâu? Deep link, tracking link.
Idempotency — chống gửi trùng
Đây là khái niệm sống còn với notification. Idempotency nghĩa là dù cùng một sự kiện được xử lý nhiều lần, thông báo chỉ gửi đúng một lần. Trong thực tế, hệ thống thường retry khi mạng chập chờn, và nếu không có cơ chế chống trùng, người dùng sẽ nhận 5 SMS OTP giống hệt, hoặc 3 email xác nhận cùng một đơn hàng. Đây là bug rất phổ biến mà tester phải chủ động săn tìm, không chờ nó tự lộ ra.
Tình huống thực tế
Ví dụ 1 — OTP tiếng Việt bị cắt tại một sàn TMĐT
Một sàn thương mại điện tử tại TP.HCM triển khai tính năng gửi mã xác thực khi người dùng đổi mật khẩu. Nội dung SMS thiết kế là: "Mã xác thực của bạn là 428193. Vui lòng không chia sẻ mã này với bất kỳ ai." — một câu 78 ký tự, có dấu tiếng Việt đầy đủ.
Trong môi trường test, mọi thứ hoạt động. Nhưng khi lên production, bộ phận chăm sóc khách hàng nhận hàng loạt phản ánh: khách chỉ thấy "Mã xác thực của bạn là 428193. Vui lòng không chia sẻ mã n" — câu bị cụt. Nguyên nhân: SMS tiếng Việt có dấu dùng bảng mã UCS-2, giới hạn chỉ 70 ký tự cho một segment. Câu 78 ký tự lẽ ra phải chia thành 2 segment, nhưng cấu hình gateway của họ đặt giới hạn cứng 1 segment để tiết kiệm chi phí, nên phần dư bị cắt phũ phàng.
Bài học: Khi test SMS tiếng Việt, luôn đếm ký tự và hiểu rõ ngưỡng 70 (có dấu) so với 160 (không dấu). Tester cần một test case riêng cho "nội dung dài vượt ngưỡng một segment" và kiểm chứng hành vi: chia đúng hay bị cắt. Nếu team quyết định giữ 1 segment để tiết kiệm, nội dung phải được rút gọn dưới 70 ký tự và bỏ dấu — và điều đó phải nằm trong acceptance criteria, không phải phát hiện sau khi ra mắt.
Ví dụ 2 — Email xác nhận đơn hàng rơi vào Spam ở một startup giao đồ ăn
Một startup giao đồ ăn ở Hà Nội gửi email xác nhận sau mỗi đơn. QA test kỹ: email tới inbox, HTML đẹp, link theo dõi đơn hoạt động. Release. Hai tuần sau, tỷ lệ khách mở email tụt xuống dưới 20%, và bộ phận vận hành báo nhiều khách khẳng định "không nhận được email nào".
Điều tra ra: đội marketing dùng chung tên miền gửi email cho cả email giao dịch (transactional) lẫn email quảng cáo hàng loạt. Một chiến dịch quảng cáo bị nhiều người bấm "Báo cáo spam", kéo tụt uy tín (reputation) của tên miền, khiến Gmail bắt đầu đẩy cả email xác nhận đơn — vốn quan trọng — vào Spam.
Bài học: Email delivery không chỉ là chuyện code. Tester cần kiểm tra các yếu tố hạ tầng: SPF, DKIM, DMARC đã cấu hình đúng chưa (đây là ba bản ghi DNS xác thực người gửi, chống giả mạo). Test không dừng ở "email tới inbox của tôi" mà phải kiểm với nhiều nhà cung cấp (Gmail, Outlook, Yahoo) và dùng công cụ như Mail-Tester để chấm điểm spam. Ngoài ra, email giao dịch nên tách domain riêng khỏi email marketing — đây là một khuyến nghị QA hoàn toàn có thể nêu trong bug report.
Ví dụ 3 — Push trùng lặp trên nền tảng học trực tuyến
Một nền tảng học trực tuyến gửi push nhắc học viên "Bạn có buổi học lúc 19:00 hôm nay". Do cấu hình cron job nhắc lịch chạy trên hai server đằng sau load balancer mà không có khóa chống trùng, mỗi học viên nhận đúng 2 push giống hệt nhau cách nhau vài giây. Ban đầu không ai để ý vì nó "chỉ hơi phiền". Nhưng khi hệ thống mở rộng lên nhắc nhiều loại sự kiện, con số nhân lên: có học viên nhận 6 push cho cùng một buổi học, dẫn tới nhiều người tắt hẳn quyền thông báo — và thế là các nhắc nhở quan trọng sau đó cũng mất luôn kênh.
Bài học: Test idempotency phải chủ động. Tester nên hỏi thẳng đội dev: "Nếu job chạy hai lần thì sao?" và thiết kế test case mô phỏng trigger lặp. Với push, một chỉ số cần theo dõi là tỷ lệ người dùng tắt quyền thông báo (opt-out) — nếu nó tăng đột biến sau một release, gần như chắc chắn có vấn đề về tần suất hoặc trùng lặp.
Hướng dẫn từng bước
Đây là quy trình kiểm thử một tính năng notification, áp dụng được cho cả bốn kênh:
Bước 1 — Lập ma trận kênh × trạng thái. Liệt kê từng kênh (Email/SMS/Push/Telegram) và từng loại thông báo (OTP, xác nhận, nhắc lịch). Với mỗi ô, xác định trigger, nội dung mẫu, và người nhận mong đợi. Ma trận này là bản đồ test của bạn.
Bước 2 — Kiểm thử Trigger. Xác nhận đúng sự kiện thì gửi, sai sự kiện thì không gửi. Ví dụ: đơn hàng bị hủy thì KHÔNG gửi email "cảm ơn đã mua". Test cả trường hợp âm tính (negative case) này — đây là nơi hay lọt bug.
Bước 3 — Kiểm thử Nội dung động. Đưa vào các giá trị biên: tên có dấu tiếng Việt ("Nguyễn Thị Ánh"), số tiền lớn (1.000.000 ₫), tên rỗng, tên chứa emoji hoặc ký tự đặc biệt. Kiểm tra placeholder được thay đúng, không lộ ra chuỗi kiểu "Xin chào {{user_name}}".
Bước 4 — Kiểm thử Send. Kiểm tra response từ API gateway. Giả lập lỗi (mất mạng, gateway trả 500) và xác nhận hệ thống retry đúng, không gửi trùng, và ghi log rõ ràng.
Bước 5 — Kiểm thử Deliver & Display trên thiết bị thật. Đây là bước không thể bỏ. Với email: mở trên Gmail web, Gmail app, Outlook, kiểm tra subject preview trên mobile (~50 ký tự). Với SMS: nhận trên máy thật, kiểm tra brandname, độ dài, tiếng Việt. Với push: test khi app ở foreground, background, và bị kill hẳn. Với Telegram: kiểm tra định dạng Markdown, nút inline button.
Bước 6 — Kiểm thử Action. Bấm vào mọi link/nút và xác nhận đi đúng nơi. Deep link push phải mở đúng màn hình trong app, kể cả khi app chưa mở sẵn.
Bước 7 — Kiểm thử biên & tiêu cực. Người dùng đã tắt quyền thông báo, số điện thoại không hợp lệ, email không tồn tại, Telegram bot bị block, token hết hạn. Hệ thống phải xử lý duyên dáng (graceful), không crash và không gửi nhầm cho người khác.
Lỗi thường gặp & mẹo
Lỗi 1 — Chỉ test "gửi thành công" mà không kiểm tra thực nhận. Response 200 từ gateway chỉ nghĩa là gateway đã nhận yêu cầu, không có nghĩa người dùng đã nhận. Luôn kiểm chứng ở đầu nhận trên thiết bị thật.
Lỗi 2 — Bỏ quên tiếng Việt có dấu. Với SMS đây là cạm bẫy kinh điển (70 vs 160 ký tự). Với email và push, dấu tiếng Việt có thể vỡ do lỗi encoding UTF-8, hiển thị thành "Tiếng Việt". Luôn có test data tiếng Việt đầy đủ dấu.
Lỗi 3 — Không test múi giờ. Push "nhắc lịch 19:00" phải theo giờ Việt Nam (UTC+7), không phải giờ server. Một thông báo gửi lúc 2 giờ sáng vì lệch múi giờ sẽ khiến người dùng khó chịu.
Mẹo 1 — Dùng công cụ chuyên dụng. Với email, dùng Mailtrap hoặc MailHog để bắt email trong môi trường test mà không gửi thật ra ngoài. Với API, dùng Mail-Tester để chấm điểm spam.
Mẹo 2 — Kiểm tra rate limit và chống spam nội bộ. Bấm "Gửi lại OTP" liên tục 10 lần — hệ thống có chặn không? Đây vừa là bảo mật vừa là trải nghiệm.
Mẹo 3 — Đặt bẫy idempotency. Luôn hỏi "nếu trigger chạy hai lần thì sao?" và test nó, đừng chờ nó tự lộ ra ở production.
Mẹo 4 — Test unsubscribe và quyền. Email marketing bắt buộc có link hủy đăng ký hoạt động được. Push phải tôn trọng việc người dùng đã tắt quyền — không được lách để gửi nữa.
Bài tập thực hành
- Viết ma trận test cho OTP. Sản phẩm gửi OTP qua cả SMS và Email. Hãy lập bảng test case gồm ít nhất 8 trường hợp, bao gồm: gửi thành công, số điện thoại sai định dạng, bấm gửi lại nhiều lần (rate limit), OTP hết hạn, tiếng Việt có dấu trong nội dung, và trường hợp gateway trả lỗi 500.
- Săn lỗi độ dài SMS. Cho nội dung: "Cảm ơn bạn đã đặt hàng tại cửa hàng của chúng tôi, đơn hàng #12345 đang được xử lý." Đếm số ký tự, xác định nội dung này cần bao nhiêu segment SMS khi có dấu tiếng Việt, và đề xuất phiên bản rút gọn dưới 70 ký tự.
- Thiết kế test case push đa trạng thái. Với một push "Bạn có tin nhắn mới", viết các test case cho ba trạng thái app: đang mở (foreground), chạy nền (background), và bị tắt hẳn (killed) — mô tả hành vi mong đợi và deep link cho từng trạng thái.
- Kịch bản idempotency. Mô tả cách bạn sẽ mô phỏng một cron job nhắc lịch chạy trùng hai lần, và cách bạn kiểm chứng rằng người dùng chỉ nhận đúng một thông báo.
Tóm tắt
Kiểm thử notification là kiểm thử một chuỗi mắt xích dễ đứt mà phần lớn nằm ngoài tầm kiểm soát của bạn. Bốn kênh — Email, SMS, Push, Telegram — mỗi kênh đi qua hạ tầng riêng và hỏng theo cách riêng: email rơi spam và vỡ HTML, SMS bị cắt vì tiếng Việt có dấu chỉ còn 70 ký tự, push phụ thuộc quyền và trạng thái app, Telegram lệ thuộc chat_id và định dạng.
Nguyên tắc vàng: đừng bao giờ dừng ở "đã gửi thành công". Phải đi hết vòng đời từ Trigger đến Action, kiểm chứng thực nhận trên thiết bị thật, luôn có test data tiếng Việt đầy đủ dấu, chủ động đặt bẫy idempotency để chống gửi trùng, và test cả những trường hợp tiêu cực — người dùng tắt quyền, gateway lỗi, token hết hạn. Lỗi notification nguy hiểm vì nó im lặng; nhiệm vụ của một QA giỏi là bắt nó lên tiếng trước khi khách hàng phải làm điều đó thay bạn.