- Published on
Golang Part 3: Go Testing
- Authors
- Name
- Somprasong Damyos
- @somprasongd
Go Testing
เมื่อเราเขียนโปรแกรมแล้ว ก็ต้องมีการทดสอบโปรแกรมที่เราเขียนขึ้นมา ซึ่งการเขียน Test ในภาษา go นั้น เป็นเรื่องง่ายมากๆ เพราะ Go นั้นได้ build in มาให้แล้ว ซึ่งสามารถทำได้ทั้งการเขียน Test, Benchmark และเขียน Example เพื่อทำแสดงตัวอย่างการเรียกใช้งานฟัง์ชันนั้นๆ ได้
Test
การเขียน Test ในภาษา go นั้นมีหลักการเขียนมีดังนี้
ชื่อของไฟล์จะต้องลงท้ายด้วย
_test.go
ฟังก์ชันของ unit test จะต้องขึ้นต้นคำว่า
Test
และควรตั้งให้อ่านแล้วเข้าใจฟังก์ชันของ unit test จะต้องรับพารามิเตอร์ 1 ตัว คือ
(t *testing.T)
(Optional) packace name จะลงท้ายด้วย _test หรือไม่ก็ได้
เขียน test และเพื่อให้ง่ายต่อการเขียนจะใช้หลักการ AAA คือ
Arrange
Act
และAssert
Arrange สำหรับกำหนดค่าเริ่มต้นของการทดสอบ เช่น กำหนด input กำหนดผลลัพธ์ที่ต้องการ หรือ mock function ต่างๆ
Act สำหรับ execute (เรียก function) ส่วนที่ต้องการทดสอบหรือ business logic
Assert สำหรับการตรวจสอบว่า ผลการทำงานตรงตามที่คาดหวังหรือไม่ ซึ่งต้องมีทุก test
ตัวอย่างจะทำการเขียน Unit Test ทดสอบโปรแกรมบวก และลบ ง่ายๆ
- สร้างโปรเจคใหม่
$ mkdir gotest
$ cd gotest
$ go mod init gotest
- ตัวอย่างโปรแกรม
package math
// Add is our function that sums two integers
func Add(x, y int) (res int) {
return x + y
}
// Subtract subtracts two integers
func Subtract(x, y int) (res int) {
return x - y
}
- เขียน Unit Test
package math
import "testing"
func TestAdd(t *testing.T){
// Arrange
input1, input2 := 4, 6
want := 10
// Act
got := Add(input1, input2)
// Assert
if got != want {
t.Errorf("got %q, wanted %q", got, want)
}
}
การรัน Unit Test
การรัน test ทำได้โดยใช้คำสั่ง go test [package_name]
$ go test gotest/math
PASS
ok gotest/math 0.252s
หรือจะการรันทุก test ตั้งแต่ directory ปัจจุบันลงไป ใช้คำสั่ง go test ./...
$ go test ./...
PASS
ok gotest/math 0.252s
หรือจะการรันทุก test ใน ./math
$ cd math
$ go test
PASS
ok gotest/math 0.244s
ถ้าต้องการให้แสดงรายละเอียดออกมา ให้เพิ่ม -v
$ go test -v
=== RUN TestAdd
--- PASS: TestAdd (0.00s)
PASS
ok gotest/math 0.254s
การเช็ค Code coverage
ถ้าต้องการตรวจสอบว่าเราเขียน test ครอบคลุมโค้ดทั้งหมดแล้วหรือไม่ ด้วยการเพิ่ม -cover เข้าไป
$ cd math
$ go test -cover
PASS
coverage: 50.0% of statements
ok gotest/math 0.254s
และเรายังสามารถส่งออกเป็นไฟล์ เพื่อนำไปดูรายละเอียดเพิ่มเติมได้
$ go test "-coverprofile=coverage.out"
coverage: 50.0% of statements
ok gotest/math 0.280s
- ดูรายละเอียดว่าแต่ละ function นั้น มี test coverage เท่าไหร่
$ go tool cover "-func=coverage.out"
gotest/math/math.go:4: Add 100.0%
gotest/math/math.go:9: Subtract 0.0%
total: (statements) 50.0%
- แสดงผลในรูปแบบ HTML
$ go tool cover "-html=coverage.out"
Benchmark
นอกจากเขียนจะ Test เพื่อทดสอบการงานว่าถูกต้องหรือไม่นั้น ใน Go ยังสามารถเขียนเพื่อทดสอบ performance ของโค้ดได้ด้วย ซึ่งจะคล้ายกับการเขียน Test แค่เปลี่ยนชื่อฟังก์ชันให้ขึ้นต้นด้วย Benchmark
แทนแบบนี้ func BenchmarkXxx(*testing.B)
ตัวอย่าง จะทดสอบ benchmark ฟังก์ชัน Add
func BenchmarkAdd(b *testing.B){
for i :=0; i < b.N ; i++{
Add(4, 6)
}
}
ส่วนการรัน ให้ใส่ -bench
เติมเข้าไป โดยถ้าต้องการ benchmark ทุกตัวใช้ -bench=.
หรือถ้าจะระบุชื่อไปก็ได้ -bench=BenchmarkAdd
$ go test gotest/math -bench=BenchmarkAdd
goos: windows
goarch: amd64
pkg: gotest/math
cpu: Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz
BenchmarkAdd-8 1000000000 0.3443 ns/op
PASS
ok gotest/math 0.664s
ถ้าจะทดสอบ memory ด้วย ให้เพิ่ม -benchmem
เข้าไป
$ go test gotest/math -bench=BenchmarkAdd -benchmem
goos: windows
goarch: amd64
pkg: gotest/math
cpu: Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz
BenchmarkAdd-8 1000000000 0.3467 ns/op
0 B/op 0 allocs/op
PASS
ok gotest/math 0.676s
Document
สุดท้ายเราสามารถเขียน Document เพื่อแสดงตัวอย่างการเรียกใช้งานฟังก์ชันได้ด้วย มีวิธีเขียนดังนี้
- สร้างฟังก์ชันที่ขึ้นต้นด้วย
Example
ไม่ต้องรับ parameter อะไร - เขียน Example เพื่อแสดงตัวอย่างการใช้งานฟังก์ชันของเรา
- ใส่
// Output: XX
เพื่อแสดงตัวอย่าง output ที่จะได้ออกมา
func ExampleAdd(){
result := Add(4, 6)
fmt.Println(result)
// Output: 10
}
วิธีเอาไปแสดงใน Godoc
เพื่อที่จะเอา ExampleAdd ไปแสดงใน godoc ต้องติดตั้ง godoc ก่อน
$ go install golang.org/x/tools/cmd/godoc
แล้วรัน godoc
$ godoc -http=:8000
เมื่อลองไปเปิดดูจะเห็นว่าฟังก์ชัน Add ของเรา นั้นมีตัวอย่างการใช้งานให้ด้วย
ก็จบแล้วกับบทความสุดท้ายของชุดการศึกษาภาษา Go ตั้งแต่พื้นฐาน จนมาจบที่การเขียน Test ซึ่งเราจะเอาความรู้ทั้งหมดนี้ ไปลองเขียนเป็น API Service กันในบทความถัดไปๆ