Skip to main content
0
Back-End DeveloperDevInitSoftware Testing

การสร้าง Unit Tests ในภาษา Go

เกริ่นนำ

รู้หมือไร่ เอ้ย! รู้หรือไม่ ว่าใน VS Code สามารถสร้างโครงของ Unit Tests ในภาษา Go ให้เราโดยอัตโนมัติได้ด้วยนะ มันจะช่วยทุ่นแรงเราได้มากเลยล่ะ แต่ยังไงก็ตาม เราก็ควรฝึกสร้าง Unit Test ด้วยตัวเองเช่นกัน ถ้าอย่างนั้น เรามาดูวิธีสร้าง Unit Test แบบอัตโนมัติ กับแบบสร้างด้วยตัวเองกันเลย ไป!

ขอขอบคุณภาพประกอบจาก https://takenoterecalllater.wordpress.com/2021/06/08/golang-unittest-%E7%B0%A1%E5%96%AE%E4%BE%8B%E5%AD%90/


Auto Generate Unit Tests


1. สร้างโฟลเดอร์ชื่อ go-unit-test


2. เปิดโฟลเดอร์นั้นด้วย VS Code


3. go mod init โปรเจกต์ของเราใน path ที่ต้องการ


4. ลองสร้างฟังก์ชัน

สมมติฟังก์ชัน Plus บวกได้เฉพาะจำนวนเต็มบวกเท่านั้น (a >= 0 และ b >= 0) ถ้าใส่ค่าติดลบมา จะต้องคืนค่า MinInt กับ error กลับไป


5. วิธีการสร้าง Unit Tests อัตโนมัติ

ให้คลิกขวาที่ชื่อฟังก์ชันที่เราต้องการ จากนั้นคลิกที่คำสั่ง Go: Generate Unit Tests For Function เราจะได้ไฟล์ใหม่ขึ้นมา เป็นชื่อไฟล์นั้นตามด้วย test เช่น ฟังก์ชัน Plus อยู่ในไฟล์ main.go พอสร้าง Unit Test ขึ้นมาจะอยู่ในไฟล์ชื่อ main_test.go


หมายเหตุ:

สำหรับใครที่คลิกขวาแล้วไม่มีเมนู Go: Generate Unit Tests For Function ให้เลือก แสดงว่ายังไม่ได้ติดตั้ง Go Extension ใน VS Code สามารถคลิกที่นี่เพื่อติดตั้งได้เลย แต่อย่าลืมเช็ค requirements ด้วยว่า version ของ VS Code กับ version ของ Go รองรับ extension นี้หรือไม่ด้วยนะ อ่านได้ในหัวข้อ Requirements และ Quick Start ของ Go Extension ได้เลย

วิธีการเช็ค version ของ VS Code ทำได้หลายวิธี เช่น

วิธีที่ 1: พิมพ์คำสั่ง code –version ใน terminal


วิธีที่ 2: บนแถบเมนูของ VS Code คลิก … –> Help –> About


จะมีหน้าต่างปรากฏขึ้นมา แสดงรายละเอียดของ VS Code เราสามารถดูในหัวข้อ Version ได้เลย


สำหรับวิธีเช็ค version ของ Go ทำได้หลายวิธี เช่น

วิธีที่ 1: กรณีที่เปิดไฟล์ภาษา Go อยู่ ให้ดูมุมขวาล่างของ VS Code จะมีตัวเลขตามด้วยสัญลักษณ์สายฟ้าอยู่

วิธีที่ 2: พิมพ์คำสั่ง go version ใน terminal

วิธีที่ 3: ดู Go version ในไฟล์ go.mod


หรือใครที่อยากติดตั้ง extension ผ่าน VS Code โดยตรง ทำได้โดย

  1. คลิกที่เมนู Extensions ทางซ้ายมือของ VS Code
  2. ค้นคำว่า go
  3. คลิกที่ extension ที่ชื่อว่า Go
  4. หลังจากเช็ค version เรียบร้อยแล้วก็คลิก install ได้เลย
  5. จากนั้นตัว Go Extension จะให้ติดตั้ง tools บางอย่างเพิ่มเติม เช่น gopls เราจะ install ด้วยหรือไม่ก็ได้ แต่แนะนำว่า install ทุกอย่างตามที่มันแนะนำจะดีกว่า


