เริ่มต้นเขียน Unit Test ใน Go ที่มือใหม่ก็เขียนได้

แนะนำขั้นตอนที่ง่ายๆ ในการเริ่มต้นเขียน Unit Test ด้วยภาษา Go พร้อมเจาะลึกหลักการ AAA และประโยชน์จากการเขียน Unit Test

Samithiwat
Thinc.
4 min readApr 7, 2023

--

ฝึกเขียน Unit Test กันเถอะ

สวัสดีครับ หลายคนอาจสงสัยว่า ‘Unit Test คืออะไร’ และ ‘Unit Test เขียนยังไง’ ในบทความนี้เราจะหาคำตอบด้วยการเขียน Unit Test ใน Go ที่มือใหม่ก็ทำได้ง่ายๆ พร้อมเจาะลึกวิธีการและประโยชน์ของการใช้หลักการ AAA

เกริ่นนำ

แม้ว่าการเขียน Unit Test สำหรับคนที่เพิ่งเริ่มต้นนั้นมักจะถูกมองข้ามบ่อยครั้ง แต่บริษัทที่มีขนาดใหญ่กลับให้ความสำคัญกับมันอย่างมากเพราะ Unit Test ช่วยให้เราตรวจจับข้อผิดพลาดได้ตั้งแต่ช่วงแรกของการพัฒนา ลดความซับซ้อนในอนาคต

ในบทความนี้เราจะเจาะลึกถึง “ประโยชน์ของ Unit Testing” และ “การใช้หลักการ AAA ใน Unit Test” ทำให้คุณสามารถเข้าใจและนำไปใช้ได้จริงในงานของคุณเรามาดูกันว่าทำไมบริษัทใหญ่เขาถึงให้ความสำคัญกับการเขียน Unit Test ถึงขนาดนี้

Catching Bug in Early Stage

แน่นอนอยู่แล้วว่าการเขียน test ก็เพื่อ test software ของเราและสิ่งที่เป็นผลพลอยได้ตามมาคือมันจะทำให้เราสามารถเจอ bug ได้ในช่วงแรกๆของการ dev

ทำให้เราสามารถแก้ไขได้อย่างก่อนที่มันจะขึ้นไปบน production และกลายเป็นจุดเล็กๆใน application ซึ่งยากต่อการค้นหา bugในอนาคตเมื่อ code base มีขนาดใหญ่ขึ้น

Software Documentation

ในการเขียน softwareใน code base ที่มีขนาดใหญ่สิ่งที่เราจะต้องคำนึงถึงนอกจากว่ามันจะใช้ได้ตาม requirement ที่เราอยากได้ไหม ยังจำเป็นที่จะต้องคิดถึงเรื่อง maintenance ด้วย

Code base ที่ดีคือสำหรับ developer ที่เข้ามาใหม่ควรที่จะสามารถทำความเข้าใจกับ code base ของเราได้อย่างไม่ยากจนเกินไป

แล้วอะไรคือสิ่งที่จะทำให้ developer สามารถทำความเข้าใจกับ code base ของเราได้บ้างล่ะ

  1. Documentation
  2. Unit Test

จากที่ list มา Documentation มันชัดเจนอยู่แล้วว่ามันคืออะไรแต่ Unit Test นี่มาได้ยังไงกันนะ 🤔

ศัพท์ที่ควรรู้ก่อนเริ่มเขียน Unit Test

Mock

สิ่งที่เราสร้างขึ้นมาเพื่อทดสอบ (ใช้แค่ในการ Test)

การ Mock ใน Unit Test เป็นไปได้ทั้ง Mock Data หรือ Mock Function ขึ้นอยู่กับโครงสร้างของโปรเจคเราและสิ่งที่เรากำลังเทส

Production Code

Code ที่เรานำมาทดสอบ (code ของจริง)

Test Case

เหตุการณ์ที่เราอยากจะทดสอบว่า code ของเราทำงานได้ตามที่คาดหวังไหม

การเขียน Unit Test

ในการเขียน test นั้นมีหลักการที่จำง่ายๆ อยู่ 3 อย่างคือ

Arrangement

การเตรียม aka mock data เพื่อใช้ในการ test โดยที่รวมไปถึงการ defined สิ่งที่เราต้องการ (expectation) จาก production code ด้วย

Act

การเรียกใช้งาน production code ที่เราต้องการเทสเพื่อนำผลลัพธ์ (actual) มาเช็คต่อในขั้นตอน assert

Assert

เช็คว่า expectation กับ actual นั้นตรงกันไหม

ถ้าคุณรู้ 3 อย่างนี้แล้วเมื่อคุณเปิดไฟล์ unit test อ่านคุณจะสามารถรู้ได้เลยว่า code ส่วนนี้ทำงานยังไงบ้างและให้ผลลัพธ์อะไรออกมา

ถ้ายังไม่เห็นภาพงั้นเรามาดูตัวอย่างกัน

scroll down the picture for more detail

จากตัวอย่าง Unit Test อันนี้จะเห็นได้ว่าชื่อของ Test จะสื่อถึง use case ของ production code และ scenario ที่ Unit Test ต้องการจะเทส

  • Use case = Divide
  • Scenario = Success

