ชุมชนนักพัฒนาซอฟต์แวร์กำลังมีการถกเถียงอย่างเข้มข้นเกี่ยวกับวิธีการทดสอบ ซึ่งถูกจุดประกายโดยการอภิปรายที่กลับมาใหม่เกี่ยวกับหลักการ Don't Mock What You Don't Own หลักเกณฑ์การทดสอบนี้แนะนำให้นักพัฒนาสร้าง mock objects เฉพาะสำหรับโค้ดของตนเองเท่านั้น ไม่ใช่สำหรับไลบรารีของบุคคลที่สามหรือ dependencies
ความขัดแย้งหลัก: การแยกส่วนเทียบกับการรวมส่วน
ชุมชนดูเหมือนจะแบ่งแยกในเรื่องของว่าควรทดสอบซอฟต์แวร์ส่วนไหนร่วมกันบ้าง นักพัฒนาบางคนสนับสนุนการทดสอบระบบจริงให้มากที่สุดเท่าที่จะทำได้ โดยโต้แย้งว่าการแยกส่วนมากเกินไปจะนำไปสู่ความมั่นใจที่ผิดพลาด พวกเขากังวลว่าการ mock dependencies ของบุคคลที่สามจะทำให้สิ่งเหล่านั้นหลุดจากการทดสอบ ซึ่งอาจพลาดการเปลี่ยนแปลงที่ทำให้เกิดปัญหาเมื่อไลบรารีอัปเดต APIs ของตน
ส่วนคนอื่นๆ สนับสนุนแนวทางของหลักการนี้ในการสร้างชั้น wrapper บางๆ รอบ external dependencies กลยุทธ์นี้มีจุดประสงค์เพื่อรักษา business logic ให้สะอาดและทดสอบได้ ขณะเดียวกันก็ลดความซับซ้อนที่มาพร้อมกับการ mock APIs ของบุคคลที่สามที่ซับซ้อน
ความท้าทายในการทดสอบในโลกจริง
ความกังวลสำคัญที่นักพัฒนายกขึ้นคือความท้าทายในทางปฏิบัติของการดูแลรักษาการทดสอบเมื่อไลบรารีของบุคคลที่สามเปลี่ยนแปลง สมาชิกชุมชนคนหนึ่งเน้นย้ำสถานการณ์ที่พบบ่อย: การค้นพบการเปลี่ยนแปลง API หลังจาก deployment เพราะการทดสอบถูกแยกออกจาก dependencies จริง สิ่งนี้ทำให้ทีมบางทีมชอบใช้ HTTP recording และ replay libraries มากกว่าแนวทาง mocking แบบดั้งเดิม
ประสบการณ์การ debug ก็เป็นปัจจัยสำคัญในการอภิปรายเช่นกัน นักพัฒนารายงานว่า fake objects ให้ประสบการณ์การ debug ที่ดีกว่ามากเมื่อเปรียบเทียบกับการตั้งค่า mock ที่ซับซ้อน ซึ่งอาจกลายเป็นสิ่งที่เข้าใจยากและดูแลรักษายากเมื่อเวลาผ่านไป
แนวทางทางเลือกที่ได้รับความนิยมเพิ่มขึ้น
การสนทนาได้เผยให้เห็นกลยุทธ์การทดสอบทางเลือกหลายแบบที่กำลังได้รับความนิยม High-fidelity fakes กำลังเป็นจุดกึ่งกลาง โดยเสนอพฤติกรรมที่สมจริงกว่า mocks ธรรมดา ขณะเดียวกันก็รักษาความน่าเชื่อถือของการทดสอบ องค์กรบางแห่งแม้กระทั่งจัดหา fake versions ของบริการของตนให้ทีมอื่นใช้ในการทดสอบการรวมส่วน
ใช้ object จริงเมื่อเป็นไปได้ ถ้าไม่ได้ก็ใช้ fakes มิฉะนั้นใช้ mocks เฉพาะเมื่อจำเป็นในสถานการณ์พิเศษเท่านั้น
แนวทางอีกแบบหนึ่งเกี่ยวข้องกับการทดสอบหน่วยอัตโนมัติสำหรับ components ที่มีตรรกะซับซ้อน เช่น parsers หรือ algorithms ซึ่งนักพัฒนาเขียนการทดสอบแยกส่วนโดยธรรมชาติเพราะมันง่ายกว่าในการตรวจสอบพฤติกรรมที่ซับซ้อนแบบแยกส่วน
การเปรียบเทียบแนวทางการทดสอบ
แนวทาง | ข้อดี | ข้อเสีย | กรณีการใช้งานที่เหมาะสม |
---|---|---|---|
Mock ทุกอย่าง | รันเร็ว, แยกส่วนได้สมบูรณ์ | ความมั่นใจที่ผิดพลาด, การทดสอบที่เปราะบาง, การตั้งค่าที่ซับซ้อน | การทดสอบ unit logic แบบง่าย |
High-Fidelity Fakes | การ debug ที่ดีกว่า, พฤติกรรมที่เหมือนจริงมากขึ้น | ต้องการการตั้งค่ามากขึ้น | การทดสอบการรวม service |
Real Dependencies | จับการเปลี่ยนแปลงที่ทำให้เสียหายจริงได้ | ช้ากว่า, เปราะบางมากขึ้น | การตรวจสอบแบบ end-to-end |
Wrapper Pattern | business logic ที่สะอาด, การควบคุม mocking | ชั้น abstraction เพิ่มเติม | third-party APIs ที่ซับซ้อน |
บริบทที่กว้างขึ้น
การถกเถียงนี้สะท้อนการเปลี่ยนแปลงที่ใหญ่กว่าในปรัชญาการทดสอบภายในชุมชนนักพัฒนาซอฟต์แวร์ นักพัฒนาที่มีประสบการณ์หลายคนกำลังเปลี่ยนจากการจัดหมวดหมู่การทดสอบแบบเคร่งครัด โดยเน้นไปที่แนวทางปฏิบัติที่จับปัญหาจริงได้ขณะเดียวกันก็ดูแลรักษาได้
การอภิปรายยังเน้นย้ำความท้าทายที่ยังคงมีอยู่ในภาษาเช่น Java ซึ่งนักพัฒนาอาวุโสบางคนยังคงยืนยันในการแยกส่วนอย่างสมบูรณ์ผ่าน mocking แม้ในบริบท functional programming ที่แนวทางดังกล่าวอาจไม่เหมาะสม
ฉันทามติของชุมชนดูเหมือนจะพัฒนาไปสู่กลยุทธ์การทดสอบที่เป็นจริงมากขึ้น ซึ่งสร้างสมดุลระหว่างการแยกส่วนกับการรวมส่วน โดยให้ความสำคัญกับการตรวจจับความล้มเหลวในโลกจริงมากกว่าการยึดมั่นในหลักการทดสอบที่เคร่งครัด