6. และนี่คือหน้าตาของไฟล์ main_test.go สามารถอธิบายแต่ละส่วนได้ ดังนี้

  • type args struct คือ ส่วนที่บอกว่าฟังก์ชันรับ parameters อะไรบ้าง แต่ละตัวมี type อะไร
  • tests struct คือ สิ่งที่เกิดขึ้นหรือถูกกำหนดในแต่ละ Test case ได้แก่
    • name คือ ชื่อของ test case ตั้งเพื่อให้รู้วัตถุประสงค์ของ test case นั้น ๆ เช่น error_case_1:_a_<_0
    • args คือ arguments หรือค่าทั้งหมดที่ใส่ให้กับฟังก์ชัน ในที่นี้คือ ค่าของ a กับ b ที่เป็น int
    • want คือ ผลลัพธ์ที่เราคาดหวัง เช่น ให้ a = 1, b = 2 ฉะนั้นผลลัพธ์ที่คาดหวังคือ want = 3
    • wantErr คือ test case นั้นเราคาดหวังให้มี error เกิดขึ้นหรือไม่
      • ถ้าใช่ก็กำหนดเป็น true
      • ถ้าไม่ก็กำหนดเป็น false
  • // TODO: Add test cases. คือ ส่วนที่กำหนด test cases เดี๋ยวจะทำเพิ่มในขั้นตอนถัด ๆ ไป
  • for loop ที่จะวนทำทีละ test case ถ้าทุก case ตรงตามที่เรากำหนดก็จะขึ้นว่า OK คือ Pass ทุก case แต่ถ้ามีบาง case ไม่ตรงตามที่เราตั้งสมมติฐานไว้ก็จะ FAIL เช่น 1+1 = 2 แต่เราพิมพ์ผิด ให้ want = 3 แบบนี้ก็จะ FAIL ได้ เป็นต้น


7. Test cases

สิ่งที่เราต้องทำเพิ่มคือ สร้าง Test cases ต่าง ๆ มาใส่หลังบรรทัดที่ 16 ที่ comment ว่า // TODO: Add test cases. ในที่นี้ เราจะทดสอบทั้งหมด 4 cases คือ

  • happy case: a >= 0 และ b >= 0
  • error case 1: a < 0 แต่ b >= 0
  • error case 2: a >= 0 แต่ b < 0
  • error case 3: a <= 0 และ b <= 0

Tips: แนะนำสำหรับคนขี้เกียจอย่างเรา เราสามารถ Auto Fill struct ได้โดย

  • พิมพ์ {}, แล้วคลิกในปีกกา
  • กด ctrl + . (ใน Windows) หรือ cmd + . (ใน macOS)
  • คลิกคำว่า Fill anonymous struct{}


จะได้ struct เริ่มต้นออกมา


จากนั้น เราก็แค่กำหนดค่าที่ต้องการลงไป ทำซ้ำขั้นนี้ไปเรื่อย ๆ จนครบทุกเคส

เราสามารถลากคลุมส่วนที่ต้องการ แล้วกด shift+alt+ลูกศรลง (ใน Windows) หรือ shift + opt + ลูกศรลง (ใน macOS) เพื่อ copy paste แบบไว ๆ ได้ แล้วค่อยแก้ค่า


จะได้ cases ทั้งหมด ดังนี้


8. เลื่อนกลับขึ้นไปด้านบน ลองกดปุ่ม run test ได้เลย


9. กรณีผ่านทุกเคส จะขึ้นแบบนี้


10. กรณีมีบางเคสไม่ผ่าน เช่น ตั้งใจให้ 1+1=3  จะขึ้นแบบนี้

จะเห็นว่าการใช้ Auto Generate Unit Test ใน VS Code นั้นง่ายมาก


