Menu
ESC

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

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

Đang tải...

Test Search & Filter & Sort

Software Testing Fundamentals Bài 58/60

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

Nếu bạn mở bất kỳ ứng dụng nào bạn dùng hằng ngày — Shopee, Tiki, Lazada, một app ngân hàng, hay chính hệ thống quản lý nội bộ nơi bạn làm việc — gần như chắc chắn bạn sẽ thấy ba thứ này: một ô tìm kiếm (search), một bộ lọc (filter) và một tùy chọn sắp xếp (sort). Đây là bộ ba tính năng "xương sống" của hầu hết sản phẩm số có dữ liệu. Người dùng không nhớ URL của từng sản phẩm; họ gõ, họ lọc, họ sắp xếp để tìm ra thứ mình cần trong vài giây.

Chính vì phổ biến như vậy, đây cũng là khu vực dễ có bug nhất mà ít khi được test kỹ. Lý do là developer thường code phần "happy path" — gõ đúng từ khóa, ra đúng kết quả — rồi coi như xong. Nhưng thực tế người dùng gõ dấu tiếng Việt, gõ khoảng trắng thừa, dán cả đoạn văn vào ô search, chọn filter mâu thuẫn nhau, hoặc sắp xếp một cột có giá trị null. Mỗi tình huống đó là một cái bẫy.

Với riêng thị trường Việt Nam, độ khó còn tăng lên vì tiếng Việt có dấu, có nhiều cách gõ (Telex, VNI), có ký tự Unicode dựng sẵn và Unicode tổ hợp trông giống hệt nhau nhưng máy tính coi là khác nhau. Một tester QA giỏi ở Việt Nam bắt buộc phải nắm được cách test search/filter/sort một cách hệ thống. Bài này sẽ cho bạn một bộ khung tư duy đầy đủ, để lần sau khi nhận được một màn hình danh sách có tìm kiếm và lọc, bạn biết ngay phải "đánh" vào đâu.

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

Trước khi test, bạn phải hiểu rõ ba tính năng này khác nhau ở đâu, vì cách test mỗi cái khác nhau.

Search — tìm kiếm

Search là việc người dùng nhập một chuỗi từ khóa, và hệ thống trả về những bản ghi "khớp" với từ khóa đó. Điều quan trọng nhất bạn phải làm rõ với team trước khi test là quy tắc khớp (matching rule):

  • Khớp chính xác (exact match) hay khớp một phần (partial/substring)? Ví dụ gõ "sơn" có ra "kem chống nắng Anessa" không, hay chỉ ra sản phẩm có đúng chữ "sơn"?
  • Tìm theo trường nào? Chỉ tên sản phẩm, hay cả mô tả, mã SKU, tên thương hiệu?
  • Có xử lý dấu tiếng Việt không? Gõ "ao thun" không dấu có ra "áo thun" có dấu không?
  • Có phân biệt hoa/thường (case-sensitive) không? Thông thường là không, nhưng phải xác nhận.
Nếu spec không nói rõ những điều này, đó chính là điểm đầu tiên bạn — với tư cách QA — phải chất vấn. Test mà không có tiêu chí đúng/sai rõ ràng thì mọi kết quả đều vô nghĩa.

Filter — lọc

Filter thu hẹp tập kết quả dựa trên các thuộc tính có sẵn: khoảng giá, danh mục, thương hiệu, đánh giá sao, tình trạng còn hàng... Điểm cốt lõi cần kiểm là logic kết hợp filter:

  • Nhiều filter khác loại thường kết hợp bằng AND (thương hiệu = Samsung VÀ giá dưới 5 triệu).
  • Nhiều lựa chọn trong cùng một filter thường kết hợp bằng OR (màu Đỏ HOẶC Xanh).
  • Chuyện gì xảy ra khi filter cho ra 0 kết quả? Phải hiện thông báo tử tế chứ không phải màn hình trắng.
  • Filter có lưu trạng thái khi reload trang / bấm back không? Có phản ánh vào URL không (quan trọng cho việc chia sẻ link)?

Sort — sắp xếp

Sort thay đổi thứ tự hiển thị chứ không thay đổi tập dữ liệu. Điểm hay bị bỏ sót:

  • Sort tăng dần / giảm dần có đúng thật không, đặc biệt với số (sort theo kiểu chuỗi sẽ cho ra "10 < 2").
  • Giá trị null / rỗng được đẩy lên đầu hay xuống cuối?
  • Sort chữ tiếng Việt có đúng thứ tự bảng chữ cái (a, ă, â, b...) hay theo bảng mã Unicode thô?
  • Khi có nhiều bản ghi bằng nhau (tie), thứ tự có ổn định (stable) qua các lần load không?

