ฉันมีโครงร่างการใช้งานเช่นเดียวกับข้อ 18 จาก Effective Java (การอภิปรายเพิ่มเติมที่นี่ ) มันเป็นคลาสนามธรรมที่มีวิธีการสาธารณะ 2 วิธี methodA () และ methodB () ที่เรียกวิธีการ subclasses เพื่อ "เติมช่องว่าง" ที่ฉันไม่สามารถกำหนดในลักษณะที่เป็นนามธรรม
ฉันพัฒนาก่อนโดยการสร้างคลาสที่เป็นรูปธรรมและเขียนการทดสอบหน่วยสำหรับมัน เมื่อชั้นสองมาฉันสามารถแยกพฤติกรรมทั่วไปใช้ "ช่องว่างที่หายไป" ในชั้นสองและมันก็พร้อม (แน่นอนการทดสอบหน่วยถูกสร้างขึ้นสำหรับคลาสย่อยที่สอง)
เวลาผ่านไปและตอนนี้ฉันมี 4 คลาสย่อยแต่ละการใช้งาน 3 วิธีการป้องกันแบบสั้นที่เฉพาะเจาะจงกับการใช้งานที่เป็นรูปธรรมของพวกเขาในขณะที่การใช้โครงร่างทำหน้าที่ทั่วไปทั้งหมด
ปัญหาของฉันคือเมื่อฉันสร้างการใช้งานใหม่ฉันเขียนการทดสอบอีกครั้ง:
- คลาสย่อยเรียกวิธีตามที่กำหนดหรือไม่?
- วิธีการที่กำหนดมีคำอธิบายประกอบที่กำหนดหรือไม่
- ฉันจะได้รับผลลัพธ์ที่คาดหวังจากวิธีการ A หรือไม่
- ฉันจะได้รับผลลัพธ์ที่คาดหวังจากวิธีการ B หรือไม่
ในขณะที่เห็นข้อดีด้วยวิธีนี้:
- เป็นเอกสารข้อกำหนดของคลาสย่อยผ่านการทดสอบ
- มันอาจล้มเหลวอย่างรวดเร็วในกรณีที่มีการปรับโครงสร้างที่มีปัญหา
- ทดสอบคลาสย่อยโดยรวมและสาธารณะ API ("methodA () ทำงานอย่างไร" และไม่ "วิธีนี้ได้รับการป้องกันหรือไม่")
ปัญหาที่ฉันมีคือการทดสอบสำหรับคลาสย่อยใหม่นั้นไม่ใช่เกมง่ายๆ: - การทดสอบนั้นเหมือนกันในคลาสย่อยทั้งหมดพวกเขาเพียงแค่เปลี่ยนประเภทการส่งคืนของเมธอด (การใช้โครงกระดูกเป็นเรื่องทั่วไป) และคุณสมบัติ ตรวจสอบส่วนยืนยันของการทดสอบ - โดยปกติคลาสย่อยไม่มีการทดสอบที่เฉพาะเจาะจงสำหรับพวกเขา
ฉันชอบวิธีการทดสอบที่มุ่งเน้นไปที่ผลของคลาสย่อยและปกป้องจากการปรับโครงสร้างใหม่ แต่ความจริงที่ว่าการดำเนินการทดสอบกลายเป็นเพียงแค่ "งานฝีมือ" ทำให้ฉันคิดว่าฉันทำอะไรผิดไป
ปัญหานี้เป็นเรื่องปกติหรือไม่เมื่อทำการทดสอบลำดับชั้น ฉันจะหลีกเลี่ยงสิ่งนั้นได้อย่างไร
ps: ฉันคิดเกี่ยวกับการทดสอบคลาสโครงกระดูก แต่มันก็ดูแปลก ๆ ที่สร้างการจำลองระดับนามธรรมขึ้นมาเพื่อทดสอบ และฉันคิดว่าการเปลี่ยนโครงสร้างในคลาสนามธรรมใด ๆ ที่เปลี่ยนพฤติกรรมที่ไม่ได้คาดหวังจากคลาสย่อยจะไม่ถูกสังเกตอย่างรวดเร็ว ความกล้าของฉันบอกฉันว่าการทดสอบคลาสย่อย "โดยรวม" เป็นวิธีการที่ต้องการ แต่โปรดบอกฉันว่าฉันผิด :)
ps2: ฉัน googled และพบคำถามมากมายเกี่ยวกับเรื่องนี้ หนึ่งในนั้นคืออันนี้ซึ่งมีคำตอบที่ดีจาก Nigel Thorne กรณีของฉันคือ "หมายเลข 1" ของเขา นั่นจะดี แต่ฉันไม่สามารถ refactor ณ จุดนี้ดังนั้นฉันจะต้องอยู่กับปัญหานี้ ถ้าฉันสามารถ refactor ฉันจะมีคลาสย่อยเป็นกลยุทธ์ นั่นจะเป็นเรื่องปกติ แต่ฉันจะยังคงทดสอบ "คลาสหลัก" และทดสอบกลยุทธ์ แต่ฉันจะไม่สังเกตเห็นการปรับโครงสร้างใด ๆ ที่ทำให้การรวมกลุ่มระหว่างคลาสหลักและกลยุทธ์แตก
ps3: ฉันพบคำตอบที่บอกว่า "เป็นที่ยอมรับ" เพื่อทดสอบระดับนามธรรม ฉันยอมรับว่านี่เป็นสิ่งที่ยอมรับได้ แต่ฉันต้องการที่จะรู้ว่าวิธีใดที่เป็นที่ต้องการในกรณีนี้ (ฉันยังคงเริ่มต้นด้วยการทดสอบหน่วย)