0

Trang trả về 200 nhưng vẫn hỏng: bài học kiểm thử chức năng từ một lần audit SEO

Chuyện bắt đầu từ một lần audit SEO

Có một khoảng thời gian vài tuần, khá nhiều bài trên blog công ty mình bị hỏng mà không ai hay biết.

Không phải kiểu hỏng có trang báo lỗi đỏ chót. Trang vẫn load bình thường, server vẫn trả về 200 đều đặn. Nhưng mở bài ra thì chỗ đáng lẽ có ảnh chỉ là một khung trống, còn link nội bộ trong bài thì dẫn thẳng tới 404.

Bọn mình phát hiện ra trong một lần audit SEO. Không phải nhờ test, cũng không phải do người đọc báo lại. Người đọc chỉ thấy ảnh trống, bấm link ra 404, rồi thoát. Vậy thôi.

Mọi thứ đều "chạy". Chỉ là nó không làm đúng việc của nó.

Mình không phải QA chuyên nghiệp. Mình làm gần sản phẩm và website, nên thường nhìn bug từ phía người dùng hơn là từ phía code. Bài này là những gì mình rút ra sau lần đó.

Kiểm thử chức năng, nói cho dễ hiểu

Nếu phải giải thích cho một người bạn, mình sẽ nói thế này: kiểm thử chức năng là kiểm tra xem thứ đó có thật sự làm được điều người dùng cần hay không, chứ không chỉ là nó chạy mà không crash.

Một bài blog không có nhiệm vụ trả về HTML. Nhiệm vụ của nó là để người ta đọc được, nhìn thấy hình minh hoạ, và bấm sang bài tiếp theo. Hỏng một trong mấy thứ đó là bài hỏng, status code nói gì cũng vậy.

Đặt cạnh các loại test khác thì đại khái như sau:

  • Unit test: kiểm tra từng hàm, từng component riêng lẻ.
  • Integration test: kiểm tra các phần có nói chuyện đúng với nhau không (API với DB, frontend với API).
  • Kiểm thử chức năng: nhìn từ bên ngoài, giống người dùng, xem tính năng có đúng yêu cầu không.
  • Non-functional: tốc độ, chịu tải, bảo mật.

Quan điểm riêng của mình: ranh giới giữa integration và functional không nằm ở chỗ test chạm vào bao nhiêu service, mà ở chỗ kỳ vọng đến từ đâu. "Endpoint trả về 200" là kỳ vọng đến từ code. "Người đọc thấy đủ mọi ảnh trong bài" là kỳ vọng đến từ yêu cầu.

Với cái blog của mình: CMS ổn, server ổn, file ảnh thì vẫn nằm ở đâu đó. Từng phần đều pass. Nhưng cả trang thì fail.

Bạn nào muốn đọc kỹ hơn về các loại, quy trình và cách viết test case thì bài tổng quan về kiểm thử chức năng này viết khá rõ, mình sẽ không nhắc lại ở đây. (Mình cũng bỏ qua luôn cái danh sách smoke, sanity, regression, UAT mỗi thứ một dòng định nghĩa. Đọc bao nhiêu lần rồi mà vẫn không nhớ nổi.)

Bug chức năng thường đến từ đâu

Đào lại vụ blog, mình thấy không có nguyên nhân nào to tát. Toàn là mấy thứ nhỏ cộng dồn lại.

  1. Thứ xung quanh nội dung thay đổi. URL ảnh đổi ở đâu đó trong quá trình, còn bài viết vẫn trỏ về chỗ cũ. Bài không đổi, xung quanh nó đổi.
  2. Link không ai chịu trách nhiệm. Link nội bộ viết một lần rồi thôi. Trang thì bị đổi tên, gộp, xoá. Cái link trong bài năm ngoái đâu có biết.
  3. Không ai định nghĩa thế nào là "xong". Vì không ai viết ra một bài viết "bình thường" là như thế nào, nên "load được là được" tự nhiên thành tiêu chuẩn.
  4. Test bằng góc nhìn của chính mình. Laptop xịn, đã đăng nhập, biết sẵn mọi thứ nằm ở đâu. Gần như là kiểu người dùng ít thực tế nhất.