Điểm giao nhau — sự tương tác

Cái khó thật sự nằm ở chỗ ba tính năng hoạt động cùng lúc. Người dùng search "áo", rồi filter giá dưới 200k, rồi sort theo giá tăng dần. Bạn phải kiểm rằng thứ tự áp dụng đúng: search + filter thu hẹp tập, sau đó sort mới áp lên tập đã thu hẹp — chứ không phải sort trên toàn bộ dữ liệu rồi mới lọc. Và khi người dùng gõ từ khóa mới, filter/sort đang chọn nên được giữ hay reset? Đây là quyết định thiết kế, và bạn cần biết đáp án để test.

Tình huống thực tế

Tình huống 1: Sàn thương mại điện tử và cái bẫy sort giá

Một sàn TMĐT tầm trung ở Việt Nam (gọi là "ChợViệt") ra mắt tính năng "Sắp xếp theo giá: Thấp đến cao". Đội dev test nhanh với 3 sản phẩm giá 50.000đ, 120.000đ, 300.000đ — chạy ngon, deploy.

Một tuần sau bộ phận chăm sóc khách hàng nhận phàn nàn: khách sort giá tăng dần nhưng sản phẩm 1.000.000đ lại đứng trước sản phẩm 90.000đ. Nguyên nhân: giá được lưu và so sánh dưới dạng chuỗi chứ không phải số. Khi so sánh chuỗi, ký tự "1" (của 1.000.000) đứng trước "9" (của 90.000), nên hệ thống nghĩ một triệu "nhỏ hơn" chín mươi nghìn.

Nếu tester ban đầu đưa vào bộ dữ liệu có số chữ số khác nhau — ví dụ 9.000đ, 90.000đ, 900.000đ, 1.200.000đ — bug này lộ ra ngay trong 30 giây. Bài học: khi test sort số, luôn dùng dữ liệu có độ dài chữ số khác nhau và trải rộng biên độ. Đừng bao giờ tin một sort chỉ vì nó "trông có vẻ đúng" với ba giá trị gần nhau.

Tình huống 2: App đặt món và bộ filter mâu thuẫn

Một app giao đồ ăn (giả định tên "NgonNgon") có bộ lọc: loại món (cơm, phở, bún...), khoảng giá, và "đang mở cửa". Một khách chọn filter "phở" + "giá dưới 30.000đ" + "đang mở cửa". Kết quả trả về 0 quán — hợp lý vì trong khu vực đó không có quán phở nào dưới 30k. Nhưng app hiển thị một màn hình trắng trơn, không chữ, không hình. Khách tưởng app bị treo, thoát ra và đặt bên đối thủ.

Tester đã kiểm "filter ra kết quả" nhưng quên kiểm "filter ra 0 kết quả". Đây là một empty state bị bỏ quên — một trong những lỗi phổ biến nhất của filter. Sau sự cố, đội QA thêm hẳn một mục checklist: mọi tổ hợp filter phải có ít nhất một ca test cho trường hợp 0 kết quả, và empty state phải có thông điệp rõ ràng kèm gợi ý ("Không tìm thấy quán phù hợp. Thử nới rộng khoảng giá?"). Bài học: empty state không phải chuyện "nice to have", nó là một ca test bắt buộc.

Tình huống 3: Tìm kiếm tiếng Việt và ký tự Unicode "ma"

Một hệ thống quản lý học viên (giống chính nền tảng khóa học) cho phép admin tìm học viên theo tên. Admin gõ "Nguyễn" để tìm bạn "Nguyễn Văn An" nhưng không ra kết quả, dù mắt thường thấy tên hiển thị đúng "Nguyễn Văn An" trong danh sách.

Điều tra ra: dữ liệu tên được nhập từ hai nguồn. Một nguồn dùng Unicode dựng sẵn (chữ "ễ" là một code point duy nhất U+1EC5). Nguồn kia dùng Unicode tổ hợp (chữ "e" + dấu mũ + dấu ngã, ba code point ghép lại). Nhìn giống hệt nhau, nhưng với máy tính là hai chuỗi khác nhau, nên phép so khớp thất bại.

Đây là lỗi kinh điển khi làm sản phẩm tiếng Việt, và tester bình thường không bao giờ phát hiện được nếu chỉ gõ tay, vì bàn phím của họ luôn sinh ra một dạng cố định. Bài học: với dữ liệu tiếng Việt, phải chủ động chuẩn bị test data ở cả hai dạng Unicode (normalization form NFC và NFD), và kiểm rằng hệ thống chuẩn hóa dữ liệu về một dạng thống nhất trước khi lưu và trước khi so khớp.

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

