·

Tiếng Việt: Real World Workflow Frontend Debugging And Qa Automation

Real World Workflow Frontend Debugging And Qa Automation

Bốn bài trước trong module này đã trang bị cho bạn từng mảnh ghép riêng lẻ: Puppeteer MCP (MCP — Model Context Protocol, giao thức giúp AI agent gọi được các tool bên ngoài, ở đây là tool điều khiển trình duyệt) là gì, cách cài đặt nó với Claude Code, OpenCode, Gemini CLI, và Cursor. Nhưng biết cài đặt và biết dùng trong công việc thật là hai chuyện khác nhau. Bài này là bài capstone (bài tổng kết) của module — ghép tất cả mảnh ghép đó lại thành một case study đầu-cuối, mô phỏng đúng những gì một kỹ sư frontend hoặc QA Engineer sẽ làm khi nhận một bug report thật ngoài đời.

Chúng ta sẽ đi theo một bug cụ thể, xuyên suốt cả bốn phần: từ lúc ticket được tạo, đến lúc agent tái hiện được lỗi, chẩn đoán nguyên nhân, và cuối cùng verify (xác nhận) fix cùng chạy regression test. Nếu bạn đọc xong bài này và áp dụng được quy trình tương tự cho một bug thật của team mình, coi như module đã đạt mục tiêu.

Workflow Overview: Từ Frontend Bug Report Đến Verified Fix Bằng Puppeteer MCP

Trước khi vào chi tiết từng bước, hãy hình dung toàn cảnh workflow — giống như một sơ đồ luồng (flow diagram) bằng lời:

[Bug Report] --> [Agent reproduce bug] --> [Agent diagnose root cause]
      |                                              |
      v                                              v
[QA/Dev review report]                    [Dev applies code fix]
                                                      |
                                                      v
                                    [Agent verify fix + run regression]
                                                      |
                                                      v
                                          [Ticket closed / re-opened]

Bug Scenario Xuyên Suốt Bài Viết

Để mọi thứ cụ thể thay vì lý thuyết suông, ta dùng một bug report thật giống như bạn sẽ thấy trên Jira hoặc Linear:

Ticket #4821 — Checkout: Nút "Apply Coupon" không phản ứng khi bấm
Môi trường: Production build (đã verify không xảy ra ở dev/local build)
Bước tái hiện: Đăng nhập → thêm 1 sản phẩm vào giỏ → vào trang /cart → nhập mã coupon bất kỳ vào ô input → bấm nút "Apply Coupon".
Kết quả mong đợi: Giá được cập nhật, hoặc hiện thông báo lỗi nếu mã coupon không hợp lệ.
Kết quả thực tế: Không có gì xảy ra. Không toast, không loading state, không network request nào được gửi (theo report của user, chưa verify).

Đây là dạng bug rất phổ biến và khó chịu: chỉ xảy ra ở production, không xảy ra ở dev build. Loại bug này thường liên quan đến minification (rút gọn code), tree-shaking (loại bỏ code không dùng tới khi build), hoặc biến môi trường khác nhau giữa hai môi trường — những thứ mà một developer ngồi debug trên máy local với dev server sẽ không bao giờ thấy được, trừ khi họ chủ động build production và test lại.

Phân Vai: Ai Làm Gì Trong Workflow Này

Điểm quan trọng cần làm rõ ngay từ đầu — AI agent không thay thế con người trong workflow này, nó thay thế phần lặp đi lặp lại và tốn thời gian thao tác tay:

  • QA/Dev (con người) viết prompt ban đầu: mô tả bug, đường link, bước tái hiện, và mục tiêu cụ thể (tái hiện, chẩn đoán, hay verify).
  • Agent (tự động qua Puppeteer MCP) thực hiện: điều hướng trình duyệt, tương tác UI, chụp screenshot, đọc DOM, đọc console log, đọc network request — toàn bộ phần thao tác tay lặp lại mà QA vẫn làm bằng chuột và F12 mỗi ngày.
  • Con người vẫn phải phán đoán: agent có thể báo cáo "tôi thấy lỗi TypeScript trong console", nhưng quyết định sửa như thế nào, có ảnh hưởng tới module nào khác không, và có nên release ngay hay cần thêm review — đó vẫn là trách nhiệm của developer/QA lead, không giao phó cho agent.