ในตัวอย่างคือเป็นเคสที่หารสำเร็จง่ายๆแบบที่เราเรียนเลขมาตอนประถมเลย

งั้นเรามาดูกันทีละส่วนว่ามันมีอะไรบ้างกัน

Arrangement

ในส่วนของ arrangement ใน unit test ตัวนี้เราได้เตรียม data และ expectation (want) ของ scenario นี้ไว้คือ

  • input1 (ตัวตั้ง) = 50
  • input2 (ตัวหาร) = 5
  • want (ผลลัพธ์ที่ควรได้) = 10

ถ้าแปลง่ายๆก็ถ้า 50 หารด้วย 5 ก็ควรจะได้ผลลัพธ์ออกมาเป็น 10 ตามี่มันควรจะเป็นจริงๆ

Act

ในส่วนนี้ก็คือการเรียกใช้ function Divide ของจริงโดยที่เรานำ input ทั้ง 2 ตัวที่เรา mock ขึ้นมาเป็น parameter ของ function Divide

Assert

และเมื่อเราได้ actual มาแล้วขั้นตอนสุดท้ายคือเช็คว่า want กับ actual นั้นตรงกันไหม และถ้ามี error เกิดขึ้นก็ถือว่า test failed เหมือนกัน

จากที่เราไล่ดูมาก็น่าจะพอเข้าใจได้ว่า function นี้คือการนำ input1 ไปหารด้วย input2 เพื่อให้ได้ผลลัพธ์ออกมา

ถ้าตัวอย่างที่แล้วยังไม่ค่อยเห็นภาพมาดูกันอีกตัวอย่างนึงในเคสที่เกิด error ถ้าหารด้วย 0

scroll down for more detail

Arrangement

ในครั้งนี้เราเตรียม data ให้ตัวหารมีค่าเป็น 0 และ expectation (want) ของ scenario นี้คือ 0 (default value) เพราะถ้าหากเกิด error คือที่ได้ควรจะเป็น default value ของแต่ละ type

  • input1 (ตัวตั้ง) = 50
  • input2 (ตัวหาร) = 0
  • want (ผลลัพธ์ที่ควรได้) = 0 (default value)

ถ้าแปลง่ายๆก็ถ้า 50 หารด้วย 0 ก็ควรจะเกิด error ก่อน assign ค่าผลลัพธ์จึงควรออกมาเป็น 0 (default value)

Act

ในส่วนนี้ก็เรียกใช้ function Divide โดยใส่ arguments เป็น input ทั้ง 2 ตัวที่เรา mock ขึ้นมา

Assert

และเช็คค่าที่เราตั้ง expectation ไว้

  • error ควรเกิดขึ้น err == nil -> ผิด
  • acutal ควรเป็น 0 (default value) actual != 0 -> ผิด

ถ้าสรุปแบบคร่าวๆตามที่ไล่ดู Unit Test ทั้ง 2 scenario เลยก็คือ function นี้จะรับ input 2 ตัวและจะเกิด error เมื่อ input2 มีค่าเป็น 0

จากที่เราไล่ดูมาทั้ง 2 ตัวอย่างก็น่าจะพอเข้าใจได้ว่า function ในการหารมันรับ input อะไรบ้างและจะเกิด error เมื่อมีเคสอะไรบ้าง

ทำให้เราพอจะเดาไส้ข้างในของ function Divide ได้เลยโดยที่ไม่ต้องไปเปิดอ่าน source

แนะนำว่าให้ลองก็อป Unit Test 2 ตัวนี้ไปแล้วไปเขียน function Divide กันดูแล้วจะเข้าใจมากขึ้นนะครับ 👍🏻

สามารถเช็คคำตอบได้ใน Github นี้เลยนะค้าบ

และถ้าอยากเข้าใจมากขึ้นในการเขียน unit test ให้ลองนำหลักการ AAA ไปลองเขียน unit test ง่ายๆสำหรับ function ที่ใช้ในการ บวก ลบ คูณ ที่เหลือดูครับ

จบแล้ววว

ในที่สุดเมื่อเราเข้าใจ ‘Unit Test คืออะไร’ และ ‘Unit Test เขียนยังไง’ การเขียน Unit Test จะไม่ใช่เรื่องที่น่ากลัวอีกต่อไป ไม่เพียงแค่เป็นทักษะพื้นฐานสำคัญใน Software Engineering แต่ Unit Test ยังเป็นเครื่องมือที่สำคัญในการพัฒนาซอฟต์แวร์ที่มีประสิทธิภาพ

การใช้หลักการ AAA ในการเขียน Unit Test ไม่เพียงแค่ช่วยให้เราพัฒนาโค้ดที่มีคุณภาพ แต่ยังช่วยให้กระบวนการพัฒนาของเรามีประสิทธิภาพมากขึ้นดังนั้นสำหรับคนที่กำลังเริ่มต้นสิ่งที่สำคัญคือความเข้าใจที่ถูกต้องเกี่ยวกับการเขียน Unit Test และการนำไปประยุกต์ใช้ซึ่งจะเป็นก้าวสำคัญในเส้นทางของคุณในวงการ Software Engineering ต่อไป

Thailand Incubator (Thinc.) — Think Make Impact 💡

ติดตามพวกเราได้ที่

--

--