Product Management
Đăng nhập
ESC

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

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

Bài 3 — Dạy agent tái hiện (reproduce) bug

Đã đọc 0/10 mục · còn khoảng 4 phút
Cách chúng tôi ghi nhận

Một mục được tính là đã đọc khi nó nằm giữa màn hình đủ lâu so với độ dài của nó (bảng và sơ đồ tính một nửa), bạn vẫn đang cuộn hoặc bấm phím, và bạn đã thấy tới cuối mục. Lướt nhanh hoặc để tab mở không được tính. Chúng tôi chỉ lưu thời gian đọc từng mục — không lưu gì khác.

Một bug chưa tái hiện được thì gần như không sửa được. Bước reproduce biến mô tả mơ hồ thành một chuỗi thao tác lặp lại được cho ra lỗi. Agent giúp việc này bằng cách chuẩn hóa repro steps, dựng môi trường tối thiểu (MCVE) và tự chạy thử khi có sandbox.

Khung tư duy: MCVE

Minimal, Complete, Verifiable Example — ví dụ nhỏ nhất, đầy đủ, kiểm chứng được. Mục tiêu của agent là rút gọn report thành MCVE:

  • Minimal: bỏ mọi bước không liên quan tới lỗi.
  • Complete: có đủ để chạy (data mẫu, config, version).
  • Verifiable: chạy là thấy lỗi, chạy lại vẫn thấy.

Ví dụ cụ thể

Report: "Tính năng xuất báo cáo lỗi". Agent chuẩn hóa thành:

repro:
  env: { app: "web", version: "2.4.1", browser: "Chrome 120" }
  precondition: "Đăng nhập tài khoản có > 10.000 dòng dữ liệu"
  steps:
    - "Vào Reports > Export"
    - "Chọn khoảng 12 tháng"
    - "Bấm Export CSV"
  expected: "Tải file CSV đầy đủ"
  actual: "Trang trắng, console báo 504 Gateway Timeout"
  reproducibility: "3/3 lần"

Trường reproducibility (bao nhiêu lần trên tổng số lần thử) cực kỳ giá trị: lỗi 3/3 khác hẳn lỗi 1/10 (flaky).

Các bước dạy agent reproduce

  • Trích các trường repro bắt buộc từ report; trường nào thiếu → đưa vào missing và hỏi lại.
  • Chuẩn hóa steps thành danh sách hành động nguyên tử (một thao tác/dòng), tránh gộp.
  • Suy ra precondition/env cần thiết (dữ liệu, quyền, cấu hình).
  • Nếu có sandbox, cho agent tự chạy script tái hiện và ghi reproducibility.
  • Phân loại kết quả: reproduced, not_reproduced, flaky, needs_info.
def classify_repro(runs: list[bool]) -> str:
    hits = sum(runs)
    if hits == 0: return "not_reproduced"
    if hits == len(runs): return "reproduced"
    return "flaky"   # đôi khi lỗi -> nghi ngờ race/thời gian/thứ tự

Xử lý bug flaky

Bug flaky (lúc lỗi lúc không) thường do: điều kiện đua (race condition), phụ thuộc thứ tự test, dữ liệu/thời gian, hoặc mạng. Agent nên chạy lại N lần (ví dụ 10), ghi tỉ lệ, và không kết luận "đã sửa" chỉ vì 1 lần chạy qua.

Checklist reproduce

[ ] Đã cố định version + môi trường
[ ] Steps là hành động nguyên tử, có thứ tự
[ ] Có precondition rõ (data, quyền, config)
[ ] Ghi expected vs actual tách bạch
[ ] Chạy >= 3 lần, ghi tỉ lệ tái hiện
[ ] Lỗi flaky -> gắn nhãn, không đóng vội

Sai lầm thường gặp

  • Kết luận "không tái hiện được" sau 1 lần thử → bỏ sót bug flaky.
  • Không cố định version/env → tái hiện trên nhánh khác, kết quả vô nghĩa.
  • Gộp nhiều thao tác vào một bước → không cô lập được bước gây lỗi.
  • Bỏ qua precondition (dữ liệu lớn, quyền admin) → người khác chạy lại không ra lỗi.
  • Coi 1 lần pass là "đã fix" với bug flaky → lỗi quay lại sản xuất.
Đã có MCVE và tỉ lệ tái hiện, Bài 4 sẽ dùng chúng để truy nguyên nhân gốc.

<!--les-append-->

Bug không tái hiện được: bốn nguyên nhân, bốn cách xử lý

"Not reproduced" không phải một kết luận — nó là một câu hỏi chưa trả lời. Bốn nguyên nhân thật, và chúng cần cách xử lý khác nhau:

Nguyên nhânDấu hiệuCách xử lý
Thiếu preconditionNgười báo có dữ liệu/quyền mà bạn không cóHỏi lại cụ thể: bao nhiêu dòng, quyền gì, tài khoản nào
Khác môi trườngChạy trên máy dev thì không lỗiSo version, biến môi trường, dữ liệu; đừng so bằng mắt
Flaky thật1/10 lầnChạy 20 lần, đừng 3 lần; ghi tỉ lệ
Bug đã được sửa tình cờMột commit khác đã váTìm commit, xác nhận, và thêm test kẻo nó quay lại
Ô cuối là ô hay bị bỏ và nó tạo ra bug lặp lại: lỗi biến mất nên ai đó đóng ticket, không ai viết test, và sáu tháng sau nó trở lại trong một hình thức khác.

Ghi rõ điều kiện tái hiện thay vì "không tái hiện được"

Khi agent kết luận không tái hiện, bắt nó xuất ra những gì đã thử, không chỉ kết luận:

  • Đã thử bao nhiêu lần, trên version nào.
  • Precondition nào đã dựng, precondition nào không dựng được và vì sao.
  • Sự khác biệt đã biết giữa môi trường thử và môi trường người báo.
Ba dòng này biến một ticket chết thành một ticket người tiếp theo làm tiếp được. Không có chúng, người sau sẽ làm lại từ đầu toàn bộ.

Vì sao tỉ lệ tái hiện là con số quan trọng nhất trong report

Nó quyết định loại lỗi, và do đó quyết định cách sửa:

  • 3/3 → lỗi tất định trong một đường code. Đọc code là đủ.
  • 4/10 → gần như luôn là điều kiện đua, phụ thuộc thời gian, hoặc trạng thái còn sót giữa các lần chạy. Đọc code sẽ không tìm ra.
  • 1/50 → thường là phụ thuộc bên ngoài (mạng, dịch vụ khác) hoặc dữ liệu rất hiếm.
Kết luận thực dụng: nếu tỉ lệ dưới 100%, đừng để agent đi tìm "dòng code sai" — hãy để nó tìm trạng thái dùng chung giữa các lần chạy. Đó là nơi lỗi flaky sống. <!--/les-append-->

Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi