ทำไม TDD ถึงทำงาน [ปิด]


92

วันนี้การพัฒนาที่ขับเคลื่อนด้วยการทดสอบ (TDD)มีขนาดใหญ่ ฉันมักจะเห็นว่าแนะนำเป็นวิธีแก้ปัญหาที่หลากหลายในโปรแกรมเมอร์ SE และสถานที่อื่น ๆ ฉันสงสัยว่าทำไมมันถึงได้ผล

จากมุมมองทางวิศวกรรมมันทำให้ฉันไขปริศนาด้วยเหตุผลสองประการ:

  1. วิธีการ "เขียนการทดสอบ + การปรับปรุงซ้ำจนผ่าน" มีลักษณะต่อต้านวิศวกรรมอย่างไม่น่าเชื่อ หากวิศวกรโยธาใช้วิธีการก่อสร้างสะพานหรือนักออกแบบรถยนต์สำหรับรถยนต์ของพวกเขาพวกเขาจะปรับเปลี่ยนสะพานหรือรถยนต์ในราคาที่สูงมากและผลที่ได้จะเป็นปัญหาที่ปะปนกับสถาปัตยกรรมที่ไม่คิด . แนวทาง "refactor จนถึงผ่าน" มักถูกนำมาใช้เป็นคำสั่งให้ลืมการออกแบบสถาปัตยกรรมและทำสิ่งที่จำเป็นเพื่อให้สอดคล้องกับการทดสอบ; กล่าวอีกนัยหนึ่งการทดสอบแทนผู้ใช้กำหนดข้อกำหนด ในสถานการณ์เช่นนี้เราจะรับประกัน "ความสามารถ" ที่ดีในผลลัพธ์ได้อย่างไรเช่นผลลัพธ์สุดท้ายที่ไม่เพียง แต่ถูกต้อง แต่ยังขยายได้แข็งแกร่งใช้งานง่ายเชื่อถือได้ปลอดภัยปลอดภัย ฯลฯ นี่คือสิ่งที่สถาปัตยกรรมมักจะทำ
  2. การทดสอบไม่สามารถรับประกันได้ว่าระบบทำงานได้; มันสามารถแสดงให้เห็นว่ามันไม่ได้ กล่าวอีกนัยหนึ่งการทดสอบอาจแสดงให้คุณเห็นว่าระบบมีข้อบกพร่องหากการทดสอบล้มเหลว แต่ระบบที่ผ่านการทดสอบทั้งหมดนั้นไม่ปลอดภัยกว่าระบบที่ล้มเหลว การครอบคลุมการทดสอบคุณภาพการทดสอบและปัจจัยอื่น ๆ มีความสำคัญที่นี่ ความรู้สึกปลอดภัยที่ผิด ๆ ที่ผลลัพธ์ "สีเขียวทั้งหมด" ก่อให้เกิดกับคนจำนวนมากได้รับการรายงานในอุตสาหกรรมโยธาและการบินและอวกาศว่าเป็นอันตรายอย่างยิ่งเพราะมันอาจถูก interepreted เป็น "ระบบไม่ดี" เมื่อมันหมายถึง "ระบบดี เป็นกลยุทธ์การทดสอบของเรา " บ่อยครั้งที่กลยุทธ์การทดสอบไม่ได้รับการตรวจสอบ หรือใครเป็นคนทดสอบการทดสอบ?

โดยสรุปฉันกังวลเกี่ยวกับบิต "ที่ขับเคลื่อน" ใน TDD มากกว่าบิต "ทดสอบ" การทดสอบก็โอเคอย่างสมบูรณ์ สิ่งที่ฉันไม่ได้รับคือการผลักดันการออกแบบโดยการทำมัน

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


53
สะพานรถยนต์และการออกแบบทางกายภาพอื่น ๆ นั้นไม่ได้มีความละเอียดอ่อนเท่าซอฟต์แวร์ นี่คือความแตกต่างที่สำคัญและหมายความว่าการเปรียบเทียบระหว่างซอฟต์แวร์และวิศวกรรมจริงไม่ได้เกี่ยวข้องกันเสมอไป การทำงานกับบริดจ์อาจไม่ทำงานกับซอฟต์แวร์และในทางกลับกัน
Lars Wirzenius

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

2
@ 6502: โดยทั้งหมด! TDD ไม่ใช่ bullet เงินและจะไม่แก้ปัญหาทั้งหมดที่เกิดขึ้นระหว่างการพัฒนาซอฟต์แวร์ อย่างไรก็ตามเป็นวิธีที่มีประโยชน์ในการจัดการเวิร์กโฟลว์ ตัวอย่างเช่นคุณสามารถกำหนดข้อกำหนดที่ทุกกรณีชายแดนได้รับการคุ้มครองโดยการทดสอบ คุณยังจำเป็นต้องรู้ว่ากรณีเส้นขอบเหล่านี้คืออะไร แต่ตอนนี้คุณมีเครื่องมือเพื่อตรวจสอบว่ารหัสของคุณเกี่ยวข้องกับพวกเขาอย่างถูกต้องหรือไม่
Mchl

2
@ CesarGon คุณอาจสนใจในคำถามนี้ฉันถามดังนั้นเมื่อไม่นานมานี้ ... ไม่ได้ค่อนข้าง TDD แต่ที่เกี่ยวข้อง ... บางคำตอบ enlightening ที่นั่น
AviD

