คุณให้การทดสอบหน่วยของคุณใช้งานได้อย่างไรเมื่อทำการปรับโครงสร้างใหม่


29

ในอีกคำถามหนึ่งพบว่าหนึ่งในความเจ็บปวดกับ TDD กำลังรักษาชุดการทดสอบให้สอดคล้องกับรหัสฐานระหว่างและหลังการปรับโครงสร้างใหม่

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

คุณจะหลีกเลี่ยงการทำลายการทดสอบเมื่อทำการเปลี่ยนโครงสร้างใหม่ได้อย่างไร

  • คุณเขียนแบบทดสอบ 'ดีกว่า' หรือไม่? ถ้าเป็นเช่นนั้นคุณควรมองหาอะไร
  • คุณหลีกเลี่ยงการ refactoring บางประเภทหรือไม่
  • มีเครื่องมือทดสอบการปรับโครงสร้างใหม่หรือไม่?

แก้ไข:ฉันเขียนคำถามใหม่ที่ถามสิ่งที่ฉันต้องการถาม (แต่เก็บไว้เป็นตัวแปรที่น่าสนใจ)


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

IDE ของคุณไม่สามารถหาวิธีปรับโครงสร้างการทดสอบได้อีกหรือไม่

@ Thorbjørn Ravn Andersen ใช่และฉันเขียนคำถามใหม่ที่ถามว่าฉันหมายถึงอะไรถาม (แต่เก็บไว้นี้เป็นตัวแปรที่น่าสนใจดูคำตอบของ azheglov ซึ่งเป็นสิ่งที่คุณพูด)
Alex Feinman

พิจารณาการเพิ่มข้อมูลให้กับคำถามนี้หรือไม่

คำตอบ:


35

สิ่งที่คุณกำลังพยายามทำนั้นไม่ได้ทำการปรับโครงสร้างใหม่จริงๆ ด้วย refactoring โดยนิยามคุณไม่เปลี่ยนแปลงสิ่งที่ซอฟแวร์ของคุณไม่คุณเปลี่ยนวิธีการที่มันไม่ได้

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

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


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

3
หากการทดสอบต้องการการปรับค่าคงที่อาจเป็นคำใบ้ว่ามีการทดสอบที่ละเอียดมากเกินไป ตัวอย่างเช่นสมมติว่าชิ้นส่วนของรหัสต้องเรียกใช้เหตุการณ์ A, B และ C ภายใต้สถานการณ์บางอย่างในลำดับที่ไม่เจาะจง รหัสเก่าทำตามคำสั่ง ABC และการทดสอบคาดหวังเหตุการณ์ตามลำดับนั้น หากรหัส refactored กระจายเหตุการณ์ในลำดับ ACB ก็ยังคงทำงานตามข้อมูลจำเพาะ แต่การทดสอบจะล้มเหลว
ออตโต

3
@ เควิน: ฉันเชื่อว่าสิ่งที่คุณอธิบายคือการออกแบบใหม่เนื่องจากการเปลี่ยนแปลงส่วนต่อประสานสาธารณะ นิยามของพรานล่าสัตว์ของการเปลี่ยนโครงสร้าง ("การแก้ไขโครงสร้างภายในของ [โค้ด] โดยไม่เปลี่ยนพฤติกรรมภายนอก") ค่อนข้างชัดเจนเกี่ยวกับเรื่องนั้น
azheglov

3
@azheglov: บางที แต่ในประสบการณ์ของผมถ้าการดำเนินการเป็นไปอย่างไม่ถูกต้องอินเตอร์เฟซ
เควิน

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

21

ข้อดีอย่างหนึ่งของการมีการทดสอบหน่วยคือคุณสามารถมั่นใจในการปรับโครงสร้างใหม่ได้อย่างมั่นใจ

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

หากการเปลี่ยนโครงสร้างเปลี่ยนอินเทอร์เฟซสาธารณะการทดสอบควรถูกเขียนใหม่ก่อน Refactor จนกว่าการทดสอบใหม่จะผ่าน

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


7

ตรงกันข้ามกับคำตอบอื่น ๆ เป็นสิ่งสำคัญที่จะต้องทราบว่าวิธีการทดสอบบางอย่างอาจเปราะบางเมื่อระบบภายใต้การทดสอบ (SUT) ถูก refactored หากการทดสอบเป็น whitebox

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

