Unit tests คือ executable document
เคยไหมที่เจอเหตุการณ์ให้ต้องไปอ่านโค้ดคนอื่น แล้วพออ่านเสร็จก็เห็นว่าโค้ดมันผิด เลยไปแก้มันให้ถูก แต่พอคิดอีกที ไม่แตะมันดีกว่า แล้วก็ undo จนมันกลับไปเป็นเหมือนเดิม
ทำไมนะ?
ผมเคยลองถามตัวเองดูว่าอะไรเป็นสาเหตุที่ทำให้ผมยอมทิ้งทั้งโอกาสและแรงที่ลงไปแล้ว ที่จะปรับปรุงโค้ดให้ดีขึ้นเพื่อตัวเองและเพื่อนร่วมทีมในอนาคต แล้วกลับไปอยู่กับโค้ดเดิม ๆ กันนะ
คำตอบที่ปรากฏออกมาคือ ผมกลัว กลัวว่าสิ่งที่แก้ไปจะไปสร้างปัญหาใหม่ที่ผมไม่คาดไม่ถึง และที่ผมกลัว เพราะ ผมไม่รู้ว่าที่โค้ดเป็นแบบที่มันเป็นอยู่ มันตั้งใจจะแก้ปัญหาอะไรบ้าง ผมมีข้อมูลไม่เพียงพอที่จะปรับปรุงมัน เพราะผมเห็นแค่ solution ใน source code แต่ไม่เห็น problem ที่โค้ดนี้พยายามจะแก้ (requirement)
แล้ว requirement อยู่ไหน?
ปรกติ requirement อยู่ใน requirement document ซึ่งบ่อนครั้งถูกจัดเก็บในรูปของ file word หรือ excel
แล้วปัญหาของการจัดเก็บ document ในลักษณะนี้คือ มันมักจะไม่ update เท่ากับโค้ด เอกสารเหล่านี้ถูกสร้างขึ้นมาบนสมมติฐานว่า user ต้องการแบบนี้ แต่พอทำไปแล้วมี feedback จาก user ว่าอยากให้ปรับอย่างไร บ่อยครั้งมันไม่ถูก update ให้ตรงตามความเข้าใจในปัญหาที่เพิ่มพูนขึ้นจากการปฏิสัมพันธ์กับ user ส่งผลให้เอกสารมันไม่ถูกต้อง 100%
เอกสารที่แม่นยำ 99% ไม่มีประโยชน์
เพราะเราไม่รู้ว่า 1% ที่มันไม่จริงนั้นอยู่ตรงไหน ถ้าสามารถขอพรได้ เราอยากให้ตัวหนังสือที่จริงเป็นสีเขียว และเมื่อไหร่ที่มันไม่จริงขึ้นมา (outdated) ตัวหนังสือก็เปลี่ยนเป็นสีแดงโดยอัติโนมัติ แต่ชีวิตจริงมันไม่เป็นแบบนั้น
Unit test
unit test จึงถูกคิดขึ้นมาเพื่อแก้ปัญหานี้ โดยแต่ละ test จะเก็บ 1 ตัวอย่างที่ user อาจจะใช้งานระบบ พร้อมกับพฤติกรรมที่ user คาดหวังจากระบบ
เมื่อเราเขียนจนครบทุกกรณีที่ระบบจะถูกใช้งาน รวมถึงพฤติกรรมที่เราคาดหวังทั้งหมดไว้ เอกสารชุดนี้ก็เลยรวบรวมปัญหาที่ระบบจะต้องแก้เก็บไว้หรือที่เราเรียกว่า requirement นั่นเอง
และการเก็บ requirement ในรูปแบบที่สามารถ execute ได้ หมายถึงเอาไป run เพื่อเช็คความแม่นยำกับระบบจริง ๆ ได้ มีประโยชน์กว่ารูปแบบ file word หรือ excel เพราะเมื่อไหร่ที่มีกรณีไหนไม่เป็นจริงขึ้นมา test case นั้นก็จะระบายสีแดงขึ้นมาโดยอัตโนมัติ ส่วน test case ที่ยังเป็นจริงก็จะยังเขียวอยู่
สรุป
อยากชวนให้มอง unit test ให้เป็นเอกสาร อย่าสักแต่ว่าเขียนเพื่อทำให้ถึง code coverage ที่ตั้งใจไว้ ทุกครั้งที่เขียนให้จินตนาการว่ากำลังเขียนจดหมายถึงตัวเราเองและเพื่อนในทีมในอนาคต เวลาที่พฤติกรรมของระบบที่คาดหวังใน test case นี้มัน fail ขึ้นมา เราอยากให้ตัวเราในอนาคตรู้เรื่องอะไรบ้าง บางครั้งผมก็ reference ข้อมูลใน wiki หรือ knowledge management ขององค์กร บางครั้ง mention ชื่อ user ที่เป็นคนเล่าความยากลำบากที่เค้ากำลังเผชิญให้ผมฟัง
test case แต่ละอันเป็นเหมือนเชือก เราทำให้มันเป็นตาข่ายที่รับเราและทีมไว้ในวันที่เราพลาดไม่ให้ตกก็ได้ หรือทำให้มันเป็นแหที่มัดเราไว้ ไม่ให้เราแก้ซอฟต์แวร์ที่เป็นอยู่ก็ได้ ขึ้นอยู่กับว่าเราถนอมเรื่องราวหรือปัญหาที่เราพยายามจะแก้ในโค้ด (หรือ solution) ที่เราสร้างไว้ได้ดีแค่ไหน
unit test เปิดโอกาสให้เรามีเอกสารในฝันที่สามารถเปลี่ยนสีเขียวหรือแดงได้อย่าอัตโนมัติแล้ว มันคงน่าเสียดายถ้าเราสักแต่เขียนให้ได้ code coverage แต่ลืมที่จะถนอมปัญหาที่เราจะแก้ไว้ แล้วเขียนแค่ระบบต้องมีพฤติกรรมแบบนี้แหละโดยไม่เล่าเรื่องราวว่าเพราะอะไร