Manual Unit Tests

ทีนี้ เราลองมาทำ Unit Test เองดูบ้างว่าทำยังไง ในที่นี้จะยกตัวอย่างแค่ happy case กับ error case อย่างละ case ก็พอนะ ไป!


1. go get “github.com/stretchr/testify/assert” และ go install “github.com/stretchr/testify/assert” มาก่อน


การ assert คือ การเทียบระหว่าง 2 ค่าว่าเท่ากันมั้ย ถ้าใช่จะ return true แต่ถ้าไม่จะ return false มันต่างจากการเช็ค if else condition ทั่วไปตรงที่ต้องส่งค่า test เข้าไปด้วย แล้วมันจะเช็คให้ว่า test case นั้น ๆ Pass หรือ Fail


2. มาลองทำ Unit Test ด้วยตัวเองของ Happy Case กัน


จากตัวอย่างนี้ จะเห็น 3 คำสั่งหลัก ๆ ที่ใช้เกี่ยวกับ assert คือ

  • assert.Error(t, err, errMsg) จะรับ 2-3 ค่า
    • กรณีที่รับ 2 ค่า จะรับตัวแปร t ประเภท *testing.T กับ err ประเภท error โดย assert.Error จะถือว่า test case นี้ผ่านก็ต่อเมื่อมี error เกิดขึ้นแล้วถูกเก็บในตัวแปร err
    • กรณีที่รับ 3 ค่า ค่าที่ 3 เป็นประเภท interface นิยมใช้เมื่อเราต้องการเช็ค Error message ด้วยว่าตรงตามที่คิดหรือไม่
  • assert.Nil(t, err)  จะรับตัวแปร t ประเภท *testing.T กับ err ประเภท error โดย assert.Nil จะถือว่า test case นี้ผ่านก็ต่อเมื่อตัวแปร err มีค่าเป็น nil
  • assert.Equal(t, expectedValue, actualValue) จะรับตัวแปร t ประเภท *testing.T, ผลลัพธ์ที่คาดหวัง, และค่าจริง ๆ ที่ได้จากฟังก์ชันนั้น โดย assert.Equal จะถือว่า test case นี้ผ่านก็ต่อเมื่อค่าที่คาดหวังคือ expectedValue เท่ากับ ค่าจริงที่ได้คือ actualValue


3. ตัวอย่าง case ที่เราต้องการ assert Error message ด้วย


Test Coverage

อ้อ แถมอีกเรื่องหนึ่งคือ เรื่อง Test Coverage เราสามารถให้ VS Code ดูให้ได้ด้วยว่า test cases ทั้งหมดที่เราคิดมันครอบคลุมทุกส่วนของ function แล้วหรือยังโดย


1. Go: Toggle Test Coverage In Current Package

คลิกขวาที่ชื่อฟังก์ชันนั้น แล้วคลิกเลือกคำว่า Go: Toggle Test Coverage In Current Package จากนั้น VS Code จะ run test อัตโนมัติในไฟล์ที่ชื่อสอดคล้องกัน เช่น เราทดสอบฟังก์ชันในไฟล์ main.go มันก็จะ run test ในไฟล์ main_test.go


2. run package tests

การคลิกเมนู Go: Toggle Test Coverage In Current Package จะมีลักษณะเหมือนการ run package tests ที่ด้านบนสุดของไฟล์ main_test.go ซึ่งจะเหมาะสำหรับกรณีที่ไฟล์เรามีหลายฟังก์ชันแล้วต้องการ run test ทุกฟังก์ชันทีเดียว จะได้ไม่ต้องมานั่งคลิก test ทีละฟังก์ชัน


3. Test Report

ถ้าทุก Test cases ครอบคลุม code ทุกบรรทัดแล้ว function ของเราก็จะมีแถบเขียว ๆ ขึ้นทุกบริเวณ และได้ coverage 100.0% ใน test report