Đây là quy trình bạn có thể áp dụng cho bất kỳ màn hình search/filter/sort nào.

Bước 1 — Làm rõ spec trước khi viết ca test. Ngồi với BA/dev và chốt các câu hỏi: khớp một phần hay chính xác, tìm theo trường nào, có bỏ dấu tiếng Việt không, filter kết hợp AND hay OR, sort xử lý null ra sao, độ dài tối thiểu/tối đa của từ khóa. Ghi lại thành bảng để làm căn cứ đúng/sai.

Bước 2 — Test riêng từng tính năng (search, filter, sort độc lập). Đừng vội test tổ hợp. Cô lập từng cái để khi có bug bạn biết ngay nó nằm ở đâu.

Với search, phủ các nhóm đầu vào:

  • Query rỗng (theo spec: trả về tất cả hay không trả gì).
  • 1 ký tự, ký tự đặc biệt, khoảng trắng đầu/cuối, khoảng trắng giữa.
  • Từ khóa có dấu và không dấu tiếng Việt.
  • Từ khóa hoa/thường lẫn lộn.
  • Từ khóa dài bất thường (dán cả đoạn văn 500 ký tự).
  • Từ khóa chứa ký tự có ý nghĩa kỹ thuật: dấu %, gạch dưới, dấu nháy đơn ' — vừa để kiểm hiển thị, vừa để phát hiện lỗ hổng (ví dụ ký tự nháy đơn có thể liên quan đến rủi ro injection; xem thêm bài Security Testing).
  • Từ khóa không khớp gì cả (kiểm empty state).
Với filter, kiểm từng filter đơn lẻ, rồi tổ hợp hai-ba filter, rồi tổ hợp cho ra 0 kết quả, rồi hành động "xóa tất cả filter" (clear/reset).

Với sort, kiểm tăng dần, giảm dần, dữ liệu có null, dữ liệu số nhiều độ dài, dữ liệu chữ tiếng Việt, và tính ổn định khi có giá trị trùng.

Bước 3 — Test tương tác kết hợp. Đây là lúc kiểm search + filter + sort cùng lúc. Kịch bản mẫu: gõ từ khóa → thấy kết quả → thêm filter → kiểm tập thu hẹp đúng → đổi sort → kiểm thứ tự đúng trên tập đã lọc → đổi từ khóa → kiểm filter/sort giữ hay reset đúng như thiết kế.

Bước 4 — Test trạng thái và điều hướng. Reload trang: filter/sort có còn không? Bấm nút Back của trình duyệt: có quay về trạng thái trước không? Copy URL gửi cho đồng nghiệp: họ mở ra có thấy đúng kết quả đã lọc không? Phân trang (pagination): sang trang 2 rồi đổi sort, hệ thống có đưa về trang 1 không hay để bạn lạc ở trang 2 với dữ liệu đã đổi thứ tự?

Bước 5 — Test hiệu năng và biên. Search trên tập dữ liệu lớn có chậm không? Có debounce (chờ người dùng gõ xong mới gọi API) không, hay gõ mỗi ký tự là bắn một request? Kết quả có phân trang khi quá nhiều không?

Bước 6 — Ghi nhận bug rõ ràng. Khi tìm ra lỗi, mô tả chính xác từ khóa/filter/sort đã dùng, kết quả mong đợi và thực tế, kèm dữ liệu tái hiện (xem bài Bug Reporting để viết chuẩn).

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

Lỗi 1 — Chỉ test happy path. Gõ đúng từ, ra đúng kết quả rồi tick pass. Đây là cái bẫy lớn nhất. Luôn dành ít nhất một nửa số ca test cho đầu vào bất thường và empty state.

Lỗi 2 — Quên khoảng trắng. " áo " (có space đầu cuối) và "áo" phải cho cùng kết quả, trừ khi spec nói khác. Rất nhiều hệ thống quên trim khoảng trắng và trả về 0 kết quả một cách khó hiểu.

Lỗi 3 — Bỏ qua sort trên số dạng chuỗi. Như tình huống ChợViệt. Mẹo: luôn có test data số với 1, 2, 3, 4 chữ số trong cùng một tập.