Người dùng thì khắt khe hơn mình tưởng. Theo dữ liệu của Zendesk, hơn một nửa người tiêu dùng sẽ chuyển sang đối thủ chỉ sau một lần trải nghiệm tệ. Một khung ảnh trống giữa bài hướng dẫn chính là một trải nghiệm tệ.

Nhìn rộng ra thì CISQ ước tính chất lượng phần mềm kém đã gây thiệt hại ít nhất 2,41 nghìn tỷ USD cho nước Mỹ trong năm 2022. Con số to quá nên khó cảm nhận, nhưng phần của mỗi team thường trông giống một đường đồ thị đi xuống mà mình đổ lỗi nhầm chỗ cả tháng trời.

Cách mình làm bây giờ

Phía engineering, team tự động sinh API test từ traffic thật và chạy trong CI. Phần API vì thế được kiểm tra dựa trên request thật, không phải request do ai đó tưởng tượng ra.

Phía website và nội dung thì vẫn còn nhiều việc thủ công, và mình thấy cũng không sao:

  • Tự mở trang, cuộn, bấm link giống như một người đọc.
  • Cho công cụ audit chạy kiểm tra link hỏng và ảnh thiếu, để không phải đợi đến đợt audit lớn mới biết.
  • Xem recording của Microsoft Clarity để thấy người dùng bị kẹt hay rage-click ở đâu.

Với những bước kiểm tra lặp đi lặp lại, viết một script nhỏ là đủ. Ví dụ đoạn Playwright (Node.js) dưới đây kiểm tra ảnh hỏng trong một bài viết:

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com/blog/bai-viet-mau');

  // cuộn xuống cuối trang để ảnh lazy-load được tải
  await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
  await page.waitForLoadState('networkidle');

  // naturalWidth = 0 nghĩa là trình duyệt không hiển thị được ảnh
  const broken = await page.$$eval('article img', (imgs) =>
    imgs.filter((i) => !i.naturalWidth).map((i) => i.currentSrc || i.src)
  );

  console.log(broken.length ? broken : 'Không có ảnh hỏng');
  await browser.close();
})();

Trang dài thì nên cuộn từng đoạn thay vì nhảy thẳng xuống cuối, nếu không vài ảnh lazy-load ở giữa có thể chưa kịp tải và bạn sẽ nhận một đống cảnh báo sai.

Một ý kiến hơi trái chiều

Recording phiên của người dùng thật bắt được nhiều bug chức năng hơn một nửa số test case mà mọi người hay viết.

Phần lớn test case kiểm tra đúng cái mà developer mong đợi. Nhập đúng, bấm một lần, assert. Nhưng người dùng thật không đi theo kịch bản. Họ bấm vào ảnh vì tưởng đó là link. Họ bấm back giữa chừng khi đang điền form. Họ lướt qua cái nút mà mình chắc chắn là "rõ ràng lắm rồi". Xem mười cái recording là thấy những thứ không ai nghĩ tới để viết test.

Nói vậy không có nghĩa là bỏ automation. Cái gì ổn định và hỏng thì đau, cứ tự động hoá. Nhưng ý tưởng "tự động hoá được tất cả" thì mình không đồng ý. Có những thứ chỉ phát hiện được khi dùng sản phẩm như một người bình thường.

Sai lầm của mình

Tin vào "không có lỗi" quá lâu. Trang load được và trả về 200 là trong đầu mình coi như nó chạy. Nhưng một response 200 đi kèm form hỏng hay ảnh thiếu thì vẫn là một trang hỏng. Lý thuyết thì biết, thực tế thì vẫn nhìn status rồi đi tiếp, vì nhanh và có cảm giác như đã kiểm tra.

Nghĩ rằng người dùng sẽ báo. Người đọc blog không gửi bug report. Họ cũng chẳng bỏ đi một cách ồn ào. Họ chỉ đóng tab.

(Ngoài lề một chút: audit SEO chắc là cách tìm ra bug kém "ngầu" nhất. Không ai kể chuyện này trong buổi daily cho oai cả.)

Điều mình muốn giữ lại

Một trang load được chưa chắc đã là một trang hoạt động. Hãy kiểm tra điều người dùng cần, đừng chỉ nghe server nói.

Còn các bạn thì sao: bug "mọi thứ đều xanh" khó chịu nhất mà bạn từng gặp là gì, và cuối cùng ai là người phát hiện ra nó?


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.