6
ช่างน่าทึ่งจริงๆที่วิศวกรรมโยธา / ซอฟแวร์อะนาล็อกพัฒนาไม่ได้ ในบรรทัดเดียวกันฉันมักจะสังเกตเห็นว่าฉันไม่สามารถทำแพนเค้กแบบเดียวกับที่ฉันตัดหญ้าได้

คำตอบ:


66

ฉันคิดว่ามีความเข้าใจผิดอยู่ที่นี่ ในการออกแบบซอฟต์แวร์การออกแบบนั้นใกล้กับผลิตภัณฑ์มาก ในงานวิศวกรรมโยธาสถาปัตยกรรมการออกแบบแยกออกจากผลิตภัณฑ์จริง: มีพิมพ์เขียวที่เก็บการออกแบบจากนั้นปรากฏเป็นผลิตภัณฑ์สำเร็จรูปและแยกจากกันโดยใช้เวลาและความพยายามเป็นจำนวนมาก

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

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

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

นี่คือทุกสิ่งที่คุณสามารถใช้กับ TDD

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

สำหรับการฝึกฝนของ TDD นั้นเป็นเรื่องของการทรงตัว ค่าใช้จ่ายในการดำเนินการทางเดียว (ตัวอย่างเช่นไม่ใช่การทดสอบแล้วหยิบชิ้นส่วนในภายหลัง) เมื่อเทียบกับค่าใช้จ่ายในการทำอีกวิธีหนึ่ง มันเป็นความสมดุลเสมอ แต่อย่าคิดว่ากระบวนการออกแบบอื่นไม่มีการทดสอบและ TDD


7
+1 สำหรับการพูดคุยเกี่ยวกับการทดสอบที่เกิดขึ้นในการผลิต จุดที่ดี
อดัมเลียร์

11
คุณบอกว่า "ชิ้นส่วนผ่านการทดสอบ" แน่นอน แต่ไม่ใช่การออกแบบทดสอบ ส่วนของเครื่องบินไม่ได้ถูกออกแบบมาในรูปแบบของการทดสอบ แต่ในรูปแบบของสถาปัตยกรรมขนาดใหญ่ ความคล้ายคลึงกับ TDD ไม่มีอยู่ที่นี่
CesarGon

3
การเพิ่มเข้าไปในนั้น: TDD คือในความคิดของฉันส่วนใหญ่เกี่ยวกับวิธีการเพื่อให้แน่ใจว่าคุณสามารถตรวจสอบชิ้นส่วนแทนที่จะเป็น 'ทั้งหมดหรือไม่มีอะไร' ที่ใหญ่ในตอนท้าย แต่ adagium ของ TDD 'สร้างการทดสอบครั้งแรก' ไม่ได้หมายถึงการ 'ทำการทดสอบก่อนที่คุณจะคิดเกี่ยวกับสิ่งที่คุณต้องการที่จะบรรลุ' เพราะความคิดของการทดสอบเป็นส่วนหนึ่งของการออกแบบ การระบุสิ่งที่คุณต้องการให้ส่วนที่แน่นอนที่จะทำคือการออกแบบ ก่อนที่คุณจะเริ่มพิมพ์คุณได้ทำการออกแบบเสร็จแล้ว (ด้วยวิธีนี้ฉันคิดว่าคำว่า 'การออกแบบที่ขับเคลื่อนด้วยการทดสอบ' นั้นหมายถึงการเข้าใจผิดทางบนทางเดินซึ่งเป็นวงข้อเสนอแนะจริงๆ)
Inca

2
+1: ซอฟต์แวร์ได้รับการออกแบบอย่างหมดจด การเปรียบเทียบสะพานในคำถามนั้นผิดทั้งหมด TDD ใช้กับการทดสอบหน่วยภายนอกโดยสิ้นเชิง การออกแบบที่ขับเคลื่อนด้วยการทดสอบนั้นใช้กับการออกแบบทุกชั้น
S.Lott

3
@CesarGon: ไม่ TDD กำลังผลักดันการพัฒนาโดยการทดสอบ มันต่างกับการออกแบบ การออกแบบกำหนดวิธีการที่คุณจะใช้ระบบและดังนั้นการทดสอบใดที่คุณต้องใช้เพื่อทำซ้ำพฤติกรรมนั้น การใช้การทดสอบเหล่านั้นมักจะช่วยให้คุณปรับแต่งการออกแบบ
deworde

26

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

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

Peter Norvig อธิบายมุมมองของเขาต่อ TDD ในหนังสือ Coders At Work

Seibel: แล้วแนวคิดเกี่ยวกับการใช้การทดสอบเพื่อออกแบบไดรฟ์ล่ะ?

Norvig: ฉันเห็นการทดสอบเป็นวิธีการแก้ไขข้อผิดพลาดมากกว่าเป็นวิธีการออกแบบ วิธีการสุดโต่งของการพูดว่า“ เอาล่ะสิ่งแรกที่คุณทำคือเขียนข้อสอบที่บอกว่าฉันได้คำตอบที่ถูกต้องในตอนท้าย” จากนั้นคุณก็รันมันแล้วเห็นว่ามันล้มเหลวแล้วคุณก็พูดว่า ต้องการต่อไปหรือไม่” - มันไม่เหมือนวิธีที่ถูกต้องในการออกแบบบางอย่างให้ฉัน ดูเหมือนว่าจะเป็นเรื่องง่ายหากการแก้ปัญหานั้นถูกกำหนดไว้ล่วงหน้าแล้วก็จะเหมาะสม ฉันคิดว่าคุณต้องคิดก่อน คุณต้องพูดว่า“ อะไรกันนะ? ฉันจะเขียนการทดสอบเป็นชิ้น ๆ ได้อย่างไรจนกว่าฉันจะรู้ว่าพวกเขาบางคนเป็นอย่างไร” จากนั้นเมื่อคุณทำเช่นนั้นแล้วมันก็เป็นระเบียบวินัยที่ดีที่จะมีการทดสอบสำหรับแต่ละชิ้นส่วนเหล่านั้น และกรณีขอบเขตและอื่น ๆ สิ่งเหล่านั้นควรมีการทดสอบ แต่ฉันไม่คิดว่าคุณจะผลักดันการออกแบบทั้งหมดโดยพูดว่า“ การทดสอบนี้ล้มเหลว”


