การเขียนการทดสอบสำหรับรหัสที่ฉันไม่เข้าใจ


59

ฉันเพิ่งเสร็จสิ้นการปรับโครงสร้างกล่องดำ ฉันไม่สามารถเช็คอินได้เพราะฉันไม่สามารถทดสอบวิธีการได้

ในระดับสูงฉันมีคลาสที่การกำหนดค่าเริ่มต้นเกี่ยวข้องกับการคว้าค่าจากคลาส B บางคลาสถ้า "ว่าง" จะสร้างค่าเริ่มต้นที่สมเหตุสมผล ฉันแยกส่วนนี้เป็นวิธีการเริ่มต้นคลาส B เป็นค่าเริ่มต้นเดียวกัน

ฉันยังไม่ได้ระบุวัตถุประสงค์ / บริบทของชั้นเรียนหรือวิธีการใช้ ดังนั้นฉันไม่สามารถเริ่มต้นวัตถุจากคลาส B ที่ว่างเปล่าและตรวจสอบว่ามันมีค่าที่ถูกต้อง / ทำสิ่งที่ถูกต้อง

ความคิดที่ดีที่สุดของฉันคือการเรียกใช้รหัสเดิมฮาร์ดโค้ดในผลลัพธ์ของวิธีการสาธารณะขึ้นอยู่กับสมาชิกเริ่มต้นและทดสอบรหัสใหม่กับที่ ฉันไม่สามารถพูดได้อย่างชัดเจนว่าทำไมฉันถึงรู้สึกไม่สบายใจกับความคิดนี้

มีการโจมตีที่ดีกว่าที่นี่ไหม?


28
ฉันรู้สึกเหมือนคุณเริ่มต้นในจุดจบที่ผิด ครั้งแรกที่คุณควรเข้าใจรหัสแล้วทดสอบมันแล้ว refactor ทำไมคุณถึงทำการเปลี่ยนโครงสร้างโดยไม่ทราบว่ารหัสนั้นมีไว้เพื่ออะไร?
Jacob Raihle

11
@JacobRaihle มันเป็นโปรแกรมที่ค่อนข้างพิเศษสำหรับผู้ที่มีองศาในสิ่งที่ฉันไม่เคยสัมผัส ฉันกำลังเก็บบริบทเมื่อฉันไป แต่มันไม่ง่ายเลยที่จะรอให้มีความเข้าใจที่มั่นคงก่อนที่ฉันจะเริ่ม
JETM

4
สิ่งที่ไม่สามารถนำไปใช้ได้จริงคือการเขียนสิ่งใหม่และเมื่อการเปลี่ยนแปลงกำลังเกิดขึ้นเราจะค้นพบสาเหตุที่คุณไม่ควรทำ หากคุณสามารถทดสอบได้อย่างละเอียดก่อนหน้านี้อาจเป็นวิธีที่ดีในการทำความรู้จักกับรหัสฐาน ถ้าไม่จำเป็นต้องเข้าใจก่อนเปลี่ยน
Jacob Raihle

37
มีการทดสอบประเภทหนึ่งที่เรียกว่าการทดสอบลักษณะเฉพาะเมื่อคุณต้องการทดสอบพฤติกรรมที่แท้จริงของระบบ คุณเพียงแค่ใช้ระบบดั้งเดิมของคุณจากนั้นเพิ่มการทดสอบที่ยืนยันสิ่งที่มันทำจริง (และไม่จำเป็นต้องเป็นสิ่งที่ตั้งใจจะทำ!) พวกเขาทำหน้าที่เป็นนั่งร้านรอบ ๆ ระบบของคุณซึ่งคุณสามารถปรับเปลี่ยนได้อย่างปลอดภัยเนื่องจากคุณสามารถมั่นใจได้ว่ามันยังคงทำงานได้
Vincent Savard

3
คุณไม่สามารถขอ / รับการตรวจสอบโดยคนที่ไม่เข้าใจหรือไม่
pjc50

