Lesson 37 — Advanced Testing (Visualization)
Lesson này dạy 3 kỹ thuật khó "tưởng tượng" nhất: fuzz testing (máy sinh input tìm bug), race detector (phát hiện data race giữa 2 goroutine), và golden file (snapshot test). Trang này minh hoạ trực quan từng cái — bạn có thể "chạy thử" trong browser mà không cần cài Go.
Module 1 — Fuzz Finder: máy tự tìm bug
Mục tiêu: test hàm Reverse(s) với invariant
Reverse(Reverse(s)) == s. Phía dưới đây mô
phỏng fuzzer: bắt đầu từ seed corpus, mutation từng bước
để sinh input mới, chạy invariant. Nếu fail → lưu vào
testdata/fuzz/<hash>.
Fuzz log
Code dưới test
// CỐ Ý có bug: đảo theo BYTE
func ReverseBuggy(s string) string {
b := []byte(s)
for i,j := 0,len(b)-1; i<j; i,j=i+1,j-1 {
b[i], b[j] = b[j], b[i]
}
return string(b) // ✗ vỡ UTF-8 với rune >1 byte
}
// Invariant fuzz check:
// ReverseBuggy(ReverseBuggy(s)) == s
// utf8.ValidString(ReverseBuggy(s))
Module 2 — Race Detector: 2 goroutine 1 ô nhớ
2 goroutine cùng gọi counter.Inc() với
c.n++ (compile ra 3 lệnh: LOAD, ADD, STORE).
Nếu lịch CPU xen kẽ "xấu", 2 goroutine cùng đọc giá trị cũ → mỗi cái
+1 → STORE đè nhau → mất 1 update. go test -race
phát hiện điều này bằng cách track happens-before relation.
🔵 Goroutine A — Inc()
?
🟢 Shared memory
🟠 Goroutine B — Inc()
?
Fix bằng Mutex: c.mu.Lock(); c.n++; c.mu.Unlock()
— chỉ 1 goroutine giữ lock tại 1 thời điểm → 3 lệnh LOAD/ADD/STORE chạy
nguyên khối, không xen kẽ. Race detector sẽ không cảnh báo nữa.
Module 3 — Golden File Workflow
Render template HTML từ data → so byte-by-byte với file
testdata/golden/report.golden. Khi template
thay đổi, dùng cờ go test -update để
regenerate file golden, review diff bằng mắt rồi commit.