Screen Shot 2558-07-16 at 2.53.29 PM
หลังจากที่เขียนเรื่อง Developer ต้องฝึกตั้งชื่อให้มันสื่อสารกันได้
ดังนั้นลองมาฝึกตั้งชื่อแต่ละ test case ใน Unit test กันดีกว่า
ซึ่งมีวิธีการตั้งชื่อที่ดี และ น่าสนใจดังต่อไปนี้

แนวทางจากหนังสือ The art of Unit testing

แนะนำว่าชื่อ test case ควรมีรูปแบบดังนี้

  • UnitOfWork_StateUnderTest_ExpectedBehavior
  • MethodName_StateUnderTest_ExpectedBehavior
  • Unit of work คือ use case ของระบบที่เราต้องการทดสอบ
  • Method name คือ ชื่อ method ที่เราต้องการทดสอบ
  • State under test คือ สถานะของการทดสอบย ซึ่งสัมพันธ์กับ input ที่เราใส่เข้าไป
  • Expected behaviour คือ ผลลัพธ์ที่คาดหวังของการทำงานจาก input ที่เรากำหนด

เมื่อ state หรือ สถานะของระบบเปลี่ยนไปแล้ว
พฤติกรรม หรือ ผลการทำงานของระบบก็ต้องเปลี่ยนไปตามที่คาดหวังด้วย

โดยแต่ละ Unit of work นั้นมันสามารถเป็น

  • method เล็กๆ
  • method ใหญ่ๆ
  • มีหลายๆ class ทำงานร่วมกัน

แต่จะต้องอยู่ภายใต้การควบคุมของเราเสมอ

ตัวอย่างการตั้งชื่อตามแนวคิดนี้

  • Sum_NegativeNumberAsFirstParameter_ExceptionThrown()
  • Sum_NegativeNumberAsSecondParameter_ExceptionThrown()
  • Sum_SimpleValues_Calculated

จะสังเกตุได้ว่า การเขียนรูปแบบดังกล่าวมีเหตุผลดังนี้

เหตุผลที่ 1

ชื่อ test case นั้นมันจะต้องบอก และ อธิบายการทำงานได้อย่างชัดเจน
และเป็นไปตามสิ่งที่ระบุไว้ใน requirement
โดยแต่ละ test case นั้นมันคือ ปัญหาย่อยๆ ที่ถูกแบ่งออกมาเพื่อแก้ไขปัญหาจาก requriement

ลองคิดดูสิว่า
ถ้าแต่ละ test case ใน unit test มันไม่เป็นไปตาม requirement แล้ว
คุณจะเขียน unit test ไปทำไม ?
สิ่งที่คุณเขียนมันจะมีประโยชน์ และ คุณค่าอะไร ?

เหตุผลที่ 2

ชื่อ test case มันต้องประกอบไปด้วย input และ สถานะที่เรากำหนด
รวมทั้งต้องมีผลลัพธ์ที่เราคาดหวังจาก input
ดังนั้น เมื่อเราอ่านชื่อ test case แล้ว
มันจะทำให้เราเข้าใจเลยว่า มันสื่อถึง requirement อะไร

ลองดูชื่อ test case ที่ไม่สื่อดูสิ เช่น Sum_NumberBiggerThan1000
คำถาม คือ ชื่อ test case นี้บอกอะไรเราบ้าง ?
คำตอบ มันบอกเราเพียงว่า input ที่ส่งเข้าไปในการคำนวณมีค่ามากกว่า 1000 …
คำถาม คือ แล้วบอกไหมว่า กำลังจะทดสอบอะไร จาก requirement ?

เหตุผลที่ 3

ชื่อ test case มันต้องอธิบายความจริงของขั้นตอนการทำงาน และ ผลลัพธ์ที่เราคาดหวัง
เนื่องจาก unit test มันก็คือเอกสารของระบบงานชนิดหนึ่งนั่นเอง
เป็นเอกสารของการทดสอบส่วนการทำงานต่างๆ
ดังนั้น ผู้อ่านจะเป็นใครก็ได้ ไม่ใช่เพียงทีมพัฒนาเท่านั้น
ซึ่งคนเหล่านั้น ไม่เสียเวลามานั่งตีความ หรือ มาพยายามทำความเข้าใจหรอกนะ !!

ในการเขียนชื่อ test case ให้มันสื่อสารได้ดีนั้น
อาจจะต้องเขียนยาวมากๆ
แต่มันก็ดีกว่าการเขียนสั้นๆ เพื่อให้ computer เข้าใจอย่างเดียวนะเออ !!

บ่อยครั้งจะพบว่าชื่อ test case แบบแย่ๆ จะเป็นแบบนี้

  • Sum_NegativeNumber1_ExceptionThrown()
  • Sum_NegativeNumber2_ExceptionThrown()

แล้วไอ้ 1, 2 มันคืออะไรหว่า ?

เปลี่ยนชื่อให้มันสื่อสารชัดเจนขึ้นกว่าเดิมไหม เช่น

  • Sum_ExceptionThrownOnNegativeNumberAsFirstParameter หรือ Sum_NegativeNumberAsFirstParameter_ExceptionThrown()
  • Sum_ExceptionThrownOnNegativeNumberAsSecondParameter หรือ Sum_NegativeNumberAsSecondParameter_ExceptionThrown()

เหตุผลที่ 4 !!!

การตั้งชื่อตัวแปรใน test (Variable name)
โดยปกตินั้น ชื่อตัวแปร มันต้องสื่อสารให้ชัดเจน
ว่าตัวมันเองทำงานอะไร ?

โดยที่ชื่อของตัวแปร มันจะเป็นไปตามชื่อของ method นั่นแหละ
แต่ใน unit test มันมีสิ่งที่ควรระวังพอสมควรนะ !!
มาดูกันว่า ควรระวังอะไรบ้าง ?

บ่อยครั้งเรามักสร้างตัวแปรที่เป็นค่าคงที่ (constant variable) ขึ้นมาใช้งาน
เพื่อลดปัญหาของ magic number ลงไป เช่น

  • MAX_SIZE
  • BAD_DATA
  • DATA_NOT_FOUND
  • EMPTY_DATA

คำถามคือ
เราต้องการพวก constant variable ใน test หรือไม่ ?
น่าคิดนะ ว่าไหม ?

แนวทางที่ขอแนะนำ ในการตรวจสอบว่าชื่อที่เราใช้งานมันดีพอหรือไม่
นั่นก็คือ ให้ดูที่ส่วนของ assert หรือ ส่วนที่ใช้ตรวจสอบผลการทำงาน
เป็นไปตามที่เราต้องการหรือไม่ นั่นเอง
ให้พิจารณาดูสิว่า มันทำงานตาม requirement หรืออธิบายตามที่เราต้องการหรือไม่ ?

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

  1. assertEquals( -1, actualResult );
  2. assertEquals( BAD_DATA, actualResult );
  3. assertEquals( -1, actualResult, “Method should return bad data” );
  4. assertEquals( BAD_DATA, actualResult, “Method should return bad data” );

คุณคิดว่าแบบใด ที่สื่อสารได้ชัดเจน ?
เลือกกันดูนะครับ !!

ลองนำแนวทางการตั้งชื่อ test case นี้
ไปใช้เพื่อปรับปรุงให้ unit test ของเรามันอ่านขึ้น เข้าใจง่ายขึ้นดูกันครับ