7
ตอนนี้ถ้าคุณบอกข้อเท็จจริงเหล่านี้ต่อผู้คนและที่ปรึกษาของ TDD คำตอบที่คุณจะได้รับคือwell, you haven't done TDD right!
Navaneeth KN

10
และพวกเขาจะถูกต้อง เรากำลังทำ BDD / TDD บนระบบเสียงที่สูงมากและมันก็ทำงานได้ดี การทดสอบจะมีเพื่อบอกคุณว่าคุณทำลายพฤติกรรมที่คาดหวัง หากคุณกำลังจะไปและเปลี่ยนแปลงสิ่งนี้ในภายหลัง "ทำลาย" การทดสอบคุณกำลังทำสิ่งที่ผิด การทดสอบควรมีการเปลี่ยนแปลงก่อนเพื่อหาพฤติกรรมใหม่ของระบบจากนั้นคุณเปลี่ยน และใช่ถ้าคุณทำถูกต้องคุณเขียนการทดสอบของคุณที่เริ่มต้นด้วย "สิ่งนี้ต้องทำอะไร" และขั้นตอนการเขียนการทดสอบจะช่วยให้คุณคิดว่า "ไอทีต้องทำงานอะไร" อ๋อและไม่เคยใช้ที่ปรึกษาเลย ...
Andy

4
การทดสอบจำนวนมากไม่ได้ยกเว้นคุณจากการสร้างการออกแบบที่เหมาะสม การออกแบบที่มีความเชื่อมโยงสูงโดยไม่คำนึงว่าจะมีการทดสอบกี่รอบและจะเปราะบางเสมอ การทดสอบแบบฝังในการออกแบบนี้สามารถทำให้ทุกอย่างแย่ลงได้
Newtopian

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

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

25

การออกแบบการทดสอบที่ขับเคลื่อนได้สำหรับฉันด้วยเหตุผลดังต่อไปนี้:

มันเป็นรูปแบบของสเปคที่รันได้

นี่หมายความว่าคุณสามารถเห็นได้จากกรณีทดสอบ:

  1. ว่ารหัสที่ถูกเรียกว่าเต็มข้อมูลจำเพาะตามผลที่คาดว่าจะมีในกรณีทดสอบ การตรวจสอบด้วยภาพ (ซึ่งคาดว่ากรณีทดสอบจะผ่านไป) สามารถพูดได้ทันที "โอ้การทดสอบนี้ตรวจสอบว่าการเรียกใบแจ้งหนี้ บริษัท ที่กำหนดในสถานการณ์นี้ควรมีผลลัพธ์นั้น"
  2. HOWรหัสควรจะเรียกว่า ขั้นตอนจริงที่จำเป็นในการทำการทดสอบนั้นมีการระบุโดยตรงโดยไม่ต้องนั่งร้านภายนอก (ฐานข้อมูลถูกเยาะเย้ยออก ฯลฯ )

คุณเขียนมุมมองจากภายนอกก่อน

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

ซึ่งมักจะส่งผลให้รหัสทำความสะอาดด้วยซึ่งต้องใช้เอกสารอธิบายที่น้อยกว่า

คุณทำได้เร็วขึ้น

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

ซึ่งหมายความว่าคุณสามารถบอกได้ว่าเมื่อใดที่จำเป็นต้องทำงานหรือไม่ (ช่วยให้ผ่านการทดสอบ) คุณต้องจบลงด้วยการทำน้อยลง

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

การศึกษาล่าสุด

"ผลจากกรณีศึกษาระบุว่าความหนาแน่นข้อบกพร่องก่อนวางจำหน่ายของทั้งสี่ผลิตภัณฑ์ลดลงระหว่าง 40% และ 90% เมื่อเทียบกับโครงการที่คล้ายกันที่ไม่ได้ใช้การฝึก TDD ในทางปฏิบัติทีมพบว่าเพิ่มขึ้น 15 ถึง 35% เวลาในการพัฒนาเริ่มต้นหลังจากใช้ TDD " ~ ผลลัพธ์และประสบการณ์ของ 4 ทีมอุตสาหกรรม


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

นี่ควรเป็นคำตอบที่ยอมรับได้
Niing

19

กระบวนการสร้างซอฟต์แวร์ไม่ใช่กระบวนการเขียนรหัส ไม่ควรเริ่มโครงการซอฟต์แวร์โดยไม่มีแผน 'ขอบเขตกว้าง' ก่อน เช่นเดียวกับโครงการการเชื่อมสองชายฝั่งของแม่น้ำจำเป็นต้องมีแผนดังกล่าวก่อน

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

ในวิศวกรรมโครงสร้างมันมีลักษณะดังนี้:

'เรามีโลหะสองชิ้นเชื่อมต่อกันและการเชื่อมต่อจำเป็นต้องรักษากำลังเฉือนตามลำดับของ x ลองทดสอบวิธีการเชื่อมต่อที่ดีที่สุดในการทำเช่นนี้ '

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

ดู V-Model: http://en.wikipedia.org/wiki/V-Model_%28software_development%29

เรามาดูกันว่ามันจะทำงานกับสะพานอย่างไร:

  1. รัฐบาลท้องถิ่นกล่าวกับ บริษัท สร้างสะพาน: "เราต้องการสะพานเชื่อมต่อสองจุดนี้สะพานจะต้องสามารถให้ปริมาณการจราจร n ต่อชั่วโมงและพร้อมสำหรับวันที่ 21 ธันวาคม 2012 '- นี่คือคำจำกัดความของ การทดสอบการยอมรับ บริษัท จะไม่ได้รับเงินเต็มจำนวน (หรือใด ๆ ) หากพวกเขาไม่สามารถผ่านการทดสอบนั้นได้

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

  3. ภายในทีมที่รับผิดชอบในการออกแบบส่วนประกอบบริดจ์โดยเฉพาะดูเหมือนว่าในตัวอย่างที่ฉันได้ให้ไว้ข้างต้น บางครั้งวิธีแก้ปัญหานั้นชัดเจนเพราะเรามีองค์ความรู้จำนวนมากเกี่ยวกับการสร้างบริดจ์ (มันเหมือนกับการใช้ห้องสมุดที่ได้รับการทดสอบมาอย่างดีในการพัฒนาซอฟต์แวร์ - คุณแค่คิดว่ามันใช้งานได้ตามโฆษณา) บางครั้งคุณจำเป็นต้องสร้างการออกแบบที่หลากหลายและทดสอบเพื่อเลือกสิ่งที่ดีที่สุด แต่ถึงกระนั้นเกณฑ์ที่ใช้ในการทดสอบส่วนประกอบจะทราบล่วงหน้า


ถ้าฉันเข้าใจคุณอย่างถูกต้องคุณกำลังบอกว่า TDD นั้นใช้ได้ตราบใดที่ (a) ใช้สำหรับการทดสอบหน่วยเท่านั้นและ (b) มันมาพร้อมกับวิธีการทดสอบอื่น ๆ เช่นกัน ถ้าเป็นกรณีนี้มันอาจจะอยู่หมายเลข 2 ใน OP คุณจะระบุที่อยู่จุดที่ 1 ได้อย่างไร
CesarGon

@CesarGon: TDD ยังใช้งานได้ดีสำหรับการทดสอบการรวม
sevenseacat

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

@Karpie: และสำหรับการทดสอบการยอมรับด้วย! คุณควรทราบล่วงหน้าว่าสิ่งใดที่ลูกค้าต้องการเพื่อให้งานของคุณได้รับการยอมรับ
Mchl

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

18

ในความคิดของฉัน TDD ทำงานเพราะ

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

โดยเฉพาะในจุดที่คุณยก

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

3
คุณควรเพิ่มว่าเป็นข้อบกพร่องที่ค้นพบคุณสามารถมั่นใจได้ว่าพวกเขาจะไม่ทำซ้ำในขณะที่คุณเพิ่มการทดสอบอื่น
แอนดี้

16

TL; DR

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

รหัสคือการออกแบบ

ในบทที่ 7 ของPPP "ลุงบ๊อบ" พูดถึงปัญหานี้โดยตรง ในบทแรก ๆ เขาอ้างอิงบทความที่ยอดเยี่ยมของ Jack Reeves ซึ่งเขาเสนอว่าโค้ดนั้นออกแบบ (ลิงก์ไปที่หน้าที่รวบรวมบทความทั้งสามของเขาในหัวข้อ)

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

TDD ตามข้อกำหนด

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

เขียนการทดสอบการใช้งาน

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

public class PersonTest:Test
{
   [Test]
   TestNameProperty()
   {
      var person=new Person();
      person.Name="John Doe";
      Assert.AreEqual("John Doe", person.Name);
   }
}

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

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

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

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


4
ค่าของการทดสอบการจับข้อบกพร่องสีแดงเป็นคุณลักษณะของการทดสอบหน่วยโดยทั่วไปไม่ใช่ TDD โดยเฉพาะ
Robert Harvey

2
คุณมาถูกที่แล้ว แต่โอกาสที่ฉันจะมีข้อผิดพลาดที่เฉพาะเจาะจงที่ครอบคลุมกับการทดสอบหน่วยโพสต์เฉพาะกิจต่ำ
Michael Brown

1
คุณสามารถสนับสนุนข้อเรียกร้องที่มีหลักฐานข้อมูลหรือการวิเคราะห์ที่มั่นคงหรือไม่?
CesarGon

1
@CesarGon การศึกษานี้ในขณะที่โปรแกรมเมอร์กำลังทำงานในโครงการขนาดเล็กแสดงให้เห็นว่านักพัฒนาที่ใช้รหัส TDD ผลิตด้วยความคุ้มครองการทดสอบที่ดีกว่าการทดสอบหลังจากข้อเท็จจริง (92% -98% เทียบกับ 80% -90%) และจับมากขึ้น ข้อบกพร่องระหว่างการพัฒนา (พบข้อบกพร่องน้อยลง 18% ในรหัสที่ผลิตโดยใช้ TDD)
จูลส์

11

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