หากฉันกำลังตรวจสอบสถานะภายในของ SUT ของฉันโดยการเปิดเผยสมาชิกส่วนตัวหรือป้องกัน (เราสามารถใช้ "เพื่อน" ใน visual Basic หรือขยายระดับการเข้าถึง "ภายใน" และใช้ "internalsvisibleto" ใน c #; ในภาษา OO จำนวนมากรวมถึง c # a " สามารถใช้คลาสเฉพาะการทดสอบได้ ") จากนั้นสถานะภายในของคลาสจะสำคัญ - คุณอาจทำการปรับโครงสร้างคลาสเป็นกล่องดำ แต่การทดสอบกล่องสีขาวจะล้มเหลว สมมติว่ามีการใช้เขตข้อมูลเดียวซ้ำเพื่อหมายถึงสิ่งต่าง ๆ (ไม่ใช่แนวปฏิบัติที่ดี!) เมื่อ SUT เปลี่ยนสถานะ - หากเราแยกมันออกเป็นสองเขตข้อมูลเราอาจจำเป็นต้องเขียนการทดสอบที่ขาดอีกครั้ง

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

ถ้าฉันใช้ " test hooks " หรือรหัสเฉพาะการทดสอบหรือการรวบรวมตามเงื่อนไขอื่น ๆ มันอาจเป็นเรื่องยากที่จะตรวจสอบให้แน่ใจว่าการทดสอบไม่หยุดทำงานเนื่องจากการพึ่งพาที่เปราะบางต่อตรรกะภายใน

ดังนั้นเพื่อป้องกันไม่ให้การทดสอบเป็นคู่กับรายละเอียดภายในของ SUT อย่างใกล้ชิดมันอาจช่วยในการ:

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

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

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

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

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

[ ... ]

การเชื่อมต่อกับการนำไปใช้ยังรบกวนการปรับโครงสร้างเนื่องจากการเปลี่ยนแปลงการใช้งานมีแนวโน้มที่จะทำลายการทดสอบมากกว่าการทดสอบแบบดั้งเดิม

ฟาวเลอร์ - Mocks ไม่สมบูรณ์


ฟาวเลอร์เขียนหนังสือเกี่ยวกับ Refactoring อย่างแท้จริง และหนังสือที่มีอำนาจมากที่สุดเกี่ยวกับการทดสอบหน่วย (รูปแบบการทดสอบ xUnit โดย Gerard Meszaros) อยู่ในซีรีย์ "ลายเซ็น" ของ Fowler ดังนั้นเมื่อเขากล่าวว่าการเปลี่ยนโครงสร้างอาจทำให้การทดสอบหยุดลง
ความสมบูรณ์แบบ

5

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

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


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

2
ในกรณีนี้การทดสอบของเขาจะถูก refactored คุณต้องระวังว่า: ก่อนอื่นให้คุณเปลี่ยนชื่อวิธีจากนั้นทำการทดสอบ มันควรล้มเหลวด้วยเหตุผลที่ถูกต้อง (ไม่สามารถคอมไพล์ได้ (C #) คุณได้รับข้อยกเว้น MessageNotUnderstood (Smalltalk) ไม่มีอะไรเกิดขึ้น (รูปแบบการกินเป็นโมฆะของ Objective-C) จากนั้นคุณเปลี่ยนการทดสอบโดยรู้ว่าคุณไม่ได้แนะนำบั๊กใด ๆ โดยไม่ได้ตั้งใจ "หากการทดสอบของคุณผิดพลาด" หมายถึง "ถ้าการทดสอบของคุณหยุดพักหลังจากที่คุณทำการรีแฟคเตอร์เสร็จ" หรืออีกนัยหนึ่ง ลองทำให้ชิ้นส่วนเปลี่ยนแปลงเล็ก ๆ !
Frank Shearar

1
การทดสอบหน่วยเป็นคู่โดยเนื้อแท้กับโครงสร้างของรหัส ตัวอย่างเช่น Fowler มีจำนวนมากในrefactoring.com/catalogที่จะส่งผลต่อการทดสอบหน่วย (เช่นวิธีซ่อน, วิธีแบบอินไลน์, แทนที่รหัสข้อผิดพลาดด้วยข้อยกเว้นและอื่น ๆ )
Kristian H

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

ฉันเขียนข้างต้นโดยสมมติว่ามีการทดสอบเป็นลายลักษณ์อักษรที่ดี: หากคุณกำลังทดสอบการใช้งานของคุณ - หากโครงสร้างของการทดสอบแสดงถึง internals ของรหัสภายใต้การทดสอบแน่นอน ในกรณีนี้ให้ทดสอบสัญญาของหน่วยไม่ใช่การดำเนินการ
Frank Shearar

4

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

>  Keep the API the same, but change how the API is implemented internally
>  Change the API

อย่างที่คนอื่นบันทึกไว้แล้วถ้าคุณรักษา API ไว้เหมือนเดิมและการทดสอบการถดถอยทั้งหมดของคุณทำงานบน API สาธารณะคุณไม่ควรมีปัญหาใด ๆ การปรับโครงสร้างไม่ควรทำให้เกิดปัญหาใด ๆ การทดสอบที่ล้มเหลวใด ๆ EITHER หมายถึงรหัสเก่าของคุณมีข้อบกพร่องและการทดสอบของคุณไม่ดีหรือรหัสใหม่ของคุณมีข้อบกพร่อง

แต่มันค่อนข้างชัดเจน ดังนั้นคุณอาจหมายถึงโดยการสร้างใหม่ว่าคุณกำลังเปลี่ยน API

ดังนั้นฉันจะตอบวิธีที่จะเข้าใกล้!

  • ก่อนอื่นให้สร้าง API ใหม่นั่นคือสิ่งที่คุณต้องการให้พฤติกรรม API ใหม่ของคุณเป็น หากเกิดขึ้นว่า API ใหม่นี้มีชื่อเหมือนกับ OLDER API ฉันจะผนวกชื่อ _NEW ต่อท้ายชื่อ API ใหม่

    int DoSomethingInterestingAPI ();

กลายเป็น:

int DoSomethingInterestingAPI_NEW( int takes_more_arguments );
int DoSomethingInterestingAPI_OLD();
int DoSomethingInterestingAPI() { DoSomethingInterestingAPI_NEW (whatever_default_mimics_the_old_API);

ตกลง - ในขั้นตอนนี้ - การทดสอบการถดถอยทั้งหมดของคุณผ่านบัตรผ่าน - ใช้ชื่อ DoSomethingInterestingAPI ()

ถัดไปอ่านรหัสของคุณและเปลี่ยนการโทรทั้งหมดเป็น DoSomethingInterestingAPI () เป็นตัวแปรที่เหมาะสมของ DoSomethingInterestingAPI_NEW () ซึ่งรวมถึงการอัปเดต / เขียนใหม่ส่วนใดของการทดสอบการถดถอยของคุณจะต้องเปลี่ยนเพื่อใช้ API ใหม่

ถัดไปทำเครื่องหมาย DoSomethingInterestingAPI_OLD () เป็น [[คัดค้าน ()]] เก็บ API ที่เลิกใช้ไว้นานเท่าที่คุณต้องการ (จนกว่าคุณจะได้รับการอัปเดตรหัสทั้งหมดอย่างปลอดภัยที่อาจต้องพึ่งพา)

ด้วยวิธีนี้ความล้มเหลวใด ๆ ในการทดสอบการถดถอยของคุณก็คือบั๊กในการทดสอบการถดถอยนั้นหรือระบุข้อบกพร่องในรหัสของคุณ - ตรงตามที่คุณต้องการ กระบวนการในขั้นตอนการแก้ไข API นี้โดยการสร้าง API ของ _NEW และ _OLD อย่างชัดเจนช่วยให้คุณมีบิตของรหัสใหม่และเก่าที่อยู่ร่วมกันชั่วขณะหนึ่ง


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

1

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

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


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

1

ทำให้ชุดการทดสอบซิงค์กับ codebase ระหว่างและหลังการปรับโครงสร้างใหม่

สิ่งที่ทำให้มันยากคือการแต่งงานกัน การทดสอบใด ๆ ที่มาพร้อมกับระดับของการมีเพศสัมพันธ์กับรายละเอียดการใช้งาน แต่การทดสอบหน่วย (ไม่ว่าจะเป็น TDD หรือไม่) โดยเฉพาะอย่างยิ่งมันไม่ดีเพราะมันเข้าไปยุ่งกับ internals: การทดสอบหน่วยเพิ่มเติมเท่ากับรหัสมากขึ้น ของหน่วย - อย่างน้อยที่สุด

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

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


0

การทดสอบของคุณเชื่อมโยงอย่างแน่นหนากับการนำไปใช้และไม่ใช่ข้อกำหนด

ลองเขียนข้อสอบของคุณด้วยความคิดเห็นแบบนี้:

//given something
...test code...
//and something else
...test code...
//when something happens
...test code...
//then the state should be...
...test code...

วิธีนี้คุณจะไม่สามารถปรับความหมายของการทดสอบได้อีก

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