Lesson 26 — Testing trong Go (Visualization)
Lesson này dạy 3 trụ cột của test trong Go: table-driven test, coverage và benchmark. Trang này minh hoạ trực quan từng cái — bạn không cần cài Go cũng "chạy thử" được trong trình duyệt.
1. Table-driven test runner — Add(a, b)
Pattern []struct{name; in; want} + t.Run cho phép viết 6 case mà chỉ tốn 1 hàm TestAdd. Bấm Run All để xem các sub-test chạy tuần tự.
| name | a | b | want | got | status |
|---|
--- chưa chạy ---
Trong code thật:
go test -v -run TestAdd sẽ in từng --- PASS: TestAdd/name (0.00s) như cách viz đang animate. Nếu inject bug, output sẽ kèm dòng Add(...) = X; muốn Y — chính là t.Errorf trong test.
2. Coverage visualizer — Divide(a, b)
Coverage đo "test có chạy qua dòng code này không". Chọn test set để xem dòng nào được cover (xanh) / chưa cover (đỏ) và phần trăm coverage thay đổi real-time.
Set A chỉ gọi
Divide(10, 2) → bỏ qua nhánh if b == 0. Set B chỉ gọi Divide(1, 0) → bỏ qua nhánh return phép chia. Set C kết hợp → 100%. Đây là lý do bạn thường cần ≥ 2 case (happy + error) chứ không chỉ 1.
⚠ Coverage cao không có nghĩa code đúng. Test viết bậy (không có
t.Errorf) vẫn cho coverage 100%. Coverage chỉ đo "đã đi qua", không đo "đã verify".
3. Benchmark visualizer — + vs strings.Builder
Cùng task: concat n lần ký tự "a". Hai implementation, ba metric: ns/op (thời gian/lần), B/op (byte cấp phát), allocs/op (số lần alloc). Mock data nhưng tuân theo độ phức tạp lý thuyết.
| Implementation | ns/op | B/op | allocs/op |
|---|
Tại sao
+ chậm? Mỗi s += "a" tạo string mới (string immutable trong Go), copy toàn bộ nội dung cũ + 1 byte → O(n²) byte copy, O(n) alloc. strings.Builder dùng []byte mutable + Grow(n) pre-alloc → 1 alloc duy nhất, O(n) byte copy.
⚠ Số liệu trên là mock tuân theo độ phức tạp lý thuyết, không phải kết quả chạy thật trên máy bạn. Để đo thật:
go test -bench=. -benchmem.