มาทำ Unit Testing บน Golang กันเถอะ

Teerasak N
THE EXISTING COMPANY
2 min readApr 20, 2020

พร้อมกับวิธีการ generate mocks ซึ่งทำให้เราไม่ต้องแตะข้อมูลจริง

เมื่อก่อนตอนผมเริ่มต้นฝึกเขียน Unit Test ใหม่ๆ ผมเขียนผิดโดยไม่รู้ตัวมาตลอด
แทนที่จะเขียน Unit Test แล้วจะได้ Unit Test ผมกลับได้ Integration Test มาแทน

จนวันหนึ่งผมได้ยินพี่คนหนึ่งพูดขึ้น Unit Test ที่แท้จริง ควรเขียนแบบไม่แตะต้องข้อมูลจริง จึงถึงจะเป็น Unit Test จริงๆ

นั่นคือเหตุผลที่ผมได้ Intergration Test มาแทน ก็เพราะว่า Test ที่เขียนต้องต่อ Database และ Test ที่เขียนต้องคุยกับ service อื่น คือถ้าไม่มี Database หรือ Internet ก็ไม่สามารถเทสได้ แค่นี้ก็ทำให้ Unit Test ของผมได้แปลงร่างเป็น Integration Test แล้วครับ

แล้วอีกอย่างผมรู้สึกมาตลอดว่า Unit Test มันเขียนยากก็เพราะผมเขียนผิดมาตลอดจนวันหนึ่งผมได้เข้าใจแนวคิดของการเขียน Unit Test มันทำให้ดูสมเหตุสมผล แล้วการเขียน Unit Test ของผมมันก็ไม่อยากอีกต่อไป

วันนี้ผมจะมาแชร์วิธีการเขียน Unit Testing ในฉบับของผมเองโดยใช้ภาษา Go
อาจเป็นแนวทางให้ทุกคนได้นำไปใช้กันครับ

Unit Testing คืออะไร

มาเริ่มกันเลยครับ

ในบทความนี้จะเป็นการทดสอบ โดยเราจะสร้าง mock Interface ในส่วนของฟังก์ชัน ที่เราได้มีการเรียกใช้ Database ด้วยวิธี generate mocks โดย Mockery

สามารถเข้าไปดูรายละเอียดเพิ่มเติมได้ที่

มาติดตั้ง mockery เพื่อจะใช้งาน generate mocks กันก่อน

go get -u github.com/vektra/mockery/.../

ผมจะยกตัวอย่างฟังก์ชันที่มีการเรียกใช้ Database ครับ

เตรียม Code ของเรากันก่อน

มาเริ่มในส่วนของ Models กันก่อน

go-unit-testing/internal/models/todo.go

ส่วนของ Repository

go-unit-testing/internal/todo/repository/postgres_todo.go

ส่วนของ Usecase ที่มีการเรียกใช้ Repository

go-unit-testing/internal/todo/usecase/todo_ucase.go

มาถึงตรงนี้ก็เรียบร้อยสำหรับ Code ของเราก็พร้อมที่จะทำการ generate mocks

$ cd internal/todo/repository
$ mockery --name=Repository

เราจะได้ไฟล์พร้อม directory ที่ชื่อว่า mocks

go-unit-testing/internal/todo/repository/mocks/Repository.go

ทำการย้าย directory /mocks ไปไว้ที่ directory /todo

$ mv mocks $GOPATH/src/github.com/(name_repo)/go-unit-testing/internal/todo/

ถึงตอนนี้ก็พร้อมสำหรับการเขียน Unit Testing แล้ว

มาเริ่มเขียนเทสกันเลยครับ

สร้างไฟล์ทดสอบอยู่ใน path /usecase

$ touch todo_ucase_test.go
go-unit-testing/internal/todo/usecase/todo_ucase_test.go

มาลองดูผลการทดสอบ Unit Testing ที่พึ่งเขียนเสร็จดูครับ

$ go test -v -cover

ก็จบแล้วครับสำหรับตัวอย่างการเขียน Unit Testing ในส่วนของ Usecase ที่มีการเรียกใช้ Repository ก็ยกตัวอย่างมาแค่ส่วนหนึ่งที่ง่ายๆ เพื่อให้ได้เห็นภาพกันครับ
เพื่อนๆ ลองนำไปปรับใช้ในโปรเจคกันดูครับ

สรุป

หลายๆ ครั้งที่เกิด Issue มักจะเป็นฝันร้ายของหลายๆ คนเลยทีเดียว ต้องรีบไป debug ตั้งแต่ต้นทางไปยังปลายทาง ทำแบบนั้นซ้ำๆ จนกว่าจะแก้ไขเสร็จ แต่ไม่ดีกว่าเหรอถ้าเรามี Unit Testing ในแต่ละหน่วยก็จะทำให้เราไม่มีเสียเวลาทั้งหมดกับการ debug และยังทำให้ Code ของเราครอบคลุมมากกว่าที่เราคิดไว้ตั้งแต่แรก

เมื่อพูดถึงการเขียน Unit Testing มันอาจจะยากและเสียเวลาในช่วงแรกๆ แต่มันจะคุ้มค่า เมื่อเกิด Issue เราจะสามารถแก้ไขได้เร็วและตรงจุดมากขึ้น ถ้าเราฝึกเขียนบ่อยๆ ครั้งต่อไปก็จะเขียนได้ง่ายขึ้นและเร็วขึ้นครับ

--

--