คุณจะไม่พบใครที่ไม่ชอบหรือไม่ประทับใจกับ TDD ที่บอกว่าการทดสอบเสียเวลาและความพยายาม แม้ว่าการทดสอบจะไม่ได้พิสูจน์ว่าแอปพลิเคชันมีประโยชน์มากในการค้นหาข้อผิดพลาด

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

ดังนั้นความแตกต่างระหว่าง TDD และไม่ใช่ TDD ไม่ใช่ว่าการทดสอบกำลังทำอยู่ ความแตกต่างคือเมื่อมีการเขียนการทดสอบ ในการทดสอบ TDD ถูกเขียนขึ้นก่อนซอฟต์แวร์ ในการทดสอบที่ไม่ใช่ TDD ถูกเขียนขึ้นหลังจากหรือในคอนเสิร์ตพร้อมกับซอฟต์แวร์

ปัญหาที่ฉันเห็นในเรื่องหลังคือการทดสอบนั้นมีแนวโน้มที่จะกำหนดเป้าหมายซอฟต์แวร์ที่กำลังเขียนมากกว่าผลลัพธ์หรือข้อกำหนดที่ต้องการ แม้ว่าทีมทดสอบจะแยกออกจากทีมพัฒนาทีมทดสอบก็มีแนวโน้มที่จะดูซอฟต์แวร์เล่นกับมันและเขียนแบบทดสอบที่กำหนดเป้าหมาย

สิ่งหนึ่งที่ถูกสังเกตเห็นครั้งแล้วครั้งเล่าโดยผู้ที่ศึกษาความสำเร็จของโครงการคือความถี่ที่ลูกค้าจะจัดวางสิ่งที่พวกเขาต้องการคนพัฒนาวิ่งออกไปและเขียนอะไรบางอย่างและเมื่อพวกเขากลับมาที่ลูกค้าพูดว่า "เสร็จสิ้น" ปรากฎว่าเป็นสิ่งที่ลูกค้าร้องขออย่างเต็มที่และไม่สมบูรณ์ "แต่มันผ่านการทดสอบทั้งหมด ... "

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

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

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


+1 ขอบคุณสำหรับคำตอบที่ครอบคลุมโนอาห์ ฉันเห็นด้วยว่าความแตกต่างที่สำคัญระหว่าง TDD และไม่ใช่ -DDD คือเมื่อมีการเขียนการทดสอบ อย่างไรก็ตามฉันยังคิดด้วยว่า "D" ตัวแรกใน TDD นั้นหมายถึง "ตัวขับเคลื่อน" ซึ่งหมายความว่าใน TDD การพัฒนาทั้งหมดนั้นมาจากการทดสอบ นั่นคือสิ่งที่ฉันพบว่าทำให้งงที่สุด ฉันไม่มีปัญหากับการทดสอบการเขียนก่อนสร้างสิ่งที่จะต้องทดสอบ แต่ให้ทดสอบขับ มันแตกต่างจากไฟเขียวที่จะทำอะไรตราบใดที่ผิวเผิน (เช่นผลลัพธ์) นั้นดี?
CesarGon

ซีซาร์คุณจะเสนออะไรเป็นเกณฑ์ที่ดีกว่าสำหรับวัตถุประสงค์ในการตัดสินใจเมื่องานการพัฒนาเสร็จสิ้น หากราวกับว่าเป็นใน TDD การทดสอบนั้นเป็นสเป็คที่นักพัฒนาเป้าหมายกำหนดไว้ดังนั้นผู้พัฒนาได้ทำงานของพวกเขาเมื่อการทดสอบผ่านไปไม่ใช่หรือ? ใช่อาจมีข้อบกพร่องในการทดสอบเหมือนมีข้อบกพร่องในสเปคใด ๆ นั่นไม่ใช่งานของนักพัฒนาที่จะต้องแก้ไข หากการทดสอบมีข้อบกพร่องก็จะได้รับการแก้ไขจากนั้นการพัฒนากำหนดเป้าหมายเป้าหมายใหม่และเมื่อมันเป็นสีเขียวทั้งหมดพวกเขาจะทำ มันใช้งานได้เพราะมีการทดสอบเสมอที่จะผ่าน ... ไม่มีขนปุยที่พิเศษและไม่มีเอกสาร
Edward Strange

3
บางทีฉันไม่ได้แสดงออกอย่างชัดเจน การทดสอบอาจเป็นวิธีที่ดีในการพิจารณาว่าคุณทำเสร็จเมื่อใด แต่ฉันไม่คิดว่าพวกเขาเป็นวิธีที่ดีในการตัดสินใจว่าคุณต้องสร้างอะไร และใน TDD ฉันพบว่าผู้คนกำลังใช้การทดสอบเพื่อตัดสินใจว่าพวกเขาควรจะสร้างอะไร นั่นคือประสบการณ์ของคุณเช่นกัน?
CesarGon

ไม่งานสร้างของเราเป็นแบบอัตโนมัติ พวกมันถูกกระตุ้นโดยการเปลี่ยนแปลง อย่างที่ฉันพูด TDD เป็นเพียงส่วนหนึ่งของการแก้ปัญหา
Edward Strange

9

ออกแบบก่อน

TDD ไม่ใช่ข้อแก้ตัวในการข้ามการออกแบบ ฉันเคยเห็นการกระโดดของ bandwagon "เปรียว" หลายครั้งเพราะพวกเขาแม้ว่าพวกเขาจะสามารถเริ่มเขียนโค้ดได้ทันที ความคล่องตัวที่แท้จริงจะช่วยให้คุณสามารถเขียนโค้ดได้เร็วกว่าวิธีปฏิบัติทางวิศวกรรม (สาขาอื่น) ที่เป็นแรงบันดาลใจให้กับกระบวนการน้ำตก