คำตอบ:


122

คุณทำได้ดี!

การสร้างการทดสอบการถดถอยแบบอัตโนมัติมักจะเป็นสิ่งที่ดีที่สุดที่คุณสามารถทำได้เพื่อสร้างองค์ประกอบที่ปรับเปลี่ยนได้ อาจเป็นเรื่องที่น่าแปลกใจ แต่การทดสอบดังกล่าวมักเขียนได้โดยไม่ต้องเข้าใจอย่างถ่องแท้ว่าส่วนประกอบทำอะไรภายในตราบใดที่คุณเข้าใจอินเทอร์เฟซ "อินพุท" อินพุตและเอาท์พุต (ตามความหมายทั่วไปของคำนั้น) เราเคยทำเช่นนี้มาแล้วหลายครั้งในอดีตสำหรับแอปพลิเคชั่นที่ได้รับมรดกเต็มรูปแบบไม่เพียงแค่ในชั้นเรียนและบ่อยครั้งที่มันช่วยให้เราสามารถหลีกเลี่ยงสิ่งที่เราไม่เข้าใจ

อย่างไรก็ตามคุณควรมีข้อมูลทดสอบเพียงพอและให้แน่ใจว่าคุณเข้าใจอย่างถ่องแท้ว่าซอฟต์แวร์ทำอะไรจากมุมมองของผู้ใช้ขององค์ประกอบนั้นมิฉะนั้นคุณอาจเสี่ยงต่อการละเว้นกรณีทดสอบที่สำคัญ

IMHO เป็นความคิดที่ดีที่จะใช้การทดสอบอัตโนมัติของคุณก่อนที่คุณจะเริ่มการปรับโครงสร้างใหม่ไม่ใช่หลังจากนั้นคุณจึงสามารถทำการปรับโครงสร้างซ้ำในขั้นตอนเล็ก ๆ และตรวจสอบแต่ละขั้นตอน การปรับโครงสร้างตัวเองควรทำให้โค้ดอ่านได้ง่ายขึ้นดังนั้นมันจะช่วยให้คุณเพิ่มความเข้าใจเกี่ยวกับ internals ทีละนิด ดังนั้นขั้นตอนการสั่งซื้อในกระบวนการนี้คือ

  1. ทำความเข้าใจเกี่ยวกับรหัส "จากภายนอก"
  2. เขียนการทดสอบการถดถอย
  3. refactor ซึ่งนำไปสู่ความเข้าใจที่ดีขึ้นของ internals ของรหัส

21
คำตอบที่สมบูรณ์แบบตามที่อธิบายไว้ในหนังสือ "การทำงานกับรหัสมรดก"
Altoyr

ฉันต้องทำอะไรแบบนี้ซักครั้ง รวบรวมข้อมูลเอาต์พุตทั่วไปจากแอปพลิเคชันก่อนที่ฉันจะแก้ไขจากนั้นตรวจสอบแอปพลิเคชันเวอร์ชันใหม่ของฉันโดยเรียกใช้ข้อมูลทดสอบเดียวกันผ่านทางแอปพลิเคชัน 30 ปีที่แล้ว ... Fortran ... มันเป็นเรื่องของการประมวลผลภาพ / การแมปบางอย่างดังนั้นฉันไม่รู้จริงๆว่าผลผลิต 'ควร' คืออะไรโดยดูจากมันหรือเขียนเคสทดสอบ และฉันก็ทำมันบนหน้าจอ Tektronix (ถาวร) งานรัฐบาล ...

4
หนึ่งอาจเพิ่มคุณยังสามารถเขียนการทดสอบของคุณสำหรับรหัสเก่าหลังจากข้อเท็จจริง จากนั้นคุณสามารถลองพวกเขาในเวอร์ชันที่ได้รับการปรับปรุงใหม่ของคุณและถ้าเกิดว่าหยุดพักให้ทำการค้นหาแบบแบ่งสองส่วนจากประวัติการกระทำของคุณเพื่อค้นหาจุดที่มันเริ่มแตกหัก
CodeMonkey

