สำหรับนักพัฒนาที่เขียน test หรือชุดการทดสอบ นะ !!
มาดูกันว่า ชุดการทดสอบมันส่งกลิ่นแปลก ๆ บ้างหรือไม่ ?
ปกติ code ที่นักพัฒนาสร้างขึ้นมา
มักจะมีสิ่งแปลก ๆ
มักจะส่งกลิ่น หรือ ส่งสัญญาณของปัญหาออกมา
ซึ่งเราเรียกว่า Code Smell
ปัญหามันไม่ใช่ Code Smell เพียงอย่างเดียว
แต่ ....
มันมีอย่างอื่นอีกเช่น
เรารู้หรือไม่ว่าสิ่งเหล่านั้นมันคือ Code Smell !!
ถ้าพูดง่าย ๆ คือ
เรามีจมูกที่ดีหรือไม่
เรามีสายตาที่ดีหรือไม่
เพื่อทำให้ได้กลิ่น ให้มองเห็น Code Smell หรือสิ่งที่ผิดปกติหรือไม่ ?
นั่นคือสิ่งที่นักพัฒนาต้องสร้างและปรับปรุงความสามารถขึ้นมา
สำหรับการทดสอบก็เช่นกัน มาเริ่มกันเลยกับ Test/Unit Test Smell ว่ามีปัญหาอะไร อย่างไรกันบ้าง ที่บ่งบอกว่าจะทำให้เกิดปัญหาขึ้นมาได้
ชุดการทดสอบมันเขียนยากนะ ต้องใช้เวลาเพิ่ม
เป็นปัญหาแรก ๆ ของการเขียนชุดการทดสอบเลย ทั้งฝั่งนักพัฒนาและหัวหน้า รวมไปจนถึงฝ่าย management อะไรที่ไม่เคยทำ หรือ ทำไม่เป็น มักจะบอกว่า มันยาก ทำไม่ได้หรอก แต่ถ้าต้องทำอาจจะใช้เวลาเยอะมากขึ้นประเด็นคือ เราเรียนรู้หรือยัง ? ประเด็นคือ เราเคยลองทำหรือยัง และทำอย่างถูกต้องหรือไม่ ?ยิ่งถ้าไปเขียนชุดการทดสอบกับระบบที่มีอยู่แล้ว ยิ่งมีความยากขึ้นไปอีก เนื่องจากระบบที่ไม่ได้คิดเรื่องของการทดสอบมาก่อน จะลำบากและยากมาก ๆ อาจทำให้หมดกำลังใจไปได้เลย
ดังนั้น ถ้าเขียนชุดการทดสอบแล้วมันยาก สิ่งที่ต้องมองคือ code ที่เรากำลังเผชิญอยู่มันมีปัญหาหรือไม่ ?
ชุดการทดสอบมาก หรือ ละเอียดจนเกินไป
เขียนชุดการทดสอบที่ว่าเหนื่อยและยากแล้ว เขียนชุดการทดสอบมากจนเกินไปยิ่งเหนื่อยกว่ามาก !! แต่ถ้าไม่เขียนมาก ๆ จะไม่รู้ว่าอะไรควรเขียนหรือไม่ควรเขียน !! ยกตัวอย่างเช่นบรรดา private method ต่าง ๆ ในช่วงเริ่มต้นมักจะเขียนเพื่อทดสอบ private method เหล่านี้ให้ครบ จากนั้นก็ทำการทดสอบ method ที่เรียก private method นี้อีกรอบ ซึ่งทำให้การทดสอบซ้ำจำนวนมากของ private method (Duplication test)คำถามคือ เราควรทดสอบทั้งสอง method เลยหรือไม่ ? ลองถามใจดูนะการทดสอบควรเน้นพฤติกรรมให้มากกว่าลงรายละเอียด เพื่อช่วยลดผลกระทบของชุดการทดสอบจากการเปลี่ยนแปลง เช่นทำการเปลี่ยนแปลง code หรือ production code เป็นต้น
ทำการ Mock มากจนเกินไป (Mock Bubble)
สิ่งสำคัญมาก ๆ สำหรับการเขียนชุดการทดสอบคือ การแยก dependency หรือส่วนการทำงานต่าง ๆ ออกจากกัน เช่น แยกส่วนของ Database, API, Legacy ออกจากส่วนการทำงานหลัก หรือแยกออกไปจากส่วนที่เราสนใจ ทำให้สามารถจำลองและส่งสิ่งที่เราต้องการใช้เข้ามา (Mock, Stub) วิธีการนี้เรามักจะเรียกว่า Dependency Injection แต่ถ้าส่วนที่เราสนใจมี dependency จำนวนมาก ๆ !! ทำให้เราต้องสร้าง mock และ stub จำนวนมาก แน่นอนว่า สามารถทดสอบได้ แต่มันคือปัญหาเรื่องการออกแบบหรือไม่ ? ส่งผลให้ชุดการทดสอบพังได้ง่าย ? ส่งผลให้ยากต่อการเปลี่ยนแปลงหรือไม่ ? จำนวนของการทดสอบจะเยอะมาก ๆ ?การทดสอบช้ามาก ๆ
เมื่อเขียนชุดการทดสอบแล้ว ปัญหาที่มักจะตามมาคือ ใช้เวลาการทดสอบมากขึ้นเรื่อย ๆ หมายถึงเวลาที่นั่งรอผลการทดสอบมากขึ้นเรื่อย ๆคำถามคือ เร็วเท่าไรดี ? ตอบง่าย ๆ คือ เร็วกว่าเดิมและเร็วกว่าเดิม (Continuous Improvement)ปัญหาหลัก ๆ ของการทดสอบที่ใช้เวลานาน มักประกอบไปด้วย
- เป็น Integration test หรือไม่ ? เช่นต้องต่อกับ Database, API จริง ๆ หรือไม่ ?
- มีการ setup ต่าง ๆ ก่อนการทดสอบเยอะและซับซ้อนมากเกินไปหรือไม่ ?
- การทดสอบเป็นแบบ sequencial หรือไม่ ? ถ้าใช่ก็ลองเปลี่ยนไปเป็นแบบ parallel สิ
- ระบบงานแยกเป็น module หรือ ออกแบบผิดหรือไม่ ?
ชุดการทดสอบมัน fail แบบ Random Fail
เป็นปัญหาที่น่ากลัวมาก ๆ นั่นคือ ชุดการทดสอบมัน fail แบบสุ่ม ทั้ง ๆ ที่ไม่ได้เปลี่ยนแปลงอะไรเลย !! input ก็หมือนเดิม แต่ทำไมผลการทำงานไม่เหมือนกัน ทำให้ยากต่อการแก้ไขมาก ๆ บอกได้เลยว่าโครตน่ากลัว ปัญหานี้มักจะมาจาก ไม่เข้าใจพฤติกรรมการทำงานของระบบเช่น มีการทำงานแบบ asynchronous มีการทำงานกับเวลา หรือ dependency ที่ควบคุมไม่ได้ มีการทำงานที่ใช้งาน CPU/Memory มากจนเกินไป มีการใช้ resource pool ออกแบบระบบผิดหรือไม่จากนั้นก็ลงมือแก้ไขซะ
สุดท้ายสิ่งที่นักพัฒนาควรทำคือ
หัดฟังเสียงหรือผลการทำงานจากชุดการทดสอบด้วยเสมอ จากนั้นทำการปรับปรุงให้ดีขึ้นอย่างต่อเนื่อง ให้จำไว้เสมอว่า ชุดการทดสอบควรมีความสำคัญเทียบเท่ากับ production code เสมอคำถาม นักพัฒนาคิดว่า การทดสอบยังมีปัญหาอื่น ๆ อีกหรือไม่ ?ขอให้สนุกกับการ coding นะครับ