แต่ทดสอบก่อน

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

ทดสอบและออกแบบ ... หนึ่งเดียว

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

แล้วใครเป็นคนขับรายการ?

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

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

เป็นของแข็งตราบใดที่การทดสอบนั้นเป็นของแข็ง

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

ใช่ แต่ถ้าฉันทำอย่างนั้นกับสะพานของฉัน ....

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

ถ้ามันดีขนาดนี้ทำไมมันไม่ได้ผล?

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

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

Tor ทีมเหล่านี้ TDD อาจไม่ใช่ทางที่จะไป


7

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

นอกจากนี้ยังง่ายสำหรับนักพัฒนาใหม่ในโครงการที่จะเพิ่มความเร็วเมื่อคุณมีรหัสที่ดีขึ้นโดยการทดสอบ


2
ฉันชอบสิ่งนี้ - มันเน้นจุดที่ว่า TDD มันไม่มากนักที่สร้างประโยชน์ (แม้ว่าการทดสอบหน่วยจะมีมูลค่ามากอย่างเห็นได้ชัด) เป็นรหัสที่ผลิตในแง่ที่สามารถทดสอบได้ (แยก) และ ทุกสิ่งที่ดีตามมาจากนั้น (แยกความกังวล, IoC และการฉีดพึ่งพา ฯลฯ ฯลฯ )
Murph

1
@Murph ใช่ TDD จะช่วยให้คุณ :) ซื่อสัตย์
Alb

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

@Murph ทฤษฎีคือการนำ IInjectedThing มาใช้ยังได้รับการออกแบบมาอย่างดีและครอบคลุมด้วยการทดสอบที่ดีดังนั้นคุณไม่จำเป็นต้องรู้ว่ามันคืออะไรที่จะสามารถเข้าใจคลาสที่มันถูกฉีดเข้าไป
อดัมเลียร์

@ Anna - ใช่จนถึงตอนนี้ ... หากคุณกำลังพยายามหาสิ่งที่แตกหัก (ฉันมักจะรู้สึกว่าการล่าบั๊กเป็นวิธีที่ดีในการหาคนที่อยู่ในโครงการ) หรือสิ่งที่ต้องเปลี่ยน / เพิ่มคุณต้องรู้ว่าอยู่ที่ไหน แม้ว่าสิ่งนั้นจะถูกห่อหุ้มอย่างดีคุณยังจำเป็นต้องค้นหา ... และถ้ามันหมายถึงการแทนที่บางสิ่ง (การติดตั้งใหม่ของ IWhatsit) คุณต้องรู้วิธีใช้การใช้งานทางเลือกอื่น อีกครั้งฉันไม่ได้สับสนว่าการก่อสร้างไม่ดี - มีหลักฐานมากเกินไปในทางตรงกันข้าม - แทนที่จะบอกว่าบางสิ่งบางอย่างอาจไม่ชัดเจน
Murph

5

ฉันคิดถึงเรื่องนี้มากแม้ว่าฉันจะไม่ได้ฝึกฝน TDD มากแค่ไหนก็ตาม ดูเหมือนจะมีความสัมพันธ์เชิงบวก (แข็งแรง?) ระหว่างคุณภาพของรหัสกับการติดตาม TDD

1) สิ่งที่ฉันใช้ครั้งแรกคือนี่คือ (โดยหลัก) ไม่ใช่เพราะ TDD เพิ่ม "คุณภาพที่ดีกว่า" ลงในรหัส (เช่น) มันเหมือน TDD ช่วยกำจัดส่วนที่เลวร้ายที่สุดและนิสัยและเพิ่มคุณภาพทางอ้อม

ฉันอยากจะสนับสนุนว่าไม่ใช่การทดสอบด้วยตนเอง - เป็นขั้นตอนการเขียนการทดสอบเหล่านั้น มันยากที่จะเขียนการทดสอบสำหรับโค้ดที่ไม่ดีและในทางกลับกัน และเก็บไว้ที่ด้านหลังของศีรษะในขณะที่เขียนโปรแกรมกำจัดรหัสที่ไม่ดีจำนวนมาก

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


+1 ฉันคิดว่าคุณจับมันมาโกลบ ฉันชอบคำอธิบายของคุณเป็นพิเศษว่า "TDD ช่วยกำจัดส่วนและนิสัยที่เลวร้ายที่สุด [... ] การเพิ่มคุณภาพโดยอ้อม" และการเปรียบเทียบหนวดเครายาวก็ดีเช่นกัน
CesarGon

คุณไม่ได้เขียนแบบทดสอบสำหรับรหัสที่ไม่ดี แต่คุณเขียนแบบทดสอบแล้วเขียนรหัสเพื่อทำการทดสอบ

Maglob สำหรับความรักในด้านที่เป็นประโยชน์มากกว่าคุณได้รับสิ่งที่ดีที่สุด @ Thorbjørnฉันคิดว่า Maglob ตามรอยมากขึ้นถ้าการออกแบบที่คุณคาดไว้แย่ลงการทดสอบของคุณจะต้องดูดขึ้นไปถึงระดับของการดูดที่คุณพยายามทำให้เป็นจริงและกลิ่นที่เน่าเสียของมันควรจะทดสอบก่อน คุณยังสามารถเขียนโค้ดจริง ๆ ได้อีกด้วย
Filip Dupanović

3

