JUnit เป็น library สำหรับการเขียน unit test สำหรับภาษา Java
ซึ่งหลายๆ คนบอกว่า มันอาจจะดูน่าเบื่อ ไม่ได้ต้องไปสนใจอะไรมากนัก
แต่ถ้าเขียน หรือ ใช้มันแบบไม่สนใจอะไร
จะพบว่า unit test ที่เขียนขึ้นมานั่นแหละ
มันจะทำให้คุณลำบาก เช่น

  • ดูแลรักษายาก
  • แก้ไขยาก
  • แก้ code ครั้งหนึ่งกระทบ test เยอะไปหมดเลย
  • ใช้เวลาในการพัฒนาสูง
  • ไม่ไว้ในการทดสอบ

ดังนั้นมาดูว่า จะเขียน unit test ด้วย JUnit อย่างไรให้ดูดีมีสาระ

เราคงไม่อยากเขียน unit test ที่มีหน้าตาน่าเกลียดแบบนี้ใช่ไหม ?

แล้วมันไม่ดีอย่างไรล่ะ ?

  • ทำไมใน test case เดียว ทำการ assert หรือทดสอบความคาดหวัง เยอะมากๆ มันไม่น่าดีนะ
  • โครงสร้างของ test case มั่วไปหมด อ่านยากและทำความเข้าใจยากไหม
  • จะพบว่าระหว่าง code ของ unit test กับ code จริงๆ มันผูกกันอย่างแนบแน่น
  • การดูแลรักษา การแก้ไข ยากมากมาย ว่าไหม ?

ดังนั้น เรายังจะทำแบบนี้ เขียน unit test แบบนี้กันอีกหรือ ???

ดังนั้นเรามาเริ่มต้นกันใหม่ดีกว่า

Lao Tzu กล่าวไว้ว่า
“A journey of a thousand miles begins with a single step”

โครงสร้างของ unit test ที่ดี

พื้นฐานของ unit test ที่ดีนั้น ประกอบไปด้วย 4 ส่วนคือ

  • Setup (Fixture)
  • Exercise
  • Verify
  • Teardown (ทำการคืน resource ต่างๆ ให้ระบบ)

ตัวอย่างเช่น

ส่วนผมชอบโครงสร้างแบบ 3 A คือ Arrange, Act, Assert
ซึ่งมีโครงสร้างคล้ายๆ กัน

เป้าหมายของโครงสร้างที่ดีนั้น
เพื่อช่วยให้นักพัฒนาอ่าน และทำความเข้าใจได้ง่ายขึ้น
ซึ่งจากผลการสำรวจพบว่า developer นั้น
ใช้เวลาในการอ่าน code เป็น 10 เท่าของการเขียน code เลยนะ
ถ้าลดเวลาการอ่านลงไปได้ ก็จะช่วยเพิ่มเวลาการเขียน code มากตามไปด้วย

เมื่อเพิ่มจำนวน test case ขึ้นมาเรื่อย เรามักจะพบว่า

ใน test case มี code ที่ซ้ำกันขึ้นมา
ใน test case มีสิ่งที่เรียกว่า magic number
ซึ่งพวกนี้จะถูกเรียกว่า Code Smell ในส่วนของ test case
ตัวอย่างเช่น code ที่ซ้ำกัน

สามารถลด code ที่ซ้ำกันในส่วนการ setup ข้อมูลเริ่มต้น
ด้วยการใช้ @Before ดังนี้

คำอธิบาย
ในแต่ละ test case ก่อนที่จะเริ่มทำงาน
จะเข้าทำงานในส่วนของ @Before ก่อนเสมอ

มี @Before ก็ต้องมี @After ซึ่งจะทำงานเมื่อแต่ละ test case ทำงานเสร็จ
เพื่อคืน resource อะไรบางอย่าง

ยังไม่พอ ว่าด้วยเรื่องของการจัดการ Exception ใน test case

โดยปกติเรามักจะทำการดักจับ exception ใน test case ในรูปแบบนี้

ซึ่งรูปแบบการดักจับ exception แบบนี้มันน่าเกลียดมากๆ
เพราะว่า มันจะทำให้คุณแยกไม่ออก หรือ แยกยากมากว่า
คุณกำลังจะทำอะไร ทดสอบอะไร นั่นคืออ่าน และ เข้าใจได้ยาก

ดังนั้น เราสามารถทำให้ test case ของเราดูสวยงาม อ่านง่ายขึ้นได้ ดังนี้

มันดูดีขึ้นกว่าเก่าไหมล่ะ …
แต่วิธีการนี้มันเกิดปัญหา หรือ มีความเสี่ยงสูงเช่นกัน
เพราะว่า เราไม่สามารถแยกได้ว่า exception ที่เกิดขึ้นมานั้น
มันมาจากส่วนของการ Setup หรือ (Exercise) การทำงานจริงๆ
ดังนั้นในส่วนของ test case อาจจะทำงานถูกต้องก็ได้
แต่ในส่วนของ Setup มันดันผิด

จากปัญหานี้ ทาง JUnit จึงคิดวิธีการอีกแบบมาให้ใช้คือ  @Rule + ExpectedException ดังนี้

โดยสรุปแล้ว

ในการนำ JUnit เพื่อมาเขียน unit test นั้น
อย่างแรกเลยก็คือ เรื่องโครงสร้างที่ดี
เพื่อทำการอธิบายว่าในแต่ละ test case นั้นทำอะไร
เพื่อลดเวลาในการอ่าน ทำความเข้าใจว่าต้องการทดสอบอะไร
เพื่อให้แต่ละ test case ทำการทดสอบอย่างไรอย่างหนึ่งเท่านั้น

ลองนำแนวคิดไปลองลงมือทำดูครับ ว่ามันช่วยอะไรบ้างไหม