แต่ถ้ายังไม่ครอบคลุมทุกส่วนของ code จะมีแถบสีแดง ๆ ขึ้น และ test coverage จะไม่ครบ 100.0% เช่น กรณีนี้เราตั้งใจ comment test case ที่ b < 0 ออกไป จึงเห็นแถบสีแดงขึ้นตรง code ส่วน else if


สรุป

ก็จบกันไปแล้วกับบทความที่ 3 ของเรานะ สำหรับตัวอย่างนี้เป็นแค่การทำ Unit Test ของ function ง่าย ๆ เราอาจจะยังไม่เห็นภาพว่า Auto Generate Unit Tests ดีกว่า manual ยังไง แต่ถ้าลองทำงานจริงแล้วเจอฟังก์ชันที่ซับซ้อนกว่านี้ ต้องมีการ mock up ค่าและส่งค่าให้หลายฟังก์ชัน ตัว Auto Generate Unit Tests จะช่วยป้องกันไม่ให้เกิดกรณีที่เรา mock up ค่าไม่ครบได้นั่นเอง แต่การเขียน Test Case เองก็อาจจะดีกว่า Auto Gen ได้ในบางกรณี เอาเป็นว่าเลือกใช้กันตามความเหมาะสมได้เลยจ้า แต่ส่วนตัวแล้ว เราขี้เกียจ เลยชอบ Auto Gen มากกว่า 5555

ขอบคุณทุกคนมาก ๆ เลยนะที่อ่านจนจบ รอติดตามบทความต่อ ๆ ไปได้เลยจ้าาาา


อ้างอิง

  1. go-fill-struct. สืบค้นเมื่อ 10 เม.ย. 2567. จาก: https://github.com/s-kostyaev/go-fill-struct
  2. assert. สืบค้นเมื่อ 10 เม.ย. 2567. จาก: https://pkg.go.dev/github.com/stretchr/testify/assert
  3. Go: Fill struct is missing. สืบค้นเมื่อ 10 เม.ย. 2567. จาก: https://github.com/golang/vscode-go/issues/3101


ข้อมูลผู้เขียน

Awassanan Phanosak

Author Awassanan Phanosak

อดีต Back-End Golang Software Engineer ที่อยากจะเป็น Full-stack Developer

More posts by Awassanan Phanosak

เราใช้คุกกี้เพื่อพัฒนาประสิทธิภาพ และประสบการณ์ที่ดีในการใช้เว็บไซต์ของคุณ คุณสามารถศึกษารายละเอียดได้ที่ นโยบายความเป็นส่วนตัว และสามารถจัดการความเป็นส่วนตัวเองได้ของคุณได้เองโดยคลิกที่ ตั้งค่า

ตั้งค่าความเป็นส่วนตัว

คุณสามารถเลือกการตั้งค่าคุกกี้โดยเปิด/ปิด คุกกี้ในแต่ละประเภทได้ตามความต้องการ ยกเว้น คุกกี้ที่จำเป็น

ยอมรับทั้งหมด
จัดการความเป็นส่วนตัว
  • คุกกี้ที่จำเป็น
    เปิดใช้งานตลอด

    ประเภทของคุกกี้มีความจำเป็นสำหรับการทำงานของเว็บไซต์ เพื่อให้คุณสามารถใช้ได้อย่างเป็นปกติ และเข้าชมเว็บไซต์ คุณไม่สามารถปิดการทำงานของคุกกี้นี้ในระบบเว็บไซต์ของเราได้
    รายละเอียดคุกกี้

  • คุกกี้สำหรับการติดตามทางการตลาด

    ประเภทของคุกกี้ที่มีความจำเป็นในการใช้งานเพื่อการวิเคราะห์ และ นำเสนอโปรโมชัน สินค้า รวมถึงหลักสูตรฟรี และ สิทธิพิเศษต่าง ๆ คุณสามารถเลือกปิดคุกกี้ประเภทนี้ได้โดยไม่ส่งผลต่อการทำงานหลัก เว้นแต่การนำเสนอโปรโมชันที่อาจไม่ตรงกับความต้องการ
    รายละเอียดคุกกี้

บันทึกการตั้งค่า