วิธีการ "เขียนการทดสอบ + การปรับปรุงซ้ำจนผ่าน" มีลักษณะต่อต้านวิศวกรรมอย่างไม่น่าเชื่อ

ดูเหมือนว่าคุณมีความเข้าใจผิดเกี่ยวกับการปรับโครงสร้างและ TDD

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

ดังนั้นคุณไม่สามารถrefactorรหัสจนกว่าจะผ่าน

และ TDD โดยเฉพาะการทดสอบหน่วย (ซึ่งฉันพิจารณาการปรับปรุงหลักเนื่องจากการทดสอบอื่น ๆ ดูเหมือนจะเป็นไปได้สำหรับฉัน) ไม่ได้เกี่ยวกับการออกแบบส่วนประกอบใหม่จนกว่าจะใช้งานได้ มันเกี่ยวกับการออกแบบส่วนประกอบและทำงานเกี่ยวกับการใช้งานจนกว่าส่วนประกอบจะทำงานตามที่ออกแบบไว้

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

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

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

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

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

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

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

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

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


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

@CesarGon: โพสต์อัปเดตแล้ว
back2dos

2

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

นอกเหนือจากการทดสอบไลบรารีที่ประกอบเป็นฐานของซอฟต์แวร์แล้วให้เขียนการทดสอบที่ครอบคลุมการโต้ตอบที่ผู้ใช้มีกับซอฟต์แวร์ / เว็บไซต์ / อะไรก็ตาม สิ่งเหล่านี้มาจากผู้ใช้โดยตรงและไลบรารี่เช่นแตงกวา (http://cukes.info) สามารถให้ผู้ใช้ของคุณเขียนแบบทดสอบด้วยภาษาธรรมชาติ

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

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


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

@CesarGon: ฉันคิดว่าคำถามเฉพาะของคุณใช้กับการทดสอบทุกประเภทไม่ใช่แค่ TDD ดังนั้นฉันจึงมุ่งเน้นไปที่คุณสมบัติเฉพาะของ TDD ที่ 'ทำงาน'
sevenseacat

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

2

ฉันคิดว่าคุณกำลังเข้าใกล้จุดแรกจากมุมที่ผิด

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

ในทางปฏิบัติสิ่งนี้เพิ่งพูดตรงไปตรงมาแปลว่า: ตอนนี้เราสามารถไปยังสิ่งต่อไปได้ (หลังจากที่เราใช้ TDD สำเร็จเพื่อสนองภาคทั้งหมด) หากคุณเข้าใกล้ TDD จากมุมมองนี้แล้วมันไม่ได้เกี่ยวกับ "เขียนทดสอบ + refactor จนผ่าน" ก็มากขึ้นเกี่ยวกับหลังจากเสร็จสิ้นการนี้ฉันตอนนี้ในเครือมุ่งเน้นไปที่คุณลักษณะถัดไปเป็นสิ่งที่สำคัญที่สุดในขณะนี้

คิดว่าวิธีนี้ใช้ได้กับวิศวกรรมโยธา เรากำลังสร้างสนามกีฬาที่สามารถสร้างบ้านให้ผู้ชมสาธารณะได้ 150000 คน หลังจากที่เราได้พิสูจน์แล้วว่าความสมบูรณ์ของโครงสร้างของสนามกีฬาเป็นเสียงเราได้รับความพึงพอใจความปลอดภัยก่อน ตอนนี้เราสามารถมุ่งเน้นไปที่ประเด็นอื่น ๆ ที่มีความสำคัญในทันทีเช่นห้องส้วมแผงขายอาหารที่นั่ง ฯลฯ ทำให้ผู้ชมได้รับประสบการณ์ที่น่าพึงพอใจยิ่งขึ้น นี่เป็นเรื่องที่เกินความจริงเนื่องจาก TDD มีอยู่มากมาย แต่จุดอ่อนก็คือคุณไม่ได้ทำให้ประสบการณ์การใช้งานที่แย่ที่สุดถ้าคุณมุ่งเน้นไปที่ฟีเจอร์ใหม่และน่าตื่นเต้นและการรักษาความสมบูรณ์ในเวลาเดียวกัน คุณได้ครึ่งทางทั้งสองกรณี ฉันหมายความว่าคุณจะรู้ได้อย่างไรห้องน้ำหลายแห่งและคุณควรพักที่ไหนสำหรับคน 150000 ฉันแทบจะไม่เคยเห็นสนามกีฬาพังทลายในช่วงชีวิตของฉันเอง แต่ฉันต้องรอแถวต่อแถวในช่วงครึ่งเวลาหลายครั้ง นั่นบอกว่าปัญหาเรื่องห้องน้ำมีความซับซ้อนมากกว่าและถ้าวิศวกรสามารถใช้เวลาน้อยลงในเรื่องความปลอดภัยพวกเขาอาจจะสามารถแก้ไขปัญหาเรื่องห้องน้ำได้

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


+1 สำหรับคำอธิบายที่ดีในประเด็นแรกของฉันและสำหรับการอ้างอิงถึง Hank Moody รุ่งโรจน์.
CesarGon

2
ขอบคุณฉันขอบคุณมัน ฉันมองว่า TDD เป็นปรากฏการณ์ทางจิตวิทยามากกว่าจะเป็นวิธีการ / กระบวนการทางเทคนิค แต่นั่นเป็นเพียงมุมมองโลกของฉันในเรื่องนี้
Filip Dupanović

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

1

TDD ในวิศวกรรมซอฟต์แวร์เป็นแนวปฏิบัติที่ดีเช่นเดียวกับการจัดการข้อผิดพลาดในแอปพลิเคชันเป็นแนวปฏิบัติที่ดีเช่นเดียวกับการบันทึกและวินิจฉัย (แม้ว่าจะเป็นส่วนหนึ่งของการจัดการข้อผิดพลาด)

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

TDD เป็นเพียงวิธีในการทำให้เป็นทางการและทำตามขั้นตอนเหล่านั้นโดยอัตโนมัติเพื่อให้คุณเป็นนักพัฒนาที่มีประสิทธิผล

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

สิ่งที่ยากที่สุดในวิศวกรรมซอฟต์แวร์คือการทำซ้ำความผิดพลาดเมื่อสะพานล้มเหลวมักจะง่ายต่อการตรวจสอบสิ่งที่ผิดพลาดและในทางทฤษฎีแล้วจะทำให้เกิดความล้มเหลวได้ง่าย เมื่อโปรแกรมคอมพิวเตอร์ล้มเหลวอาจเป็นเหตุการณ์ที่ซับซ้อนซึ่งทำให้ระบบเข้าสู่สถานะที่ผิดพลาดและอาจเป็นเรื่องยากมากที่จะพิจารณาว่าข้อผิดพลาดนั้นอยู่ที่ไหน การทดสอบ TDD และหน่วยทำให้ง่ายต่อการทดสอบความทนทานของส่วนประกอบซอฟต์แวร์ไลบรารีและอัลกอริทึม

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


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

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

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

1

หากคุณยอมรับว่าพบข้อผิดพลาดที่เร็วกว่าค่าใช้จ่ายในการแก้ไขที่น้อยลงก็จะทำให้ TDD คุ้มค่า


1
คุณมีหลักฐานว่าพบข้อบกพร่องได้เร็วขึ้นในการตั้งค่า TDD หรือไม่? นอกจากนี้ผลข้างเคียงของ TDD เช่นผลกระทบต่อสถาปัตยกรรมคืออะไร
CesarGon

0

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

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


6
-1 มีหลายคนที่พูดแบบนี้ แต่ฉันยังไม่ได้เห็นเวทมนตร์ที่ทำให้มันเกิดขึ้น
Bart van Ingen Schenau

@Bart van Ingen Schenau คุณทำ TDD แล้วหรือยัง? ฉันได้ทำมันมาประมาณ 4 ปีและฉันได้เห็นว่า "วิเศษ" เกิดขึ้นแน่นอน
Marcie

0

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

มันเหมือนกับการเขียนใช้กรณีสำหรับห้องสมุดก่อนที่จะออกแบบห้องสมุด ยกเว้นคุณสามารถเปลี่ยนกรณีการใช้งานในไลบรารีและคุณอาจไม่ใช่ TDD (ฉันใช้ TDD สำหรับการออกแบบ API) นอกจากนี้คุณยังได้รับการสนับสนุนให้เพิ่มการทดสอบมากขึ้นและนึกถึงอินพุต / การใช้งานการทดสอบที่อาจได้รับ ฉันพบว่ามีประโยชน์เมื่อเขียนไลบรารีหรือ API ซึ่งถ้าคุณเปลี่ยนสิ่งที่คุณต้องรู้ว่าคุณทำบางสิ่งบางอย่างเสียหาย ในซอฟต์แวร์ส่วนใหญ่แบบวันต่อวันฉันไม่รำคาญเพราะเหตุใดฉันต้องมีกรณีทดสอบสำหรับผู้ใช้กดปุ่มหรือถ้าฉันต้องการยอมรับรายการ CSV หรือรายการที่มีหนึ่งรายการต่อบรรทัด ... นั่นไม่สำคัญว่าฉันจะอนุญาต เพื่อเปลี่ยนมันดังนั้นฉันไม่ควร / ไม่สามารถใช้ TDD


0

ซอฟต์แวร์เป็นสารอินทรีย์เมื่อวิศวกรรมโครงสร้างเป็นรูปธรรม

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

เมื่อคุณทดสอบในการแยกโดยทั่วไปจะมีกรอบงานสองประเภทที่คุณสามารถใช้ได้ กรอบข้อ จำกัด และไม่ จำกัด กรอบงานที่ไม่มีข้อ จำกัด (ใน. NET) ช่วยให้คุณสามารถทดสอบและแทนที่ทุกอย่างโดยไม่คำนึงถึงตัวดัดแปลงการเข้าถึง นั่นคือคุณสามารถ stub และเยาะเย้ยส่วนประกอบส่วนตัวและการป้องกัน

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

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

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


0

ทำไม TDD ถึงทำงาน

มันไม่ได้

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

และที่สำคัญที่สุด: การออกแบบซอฟต์แวร์ที่ดีไม่ได้เกิดจากการทดสอบอย่างน่าอัศจรรย์เนื่องจากโฆษณาโดยผู้เผยแพร่ศาสนาที่มีความคล่องตัว / TDD ทุกคนที่อ้างสิทธิ์เป็นอย่างอื่นโปรดให้ลิงก์ไปยังการวิจัยทางวิทยาศาสตร์ที่ผ่านการตรวจสอบโดยเพื่อนซึ่งพิสูจน์เรื่องนี้หรืออย่างน้อยก็อ้างอิงถึงโครงการโอเพนซอร์ซบางโครงการซึ่งประโยชน์ของ TDD สามารถศึกษาได้จากประวัติการเปลี่ยนแปลงรหัส

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.