Testing & Tooling
เรื่องราวของ testing ใน Go
หัวข้อที่มีชื่อว่า “เรื่องราวของ testing ใน Go”ภาษาส่วนใหญ่ต้องการ testing framework จาก third-party แต่ Go มีทุกอย่างที่จำเป็นอยู่ใน standard library แล้ว package testing มี *testing.T สำหรับ unit tests, *testing.B สำหรับ benchmarks, และ *testing.F สำหรับ fuzzing — ทั้งหมดขับเคลื่อนด้วยคำสั่งเดียว: go test
go toolchain ที่ติดตั้งมาพร้อมกับ Go ทุกเวอร์ชันยังรวมถึง:
| เครื่องมือ | วัตถุประสงค์ |
|---|---|
go test | รัน tests และ benchmarks |
go build | compile packages และ binary |
go run | compile และรันในขั้นตอนเดียว |
go fmt | จัดรูปแบบ source code (เรียกใช้ gofmt) |
go vet | static analysis สำหรับข้อผิดพลาดทั่วไป |
go mod | จัดการ module และ dependency |
go doc | เรียกดู package documentation |
สิ่งที่โมดูลนี้ครอบคลุม
หัวข้อที่มีชื่อว่า “สิ่งที่โมดูลนี้ครอบคลุม”- go-test — การเขียนไฟล์
_test.go,func TestXxx(t *testing.T), และ table-driven tests ด้วยt.Run - benchmarks — การวัด performance ด้วย
func BenchmarkXxx(b *testing.B)และการอ่านผลลัพธ์จาก-benchmem - modules — การจัดการ dependency ด้วย
go mod init,go.mod,go.sum, และgo get - go-tooling — คำสั่งประจำวัน:
go run,go build,go fmt,go vet, และgo doc
ฟังก์ชันที่คุ้มค่าแก่การทดสอบ
หัวข้อที่มีชื่อว่า “ฟังก์ชันที่คุ้มค่าแก่การทดสอบ”วิธีที่ดีที่สุดในการทำความเข้าใจ testing tools ของ Go คือเริ่มต้นด้วย pure function — ฟังก์ชันที่ไม่มี side effect ไม่มี I/O มีแค่ input และ output Playground ด้านล่างรัน Fibonacci และ IsPrime จาก main ในบทเรียนถัดไปคุณจะเขียนไฟล์ _test.go สำหรับฟังก์ชันแบบนี้โดยตรง
package main
import "fmt"
// Fibonacci returns the nth Fibonacci number (0-indexed).// fib(0)=0, fib(1)=1, fib(2)=1, fib(3)=2, ...func Fibonacci(n int) int { if n <= 1 { return n } return Fibonacci(n-1) + Fibonacci(n-2)}
// IsPrime reports whether n is a prime number.func IsPrime(n int) bool { if n < 2 { return false } for i := 2; i*i <= n; i++ { if n%i == 0 { return false } } return true}
func main() { // Print the first 10 Fibonacci numbers fmt.Println("Fibonacci sequence:") for i := 0; i < 10; i++ { fmt.Printf(" fib(%d) = %d\n", i, Fibonacci(i)) }
// Find primes up to 30 fmt.Println("Primes up to 30:") for n := 2; n <= 30; n++ { if IsPrime(n) { fmt.Printf(" %d\n", n) } }}Loading Go runtime (first run only, ~8 MB)…
ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| Approach | Benefit | Cost |
|---|---|---|
| built-in testing package | ไม่ต้อง install, standard API ทุก Go project | ไม่มี assertion library — ต้องเขียน if got != want เอง |
| table-driven tests | test หลาย case ใน 1 function, เพิ่ม case ได้ง่าย | ถ้า table ยาวมาก อ่านยาก |
go test ./... | รัน test ทุก package ใน module ครั้งเดียว | parallel test อาจ race ถ้าไม่ระวัง shared state |
race detector (-race) | ตรวจหา concurrent bugs อัตโนมัติ | ช้าลง 2-10x — ควรรันใน CI ไม่ใช่ทุก local run |
ความเข้าใจผิดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ความเข้าใจผิดที่พบบ่อย”- ต้องใช้ testing framework เหมือน Python/Node — Go standard library มีทุกอย่างที่ต้องการ ไม่ต้องติดตั้ง testify หรือ gomega เพิ่ม
- coverage 100% = code ปลอดภัย — coverage วัดว่า line ถูกรันหรือไม่ ไม่ได้วัด correctness — test ที่ไม่มี assertion ก็ทำให้ coverage 100% ได้
go testช้า —go testcache ผลลัพธ์ — ถ้าไม่มีไฟล์เปลี่ยน จะ return cached result ทันที
💡 ตัวอย่างจากของจริง
Kubernetes ใช้
go test ./...ทั้งหมด ไม่ใช้ external testing framework — standard library เพียงพอสำหรับ codebase ระดับ enterpriseDocker enforce
-raceflag ใน CI pipeline ทุก PR เพื่อตรวจจับ concurrent bug ก่อน merge