Vòng đời của một bug và cách viết báo cáo để người khác sửa được ngay
Xem thửHãy quay lại lỗi mã CHUTU10 của Cà Phê Chú Tư: đơn 200.000 đồng bị giảm 20.000 thay vì tối đa 15.000. Giả sử hai tester khác nhau cùng thấy lỗi này và gửi hai báo cáo cho An, lập trình viên phụ trách.
Báo cáo thứ nhất chỉ có tiêu đề "Giảm giá bị sai" và một dòng: "Mã giảm giá hôm nay bị lỗi, dev xem lại giúp. Chắc do tính phần trăm sai." Báo cáo thứ hai ghi đủ môi trường, các bước, kết quả thực tế và kết quả mong đợi. Với báo cáo thứ hai, An xử lý xong trong khoảng 70 phút. Với báo cáo thứ nhất, từ lúc nhận đến lúc có bản sửa mất khoảng 300 phút, trong đó 180 phút là chờ người báo trả lời câu hỏi (số liệu minh họa).
Trước khi đọc tiếp, hãy nhắm mắt đóng vai An: chỉ với tiêu đề "Giảm giá bị sai", bạn phải hỏi lại người báo những gì? Hãy viết ra ít nhất bốn câu hỏi.
Sau bài này, bạn có thể
- Kể được vòng đời của một bug và nói ai phụ trách ở từng trạng thái.
- Phân biệt bốn nhánh rẽ khỏi đường chính: Rejected, Not a bug, Duplicate, Deferred, và nhánh quay lại Reopened.
- Viết một báo cáo bug đủ các phần chính để người khác tái hiện được mà không phải hỏi lại.
- Mô tả cái mình quan sát được thay vì đoán nguyên nhân hay đổ lỗi cho người.
Cần biết trước: sai sót, lỗi và sự cố ở bài đầu chương, và bước thực thi test ở bài quy trình kiểm thử (đó là nơi bug được sinh ra từ test thất bại).
Bằng chứng: hai báo cáo cho cùng một lỗi
Đây là báo cáo thứ nhất, và báo cáo thứ hai đặt ngay bên dưới (dữ liệu và tên sản phẩm trong báo cáo là ví dụ):
Tiêu đề: Giảm giá bị sai
Mô tả: Mã giảm giá hôm nay bị lỗi, dev xem lại giúp. Chắc do tính phần trăm sai.
Tiêu đề: [Thanh toán] Mã CHUTU10 giảm 20.000 thay vì tối đa 15.000 với đơn 200.000
Môi trường: Android 14, app Cafe Chu Tu 2.3.0 (build 231), môi trường staging, tài khoản test binh.test01
Điều kiện ban đầu: giỏ hàng trống, tài khoản chưa dùng mã CHUTU10
Các bước tái hiện:
1. Thêm 4 ly Tra dao (50.000 mỗi ly) vào giỏ, tạm tính 200.000.
2. Mở giỏ hàng, nhập mã CHUTU10, bấm Áp dụng.
3. Xem dòng Giảm giá và dòng Tổng thanh toán.
Kết quả thực tế: Giảm giá 20.000, Tổng thanh toán 180.000.
Kết quả mong đợi: Giảm giá 15.000 (tối đa theo quy định), Tổng thanh toán 185.000.
Tần suất: 3 trên 3 lần thử.
Thông tin đối chiếu: đơn 150.000 giảm 15.000 (đúng), đơn 100.000 giảm 10.000 (đúng).
Mức nghiêm trọng đề xuất: Cao (sai số tiền khách phải trả).
Ưu tiên đề xuất: Cao (khuyến mãi đang chạy).
Bằng chứng: ảnh chụp giỏ hàng, video 12 giây, mã đơn thử STG-0412.
Thời gian xử lý ước tính của hai báo cáo (phút, số liệu minh họa của bài):
| Giai đoạn | Báo cáo "Giảm giá bị sai" | Báo cáo đủ thông tin |
|---|---|---|
| Đọc và hiểu | 20 | 5 |
| Chờ người báo trả lời câu hỏi | 180 | 0 |
| Tái hiện lỗi | 40 | 5 |
| Tìm nguyên nhân | 25 | 25 |
| Sửa và tự kiểm tra | 35 | 35 |
| Tổng | 300 | 70 |
Hai giai đoạn cuối giống nhau, vì việc tìm nguyên nhân và sửa là việc của lập trình viên và không phụ thuộc cách viết báo cáo. Toàn bộ 230 phút chênh lệch nằm ở ba giai đoạn đầu, tức ở chất lượng thông tin mà tester cung cấp. Bài này trả lời hai câu hỏi: bug đi qua những trạng thái nào, và một báo cáo tốt gồm những gì.
Mô hình tư duy 1: bug có vòng đời, mỗi trạng thái có một người giữ
Một bug không phải một tin nhắn gửi đi là xong. Nó là một mục việc được theo dõi trong công cụ quản lý lỗi, và nó chuyển qua nhiều trạng thái (status). ISTQB nêu rằng quy trình xử lý lỗi tối thiểu phải có luồng đi từ lúc phát hiện đến lúc đóng và quy tắc phân loại, và nêu ví dụ về trạng thái như open, deferred, duplicate, waiting to be fixed, awaiting confirmation testing, re-opened, closed, rejected. Tên cụ thể tùy công cụ và công ty; bài này dùng bộ tên thông dụng.
| Trạng thái | Ý nghĩa | Ai giữ | Việc cần làm | Chuyển sang |
|---|---|---|---|---|
| New | Tester vừa báo, chưa ai xem | Tester, rồi người phân loại | Xem báo cáo, kiểm tra hợp lệ và trùng lặp | Assigned, hoặc một nhánh rẽ |
| Assigned | Đã giao cho một lập trình viên | Lập trình viên | Nhận việc | Open |
| Open | Lập trình viên đang xử lý | Lập trình viên | Tái hiện, tìm nguyên nhân, sửa | Fixed |
| Fixed | Đã sửa và đưa lên bản build để thử | Tester | Chờ bản build có bản sửa | Retest |
| Retest | Tester đang kiểm tra lại | Tester | Chạy lại đúng kịch bản và các test liên quan | Verified hoặc Reopened |
| Verified | Bản sửa đã được xác nhận | Tester | Kiểm tra lần cuối rồi đóng | Closed |
| Closed | Hoàn tất | Không ai | Giữ lại để tra cứu | Kết thúc |
| Reopened | Bản sửa không đạt hoặc lỗi tái phát | Lập trình viên | Xử lý lại kèm ghi chú của tester | Open |
Nhiều công ty gộp Verified và Closed thành một. Người "giữ" bug là người đang phải hành động; chuyển trạng thái cũng là chuyển trách nhiệm. Ở nhóm nhỏ như Cà Phê Chú Tư, Bình có thể tự phân loại và chị Lan (trưởng nhóm) giao việc; ở nhóm lớn có một người phân loại riêng (triage).
Đang tải sơ đồ…
Cách đọc hình: đường chính chạy dọc từ New đến Closed. Khung rẽ nhánh duy nhất là Retest: đạt thì sang Verified, không đạt thì sang Reopened rồi quay lại Open, nên bug có thể đi vòng nhiều lần. Khối SideExits gom bốn lối thoát khác ngay từ lúc phân loại (Rejected, Not a bug, Duplicate, Deferred); phần dưới giải thích khi nào bug rẽ vào đó.
Bốn lối thoát ngoài đường chính cùng có chung một đặc điểm: bug không được sửa trong bản này, và người đổi trạng thái phải ghi lý do.
| Nhánh | Khi nào dùng | Ví dụ ở Cà Phê Chú Tư | Việc tiếp theo |
|---|---|---|---|
| Rejected | Báo cáo bị từ chối: thiếu thông tin hoặc không tái hiện được dù đã làm đúng các bước | Báo "app chậm" không kèm thiết bị và thời điểm | Người báo bổ sung thông tin, nếu có thì mở lại |
| Not a bug | Phần mềm đang chạy đúng theo yêu cầu đã duyệt | Báo "không dùng được mã khi đơn 40.000", trong khi yêu cầu nói đơn từ 50.000 | Nếu người dùng thấy yêu cầu chưa hợp lý thì tạo đề nghị thay đổi yêu cầu |
| Duplicate | Đã có bug khác mô tả cùng sự cố | Hai tester báo cùng lỗi mã giảm giá | Gắn liên kết tới bug gốc, bổ sung thông tin mới vào bug gốc |
| Deferred | Công nhận là lỗi nhưng hoãn sang bản sau | Lỗi màu chữ lệch ở màn hình giới thiệu trước ngày ra mắt | Ghi lý do, bản sau đưa lại vào danh sách |
Một bug có đi vào nhánh nào hay không do một chuỗi câu hỏi quyết định, và người phân loại cần trả lời lần lượt, từ trên xuống:
Đang tải sơ đồ…
Cách đọc hình: bốn khối cam là bốn câu hỏi phân loại, hỏi theo thứ tự từ trên xuống; mỗi câu trả lời "Yes" hoặc "No" dẫn tới một lối thoát (khối tím) hoặc câu hỏi tiếp theo. Chỉ khi vượt qua cả bốn câu, bug mới đến khối xanh lá và được giao cho lập trình viên. Hai hình bổ sung cho nhau: hình trước cho thấy bug đi qua các trạng thái nào, hình này cho thấy vì sao một bug rẽ vào từng lối thoát.
Mô phỏng dưới đây đi cùng bug mã giảm giá qua vòng đời, kèm số giờ và người đang giữ. Thử nút đổi biến thể để xem điều gì xảy ra khi bản sửa chưa đạt.
Đang tải Animation…
Mô hình tư duy 2: một báo cáo tốt trả lời trước mọi câu hỏi của người sửa
Quay lại câu hỏi đầu bài. Với tiêu đề "Giảm giá bị sai", An phải hỏi: mã nào, đơn bao nhiêu, màn hình nào, sai thế nào, đúng phải thế nào, trên bản app nào, môi trường nào, có lần nào cũng sai không. Mỗi câu hỏi là một vòng chờ. Báo cáo tốt trả lời trước mọi câu hỏi đó. Theo ISTQB, báo cáo lỗi có ba mục đích: cho người xử lý đủ thông tin để giải quyết, giúp theo dõi chất lượng sản phẩm, và gợi ý cải tiến cho quy trình phát triển và kiểm thử.
| Phần | Trả lời câu hỏi | Trong ví dụ |
|---|---|---|
| Tiêu đề | Lỗi gì, ở đâu, trong điều kiện nào? | [Thanh toán] Mã CHUTU10 giảm 20.000 thay vì tối đa 15.000 với đơn 200.000 |
| Môi trường | Chạy trên thiết bị, bản và dữ liệu nào? | Android 14, app 2.3.0 (build 231), staging |
| Điều kiện ban đầu | Cần chuẩn bị trạng thái gì trước khi làm? | Giỏ trống, chưa dùng mã |
| Các bước tái hiện | Làm thế nào để thấy lại lỗi? | Ba bước đánh số, mỗi bước một hành động |
| Kết quả thực tế | Đã thấy gì? | Giảm 20.000, tổng 180.000 |
| Kết quả mong đợi | Lẽ ra phải thấy gì, theo yêu cầu nào? | Giảm 15.000, tổng 185.000 |
| Tần suất | Có lặp lại không? | 3 trên 3 lần |
| Nghiêm trọng và ưu tiên đề xuất | Ảnh hưởng nặng đến đâu, nên sửa gấp thế nào? | Cao và Cao |
| Bằng chứng | Có gì để kiểm chứng? | Ảnh, video 12 giây, mã đơn thử |
Hai phần cuối cần lưu ý. Mức nghiêm trọng (severity) là mức ảnh hưởng của lỗi lên hệ thống và người dùng. Mức ưu tiên (priority) là mức gấp phải sửa. Tester đề xuất cả hai nhưng quyết định cuối cùng thuộc về nhóm hoặc người sở hữu sản phẩm, vì ưu tiên còn phụ thuộc kế hoạch và nguồn lực. Hai khái niệm này được dạy riêng ở chương sau; ở đây chỉ cần nhớ chúng là hai thứ khác nhau. Các thông tin như mã bug, ngày và người báo thường được công cụ quản lý lỗi tự điền.
Hai nguyên tắc nhỏ giúp báo cáo gọn: một bug một báo cáo (hai lỗi gộp một báo cáo thì khó theo dõi và khó đóng), và tiêu đề đọc riêng vẫn hiểu (người xem danh sách chỉ thấy tiêu đề).
Mô phỏng sau cho thấy thời gian trôi ở từng giai đoạn với hai báo cáo.
Đang tải Animation…
Mô hình tư duy 3: mô tả điều quan sát được, không đoán nguyên nhân, không đổ lỗi
Báo cáo thứ nhất có câu "Chắc do tính phần trăm sai". Câu này gây hại vì ba lý do:
- Tester chỉ thấy sự cố. Như bài đầu đã nói, tester thấy kết quả sai trên màn hình; lỗi trong code là việc của gỡ lỗi. Nguyên nhân thật ở ví dụ này là thiếu giới hạn 15.000 chứ không phải tính phần trăm sai. Một lời đoán sai có thể đưa An đi kiểm tra nhầm chỗ.
- Đoán nguyên nhân làm lệch hướng và làm mất thời gian. Lập trình viên dễ tin gợi ý, nhất là khi đang gấp.
- Đổ lỗi phá bầu không khí. Báo cáo nói về sản phẩm, không nói về người. Câu "An code ẩu" khiến người nhận phòng thủ và lần sau tester sẽ bị xa lánh, hoặc bị giấu lỗi.
Cách thay thế là nêu dữ kiện có thể kiểm chứng:
| Cách viết kém | Cách viết tốt |
|---|---|
| An code ẩu nên giảm sai | Đơn 200.000 áp mã CHUTU10 hiển thị giảm 20.000, quy định tối đa 15.000 |
| Chắc do tính phần trăm sai | Đơn 150.000 giảm đúng 15.000, đơn 200.000 giảm 20.000; chưa thử các mức khác |
| Mã giảm giá lỗi nặng lắm | Khách trả 180.000 thay vì 185.000, chênh 5.000 mỗi đơn lớn dùng mã |
| Lỗi này lần trước cũng bị | Lỗi tương tự BUG-087 ở bản 2.1; đính kèm liên kết để so sánh |
Lưu ý dòng thứ hai: nêu thêm thông tin đối chiếu (đơn 150.000 vẫn đúng) hữu ích vì đó là dữ kiện đã quan sát, nó thu hẹp phạm vi giúp lập trình viên mà không kết luận hộ. Nếu bạn có một giả thuyết, hãy ghi riêng, đánh dấu là chưa xác nhận, và chỉ khi nó có dữ kiện đi kèm.
Hiểu lầm thường gặp
- "Tester giỏi là tester báo nhiều bug nhất." Sai ở chỗ số lượng không đo chất lượng. Báo cáo trùng, mơ hồ hoặc nhỏ nhặt làm tốn thời gian của cả nhóm. Điều đáng đo là bug có giá trị, báo rõ và sửa được.
- "Bug đã Closed là không bao giờ quay lại." Sai ở chỗ lỗi có thể tái phát ở bản sau, và bản sửa có thể làm hỏng chỗ khác. Đó là lý do cần kiểm thử hồi quy và có trạng thái Reopened.
- "Lập trình viên đổi sang Not a bug nghĩa là tester sai." Sai ở chỗ đôi khi yêu cầu mơ hồ. Hãy trao đổi và làm rõ yêu cầu với người sở hữu sản phẩm; nếu hành vi đúng yêu cầu nhưng không hợp lý, tạo đề nghị thay đổi yêu cầu.
- "Có ảnh chụp màn hình là đủ." Sai ở chỗ ảnh chỉ cho thấy kết quả, không cho biết các bước, môi trường và kết quả mong đợi.
- "Deferred nghĩa là bỏ qua." Sai ở chỗ bug Deferred vẫn được ghi, có lý do và được xem lại ở bản sau.
Điều kiện và giới hạn
- Tên trạng thái và số bước khác nhau giữa các công cụ (Jira, Redmine, Azure DevOps, và công cụ riêng). Điều cần nắm là ý nghĩa: ai đang giữ bug và việc tiếp theo.
- Một số nhóm nhỏ không có người phân loại riêng và bỏ trạng thái Assigned. Vẫn cần ai đó quyết định trước khi giao việc.
- Ví dụ BUG-087, các con số thời gian xử lý, và mã đơn thử là minh họa của bài.
Tự kiểm tra (có đáp án)
Câu 1. Bình chạy lại kịch bản trên bản build 2.3.1 và vẫn thấy đơn 300.000 giảm 30.000. Bug chuyển sang trạng thái nào, ai giữ tiếp? Đáp án: Reopened, và lập trình viên (An) giữ tiếp để xử lý lại. Bình ghi kết quả, bản build đã thử và đơn nào còn lỗi vào bug để An không phải hỏi lại.
Câu 2. Hai tester báo cùng lỗi mã giảm giá vào hai thời điểm khác nhau. Nên xử lý thế nào? Đáp án: đánh dấu Duplicate cho báo cáo đến sau và gắn liên kết tới bug gốc, đồng thời bổ sung thông tin mới (nếu có) vào bug gốc. Không xóa báo cáo trùng vì nó có thể chứa dữ kiện hữu ích.
Câu 3. Viết lại câu "Chắc An quên tính tối đa nên giảm sai" thành một câu không đoán nguyên nhân, không đổ lỗi. Đáp án: "Đơn 200.000 áp mã CHUTU10 hiển thị giảm 20.000; yêu cầu quy định tối đa 15.000. Đơn 150.000 giảm đúng 15.000." Câu này chỉ nêu dữ kiện quan sát và đối chiếu.
Điều cần nhớ
- Bug đi qua các trạng thái New, Assigned, Open, Fixed, Retest, Verified, Closed; mỗi trạng thái có người giữ và việc cần làm.
- Bug có thể rẽ vào Rejected, Not a bug, Duplicate, Deferred, hoặc quay lại Reopened nếu bản sửa không đạt.
- Báo cáo tốt trả lời trước mọi câu hỏi của người sửa: tiêu đề, môi trường, các bước, thực tế, mong đợi, tần suất, mức đề xuất, bằng chứng.
- Mô tả điều quan sát được; không đoán nguyên nhân và không đổ lỗi cho người.
- Sang chương sau, bạn sẽ học cách thiết kế test case để tìm bug có hệ thống, rồi quay lại phân biệt kỹ mức nghiêm trọng và mức ưu tiên.
Nguồn tham khảo
- ISTQB Certified Tester Foundation Level Syllabus v4.0.1, mục 5.5 (quản lý lỗi, nội dung báo cáo lỗi và trạng thái ví dụ) và mục 1.1.2 (kiểm thử và gỡ lỗi): https://istqb.org/wp-content/uploads/2024/11/ISTQB_CTFL_Syllabus_v4.0.1.pdf
- Bộ thuật ngữ ISTQB (defect report, severity, priority): https://glossary.istqb.org/