Nói cách khác: agent là một junior QA cực kỳ nhanh nhẹn và không bao giờ mệt, nhưng thiếu context nghiệp vụ và không chịu trách nhiệm quyết định cuối cùng.

Mẹo: Trước khi bắt đầu bất kỳ session debugging nào với Puppeteer MCP, hãy chuẩn bị sẵn một file "context ngắn" (product context, tài khoản test, base URL của từng môi trường) để paste vào đầu prompt. Agent càng có nhiều context đúng ngay từ đầu, số vòng lặp "thử lại" càng ít, tiết kiệm cả thời gian lẫn token.

Bước 1: Tái Hiện Bug — Agent Điều Hướng UI Và Ghi Lại Trạng Thái Lỗi

Mục tiêu của bước này chỉ có một: chứng minh bug có thật, tái hiện được một cách nhất quán, và có bằng chứng (screenshot, log) để đính kèm vào ticket. Đây là bước nền tảng — nếu agent không tái hiện được bug, mọi bước sau đều vô nghĩa.

Các Hành Động Agent Cần Thực Hiện

Với Puppeteer MCP đã cài đặt (theo hướng dẫn ở bài 2-5 của module), agent sẽ thực hiện tuần tự các tool call sau:

  1. puppeteer_navigate tới URL production (ví dụ https://shop.example.com/login).
  2. Điền form đăng nhập bằng tài khoản test đã cung cấp, submit.
  3. puppeteer_navigate hoặc click vào một sản phẩm, thêm vào giỏ hàng.
  4. puppeteer_navigate tới /cart.
  5. Điền mã coupon vào input field (dùng selector CSS hoặc tìm bằng text label).
  6. Click vào nút "Apply Coupon".
  7. Đợi một khoảng thời gian ngắn (để loại trừ khả năng chỉ là network chậm), rồi puppeteer_screenshot để chụp lại trạng thái UI.
  8. So sánh trạng thái trước/sau khi click — có thay đổi gì không (giá, thông báo, loading spinner)?

Prompt Mẫu Để Yêu Cầu Agent Tái Hiện Bug

Bạn có quyền truy cập Puppeteer MCP. Nhiệm vụ: tái hiện bug sau trên
môi trường production.

Bug: Ticket #4821 - Nút "Apply Coupon" không phản ứng khi bấm trên
trang /cart, chỉ xảy ra ở production build.

URL production: https://shop.example.com
Tài khoản test: qa.tester@example.com / [password đã cung cấp riêng]

Các bước cần thực hiện:
1. Navigate tới trang login, đăng nhập bằng tài khoản test.
2. Thêm bất kỳ 1 sản phẩm nào vào giỏ hàng (chọn sản phẩm đầu tiên
   trong danh sách nếu không có chỉ định cụ thể).
3. Navigate tới /cart.
4. Chụp screenshot trạng thái ban đầu của trang cart (đặt tên
   "01-cart-initial.png").
5. Nhập mã coupon "TESTCODE10" vào ô input coupon.
6. Click nút "Apply Coupon".
7. Đợi 3 giây, sau đó chụp screenshot trạng thái sau khi click
   (đặt tên "02-cart-after-click.png").
8. So sánh 2 screenshot, mô tả rõ có sự khác biệt nào không (giá,
   thông báo lỗi/thành công, loading indicator, thay đổi DOM).
9. Báo cáo: bug có tái hiện được không? Nếu có, mô tả chính xác
   hành vi quan sát được (không suy đoán nguyên nhân ở bước này).

Điều Cần Lưu Ý Khi Đọc Kết Quả

Khi agent báo cáo lại, hãy để ý các tín hiệu:

  • Nếu hai screenshot giống hệt nhau — xác nhận bug tồn tại, không có bất kỳ phản hồi UI nào.
  • Nếu agent gặp lỗi ngay ở bước tìm selector của nút "Apply Coupon" (ví dụ không tìm thấy element) — có thể chính selector đã đổi, hoặc đây là một manh mối khác (element bị ẩn/disabled).
  • Luôn yêu cầu agent lưu lại URL chính xácthời điểm thực hiện, để dev có thể đối chiếu với log server nếu cần.

Mẹo: Luôn yêu cầu agent tái hiện bug cả trên dev build và production build trong cùng một session, rồi so sánh. Việc này biến một câu hỏi mơ hồ ("tại sao chỉ lỗi ở production?") thành một dữ liệu có thể đối chiếu ngay — tiết kiệm rất nhiều thời gian ở bước chẩn đoán tiếp theo.

Bước 2: Chẩn Đoán Root Cause — Agent Kiểm Tra DOM, Console Errors, Và Network Requests

Sau khi đã xác nhận bug tồn tại, bước tiếp theo là tìm ra vì sao nó xảy ra. Đây là bước tốn nhiều effort thủ công nhất theo cách làm truyền thống — mở DevTools, click qua từng tab (Elements, Console, Network), đọc stack trace, và nối các mảnh thông tin lại với nhau. Puppeteer MCP cho phép agent làm chính xác việc này, nhưng nhanh hơn nhiều vì nó có thể đọc đồng thời cả ba nguồn dữ liệu và tổng hợp lại.

Ba Nguồn Dữ Liệu Chẩn Đoán

  • DOM inspection: kiểm tra element của nút có tồn tại đúng không, có đúng class name không, có bị gắn thuộc tính disabled không, event listener có được đăng ký hay không (thường suy luận gián tiếp qua việc element có phản ứng khi dispatch một sự kiện thử nghiệm hay không).
  • Console errors: đọc toàn bộ log console sau khi thực hiện hành động — đây thường là nơi lộ ra JavaScript exception (ngoại lệ) rõ ràng nhất, ví dụ TypeError: Cannot read properties of undefined.
  • Network requests: kiểm tra xem một API call có được gửi đi hay không, và nếu có, response status code là gì (200, 404, 500, hay bị timeout).

Prompt Mẫu Để Yêu Cầu Agent Chẩn Đoán

Tiếp tục từ bug đã tái hiện ở bước trước (nút Apply Coupon không phản
ứng trên production). Nhiệm vụ bây giờ là chẩn đoán root cause.

Hãy thực hiện lại đúng các bước tái hiện bug (login, add to cart,
vào /cart, nhập coupon, click Apply Coupon), nhưng lần này:

1. Bật ghi lại console log TRƯỚC khi click nút Apply Coupon, để không
   bỏ lỡ log nào xảy ra ngay lúc click.
2. Sau khi click, lấy toàn bộ console log (bao gồm error, warning),
   trích dẫn nguyên văn message và stack trace nếu có.
3. Lấy danh sách toàn bộ network request được gửi trong vòng 5 giây
   sau khi click, gồm: request URL, method, status code, response
   body (nếu có thể). Đặc biệt chú ý các request liên quan đến
   "coupon" hoặc "cart".
4. Inspect DOM của nút "Apply Coupon": lấy outerHTML, kiểm tra có
   thuộc tính "disabled" hay class nào biểu thị trạng thái bất
   thường (ví dụ class "is-loading" bị stuck).
5. So sánh với kết quả tương tự trên dev build (nếu có thể truy cập)
   để xác định điểm khác biệt.
6. Tổng hợp và đưa ra giả thuyết root cause có căn cứ nhất, dựa trên
   bằng chứng ở bước 1-4, không đoán mò.

Ví Dụ Báo Cáo Agent Có Thể Trả Về

KẾT QUẢ CHẨN ĐOÁN - Ticket #4821

Console error phát hiện được (production build):
  TypeError: Cannot read properties of undefined (reading 'items')
    at handleApplyCoupon (main.a1b2c3.js:1:48291)

Network request: KHÔNG có request nào được gửi tới
/api/cart/apply-coupon sau khi click (đã kiểm tra 5s sau event).
=> Lỗi xảy ra TRƯỚC khi kịp gọi API, tại thời điểm xử lý client-side.

DOM inspection: nút "Apply Coupon" không có thuộc tính disabled,
class name và onClick handler tồn tại bình thường trong bundle.

So sánh với dev build: KHÔNG tái hiện được lỗi này ở dev build, biến
`cart.items` vẫn có giá trị đúng ở dev.

Giả thuyết root cause: hàm handleApplyCoupon() đang truy cập
`cart.items.length` mà không optional-chaining hay kiểm tra tồn tại
trước. Ở dev build, biến `cart` được khởi tạo qua một đường import
đầy đủ. Ở production build, có khả năng một bước tree-shaking/
minification đã loại bỏ một đoạn code khởi tạo default state của
cart (nghi ngờ do side-effect bị đánh dấu sai trong package.json
hoặc do một import bị "shake" nhầm), khiến `cart` là undefined tại
thời điểm handler chạy trong production.

=> Đề xuất dev kiểm tra: (1) cấu hình sideEffects trong package.json
của module cart-store, (2) thêm optional chaining tạm thời như một
bản vá an toàn, (3) build production ở local với source map để xác
nhận chính xác dòng code bị ảnh hưởng.

Đây là một ví dụ minh hoạ — bug thật có thể phức tạp hơn hoặc đơn giản hơn, nhưng cấu trúc báo cáo (evidence trước, giả thuyết sau) là mẫu bạn nên yêu cầu agent tuân theo mọi lúc.

Ánh Xạ Sang Các Nhóm Nguyên Nhân Gốc Rễ (Root Cause Categories)

Khi đọc báo cáo của agent, hãy phân loại nguyên nhân vào một trong các nhóm quen thuộc — việc này giúp bạn (và cả agent, nếu bạn hỏi tiếp) định hướng hướng sửa nhanh hơn:

Nhóm nguyên nhân Dấu hiệu nhận biết Ví dụ
JS error (lỗi logic JavaScript) Console có exception rõ ràng, stack trace trỏ vào file cụ thể TypeError, undefined is not a function
CSS/layout issue UI hiển thị sai vị trí, element bị che khuất, nhưng không có console error Nút bị một overlay vô hình che mất, click "trúng" element khác
API/network issue Request được gửi nhưng response lỗi (4xx/5xx) hoặc không có request nào Response 500 từ backend, hoặc request bị chặn bởi CORS
Race condition (điều kiện tranh chấp) Bug chỉ xảy ra không nhất quán, phụ thuộc thứ tự load State chưa kịp khởi tạo xong đã bị truy cập
Build/bundling issue Chỉ xảy ra ở production, không ở dev; liên quan tree-shaking, minification, env variable Đúng như case #4821 ở trên

Mẹo: Luôn yêu cầu agent trích dẫn nguyên văn console error và network response, đừng để nó tự diễn giải lại bằng lời. Một exception message bị paraphrase (diễn đạt lại) có thể làm mất đi chi tiết quan trọng như tên biến hay số dòng — thứ mà developer cần để định vị chính xác đoạn code lỗi.

Bước 3: Verify Fix Và Chạy UI Regression Check Với Puppeteer MCP

Sau khi developer đã áp dụng fix (trong ví dụ này, giả sử họ đã thêm optional chaining và sửa cấu hình sideEffects, rồi build lại production), vai trò của agent chuyển từ "điều tra viên" sang "người kiểm chứng". Có hai việc cần làm: verify đúng bug đã được sửa, và chạy regression để đảm bảo fix không làm hỏng những luồng liên quan khác.

Verify Lại Đúng Kịch Bản Bug Gốc

Bước đầu tiên đơn giản: lặp lại chính xác các bước đã dùng để tái hiện bug ở Bước 1, trên bản build mới, và xác nhận hành vi đã đúng như mong đợi.

Fix đã được deploy lên môi trường staging (URL:
https://staging.shop.example.com). Hãy verify lại bug #4821 đã được
sửa chưa, bằng cách lặp lại đúng các bước tái hiện đã dùng trước đó:

1. Login, add to cart, vào /cart.
2. Nhập coupon "TESTCODE10", click Apply Coupon.
3. Chụp screenshot kết quả, kiểm tra console log có còn xuất hiện
   TypeError như trước không.
4. Kiểm tra network request tới /api/cart/apply-coupon có được gửi
   đi không, response status code là gì.
5. Kết luận: PASS (bug đã sửa) hay FAIL (vẫn còn lỗi), kèm bằng
   chứng cụ thể.

Mở Rộng Sang Regression Check Cho Các Luồng Liên Quan

Chỉ verify đúng 1 kịch bản là chưa đủ — fix có thể vô tình phá vỡ một luồng khác dùng chung logic (ví dụ handleApplyCoupon cũng được gọi từ trang order summary). Đây là lúc biến quy trình thành một regression checklist có thể tái sử dụng.

# Kịch bản test Bước thực hiện Kết quả mong đợi
1 Áp mã coupon hợp lệ Nhập mã đúng, click Apply Giá được giảm, hiện thông báo thành công
2 Áp mã coupon không hợp lệ Nhập mã sai, click Apply Hiện thông báo lỗi rõ ràng, không crash
3 Checkout không dùng coupon Bỏ qua bước nhập coupon, thanh toán thẳng Giá giữ nguyên, checkout thành công
4 Giỏ hàng nhiều sản phẩm + coupon Thêm 2-3 sản phẩm, áp coupon Giảm giá áp dụng đúng trên tổng đơn
5 Xóa coupon sau khi đã áp Áp coupon, sau đó bấm "Remove" Giá trở lại đúng như trước khi áp mã

Prompt để agent chạy toàn bộ checklist này tự động:

Chạy bộ regression check sau trên môi trường staging sau khi fix
bug #4821. Với mỗi kịch bản, thực hiện các bước, chụp screenshot kết
quả, và báo cáo PASS/FAIL kèm lý do:

1. Áp mã coupon hợp lệ "TESTCODE10" trên giỏ có 1 sản phẩm - kỳ vọng
   giá giảm và hiện thông báo thành công.
2. Áp mã coupon không hợp lệ "INVALIDXYZ" - kỳ vọng thông báo lỗi rõ
   ràng, không có exception trong console.
3. Checkout không dùng coupon (giỏ 1 sản phẩm) - kỳ vọng thanh toán
   thành công, giá không đổi.
4. Thêm 2 sản phẩm vào giỏ, áp mã "TESTCODE10" - kỳ vọng giảm giá áp
   dụng đúng trên tổng đơn hàng.
5. Áp coupon, sau đó bấm nút xóa/remove coupon - kỳ vọng giá trở về
   giá trị ban đầu.

Sau khi chạy hết, tổng hợp bảng kết quả: STT | Kịch bản | PASS/FAIL |
Ghi chú (kèm số bug/observation nếu FAIL).

Biến Đây Thành Smoke Test Bán Tự Động Cho QA Tái Sử Dụng

Điểm mạnh nhất của cách làm này không nằm ở việc verify một bug đơn lẻ, mà ở việc bảng regression checklist bên trên có thể lưu lại thành một file test scenario chuẩn, để bất kỳ lần nào có thay đổi liên quan tới module cart/coupon trong tương lai, QA chỉ cần chạy lại đúng prompt đó (đổi URL môi trường nếu cần) thay vì test tay lại từ đầu. Theo thời gian, mỗi module quan trọng trong sản phẩm nên có một "bộ smoke test" như vậy, được review và cập nhật mỗi khi có bug mới liên quan được phát hiện — biến mỗi bug đã fix thành một lớp bảo vệ regression cho tương lai.

Mẹo: Lưu prompt regression checklist của từng module (cart, checkout, login, v.v.) thành các file riêng trong repo (ví dụ qa-prompts/cart-regression.md), để cả team dùng chung và không phải "phát minh lại" prompt mỗi lần cần test. Coi nó như test script, cần version control (quản lý phiên bản) giống hệt code.

Kết Luận

Workflow xuyên suốt bốn bước — tái hiện, chẩn đoán, fix, verify + regression — không phải là quy trình mới. Đó chính là quy trình debug mà mọi frontend engineer và QA Engineer đã làm hàng chục năm nay. Điều Puppeteer MCP thay đổi là tốc độ và tính nhất quán của các bước thao tác tay: agent không mệt, không bỏ sót bước, và có thể chạy lại y hệt cùng một kịch bản bao nhiêu lần cũng được, trong khi con người vẫn giữ vai trò không thể thay thế — đọc hiểu bối cảnh nghiệp vụ, phán đoán nguyên nhân gốc rễ ở tầng kiến trúc, và quyết định khi nào một fix đã đủ an toàn để release. Nắm vững workflow này, bạn đã có trong tay một công cụ thực chiến, sẵn sàng áp dụng ngay cho bug report tiếp theo trên bàn làm việc của mình.