Lỗi 4 — Không chuẩn bị test data tiếng Việt đủ hiểm. Mẹo: giữ sẵn một bộ "dữ liệu vàng" gồm tên có đủ dấu (Nguyễn, Đặng, Huỳnh, Phượng), cả dạng NFC lẫn NFD, cả có dấu lẫn không dấu, để tái sử dụng cho mọi dự án tiếng Việt.

Lỗi 5 — Tin vào giao diện mà không kiểm dữ liệu ngầm. Đôi khi UI hiển thị đúng nhưng do trùng hợp thứ tự dữ liệu gốc. Mẹo: cố ý nhập dữ liệu theo thứ tự ngược với kết quả mong đợi, để nếu sort không chạy thì bug sẽ lộ ngay.

Lỗi 6 — Không kiểm race condition khi gõ nhanh. Gõ "iph" rồi nhanh tay sửa thành "samsung", nếu API trả về chậm, kết quả cũ của "iph" có thể ghi đè lên kết quả "samsung". Mẹo: gõ nhanh, xóa nhanh, đổi từ khóa liên tục và quan sát kết quả cuối cùng có khớp từ khóa cuối cùng không.

Mẹo tổ chức: dùng kỹ thuật phân vùng tương đương và phân tích giá trị biên (đã học ở các bài EP và BVA) để chọn đầu vào search/filter đại diện, tránh test tràn lan mà vẫn phủ đủ. Với các bộ filter nhiều lựa chọn kết hợp, kỹ thuật pairwise (bài Pairwise Testing) giúp giảm số tổ hợp cần test mà vẫn giữ độ phủ cao.

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

Hãy chọn một ứng dụng thật bạn hay dùng — ví dụ trang tìm khóa học của chính nền tảng này, hoặc Tiki/Shopee — và làm các bài sau:

  • Thiết kế bộ ca test search: Viết ít nhất 10 ca test cho ô tìm kiếm, phủ đủ: query rỗng, 1 ký tự, có dấu / không dấu tiếng Việt, khoảng trắng thừa, ký tự đặc biệt (%, ', _), từ khóa siêu dài, và một từ khóa chắc chắn không có kết quả. Với mỗi ca, ghi rõ đầu vào, kết quả mong đợi và căn cứ (spec hoặc suy luận).
  • Kiểm logic filter kết hợp: Chọn hai bộ filter khác loại (ví dụ danh mục + khoảng giá). Lập bảng: filter A đơn, filter B đơn, A+B, A+B cho ra 0 kết quả. Xác định logic là AND hay OR bằng cách quan sát kết quả, rồi đối chiếu xem có đúng thiết kế không.
  • Bẫy sort số: Tìm một danh sách có sort theo giá hoặc theo số lượng. Cố ý tìm sản phẩm có giá chênh lệch số chữ số (vài nghìn, vài trăm nghìn, vài triệu). Sort tăng dần và kiểm xem thứ tự có đúng về mặt số học không.
  • Thử tiếng Việt nâng cao: Gõ một cái tên có dấu bằng hai cách khác nhau (nếu biết cách tạo NFD, dùng công cụ chuyển đổi online). Kiểm hệ thống có coi chúng như nhau không. Ghi lại kết quả.
  • Viết một bug report hoàn chỉnh cho bất kỳ lỗi nào bạn tìm được ở trên, theo chuẩn severity/priority đã học.

Tóm tắt

Search, filter và sort là bộ ba tính năng gần như luôn xuất hiện, và cũng gần như luôn có bug ẩn nếu chỉ test happy path. Với search, hãy làm rõ quy tắc khớp và tấn công bằng đầu vào rỗng, một ký tự, khoảng trắng, ký tự đặc biệt, và đặc biệt là tiếng Việt có dấu / không dấu cùng hai dạng Unicode NFC/NFD. Với filter, tập trung vào logic AND/OR khi kết hợp và đừng bao giờ quên ca test 0 kết quả cùng empty state tử tế. Với sort, cảnh giác với sort số dạng chuỗi, giá trị null, thứ tự chữ tiếng Việt và tính ổn định.

Quan trọng nhất là test sự tương tác giữa cả ba, cùng với trạng thái qua reload, back, URL và phân trang. Hãy chuẩn bị sẵn một bộ "dữ liệu vàng" tiếng Việt để tái sử dụng, và luôn cố ý nhập dữ liệu theo thứ tự ngược với kết quả mong đợi để bug không thể lẩn trốn. Nắm chắc bài này, bạn sẽ tự tin đối mặt với bất kỳ màn hình danh sách nào — thứ mà bạn sẽ gặp trong hầu hết mọi dự án phần mềm suốt sự nghiệp QA của mình.