2
ฉันขอแนะนำให้ทำอย่างอื่นอีก ขณะรวบรวมข้อมูลทดสอบให้รวบรวมสถิติการครอบคลุมรหัสถ้าเป็นไปได้ คุณจะรู้ว่าข้อมูลทดสอบของคุณอธิบายรหัสที่เป็นปัญหาได้ดีเพียงใด
liori

2
@nocomprende เป็นเรื่องตลกที่ฉันได้ทำสิ่งที่แน่นอนด้วยรหัสทางวิทยาศาสตร์ fortran 77 รหัสเมื่อสัปดาห์ที่แล้ว เพิ่มการพิมพ์ข้อมูล ascii ลงในไฟล์ตั้งค่าไดเรกทอรีทดสอบด้วยอินพุตและเอาต์พุตที่คาดหวังและกรณีทดสอบของฉันนั้นแตกต่างจากเอาต์พุตสองชุด หากพวกเขาไม่ตรงกับตัวละครสำหรับตัวละครฉันทำลายอะไรบางอย่าง เมื่อรหัสส่วนใหญ่เป็นสองรูทีนย่อยที่แต่ละโลเคชั่น 2-3k คุณต้องเริ่มต้นที่ไหนสักแห่ง
Godric Seer

1

เหตุผลสำคัญสำหรับการเขียนการทดสอบหน่วยก็คือพวกเขาเอกสารส่วนประกอบ API อย่างใด การไม่เข้าใจวัตถุประสงค์ของรหัสภายใต้การทดสอบเป็นปัญหาที่นี่จริงๆ การครอบคลุมรหัสเป็นเป้าหมายสำคัญอีกประการหนึ่งยากที่จะบรรลุโดยไม่ทราบว่ามีสาขาการดำเนินการใดอยู่บ้างและถูกกระตุ้นอย่างไร

อย่างไรก็ตามหากมีความเป็นไปได้ที่จะรีเซ็ตสถานะให้หมดจด (หรือสร้างวัตถุทดสอบใหม่ทุกครั้ง) หนึ่งอาจเขียนการทดสอบประเภท "ถังขยะในถังขยะ" ที่เพียงป้อนอินพุตสุ่มไปยังระบบและสังเกตผลลัพธ์

การทดสอบดังกล่าวนั้นยากต่อการบำรุงรักษาเช่นเมื่อพวกเขาล้มเหลวมันอาจซับซ้อนที่จะบอกว่าทำไมและรุนแรงแค่ไหน ความครอบคลุมอาจมีข้อสงสัย อย่างไรก็ตามพวกเขายังดีกว่าไม่มีอะไรมาก เมื่อการทดสอบดังกล่าวล้มเหลวผู้พัฒนาสามารถแก้ไขการเปลี่ยนแปลงล่าสุดพร้อมความสนใจมากขึ้นและหวังว่าจะพบจุดบกพร่องที่นั่น


1
ข้อมูลชนิดใดก็ดีกว่าการมองไม่เห็น ฉันใช้เพื่อค้นหาข้อผิดพลาดในโปรแกรมเซิร์ฟเวอร์ที่อยู่ระหว่างการผลิตโดยเรียกใช้ดีบักเกอร์ในไฟล์ crash dump (Unix) และขอ stack trace มันให้ชื่อของฟังก์ชั่นที่เกิดความผิดพลาด แม้ว่าจะไม่มีความรู้อื่น ๆ (ฉันไม่รู้ว่าจะใช้ดีบักเกอร์นี้ได้อย่างไร) แต่ก็ช่วยได้ในสิ่งที่จะเป็นสถานการณ์ที่ลึกลับและไม่สามารถพิสูจน์ได้
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.