เมื่อใดจึงเหมาะสมที่จะไม่ทำการทดสอบหน่วย


138

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

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

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

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

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

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

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


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

1
เราประสบความสำเร็จอย่างยิ่งใหญ่ที่ Transactis โดยใช้เครื่องมือทดสอบการทำงานอัตโนมัติบนเว็บของ Telerik เรามีการทดสอบเบราว์เซอร์ด้วยตนเองมาหลายสิบครั้งแล้วซึ่งเปลี่ยนเป็นระบบอัตโนมัติ การทดสอบแบบอัตโนมัตินั้นเร็วกว่าและเป็นสิ่งที่ดีสำหรับการเน้นปัญหาด้านประสิทธิภาพที่เว็บไซต์ของคุณมี
John Kaster

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

1
นี่ไม่ใช่คำตอบจริงๆเพียงแค่การสังเกต ... ข้อโต้แย้งของคุณกับการทดสอบหน่วยเพราะ "ข้อกำหนดเปลี่ยนบ่อยเกินไป" เตือนฉันถึงข้อโต้แย้งผกผันที่ฉันได้ยินว่าฉันทำงานที่ไหน: "โปรแกรมของเรามีความคงที่ มันแทบจะไม่เปลี่ยนอะไรเลย! " ;)
Bane

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

คำตอบ:


84

ตัวอย่างมากมายที่ฉันเคยเห็นจากการทดสอบลงไปที่ minutiae ซึ่งครอบคลุมทุกส่วนของโค้ด

ดังนั้น? คุณไม่ได้มีการทดสอบทุกอย่าง เพียงแค่สิ่งที่เกี่ยวข้อง

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

มันผิดจริง มันไม่ได้มีประสิทธิภาพมากขึ้น มันเป็นเพียงนิสัย

สิ่งที่นักพัฒนาโซโลคนอื่นทำคือเขียนแบบร่างหรือโครงร่างเขียนกรณีทดสอบจากนั้นกรอกรหัสด้วยเค้าร่าง

นั่นเป็นเรื่องที่มีประสิทธิภาพมาก

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

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

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

รหัสไม่ได้ทำจนกว่าการทดสอบจะผ่าน นั่นเป็นความจริงสากลประการหนึ่งของซอฟต์แวร์

คุณสามารถมีข้อ จำกัด "นี่คือ" การทดสอบการยอมรับ

หรือคุณสามารถมีการทดสอบหน่วย

หรือคุณสามารถมีทั้ง

แต่ไม่ว่าคุณจะทำอะไรมีการทดสอบเพื่อแสดงให้เห็นว่าซอฟต์แวร์ใช้งานได้เสมอ

ฉันขอแนะนำให้ใช้ชุดเครื่องมือทดสอบหน่วยที่เป็นทางการเล็กน้อยซึ่งเป็นประโยชน์เล็กน้อยทำให้การทดสอบมีประโยชน์มากขึ้น


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

9
@Ken Pespisa: ขออภัย ฉันดื่ม TDD Kool-Aid ประมาณสองปีที่แล้ว (หลังจาก 30 ปีของการทดสอบครั้งสุดท้าย) ตอนนี้ฉันติดอยู่กับการทดสอบก่อน มันทำให้ฉันมีประสิทธิผลมากขึ้นเพราะฉันคิดน้อยลงเมื่อต้องสร้าง
S.Lott

3
@Ken Pespisa: ไม่มีคำตอบที่สมดุล ถ้าคุณถามว่ามันถูกต้องหรือเปล่าที่จะหารด้วยศูนย์คุณจะได้รับคำตอบที่ล้นหลามด้วยเหตุผลเดียว หากคุณถามว่าsqrt(-1)ควรเป็นจำนวนเต็มหรือไม่ ยอดคงเหลืออยู่ที่ประมาณ "วิธี" และ "ลำดับใด" ความจริงเปล่าคือคุณต้องทดสอบ ดังนั้นเขียนแบบทดสอบก่อนและตรวจสอบให้แน่ใจว่าได้ผล
S.Lott

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

10
"รหัสไม่ได้ทำจนกว่าการทดสอบจะผ่าน" - ไม่ได้จริงๆ IMO รหัสเริ่มต้นเมื่อผ่านการทดสอบ รหัสจะไม่ถูกดำเนินการจนกว่าจะใช้งานได้จริงประมาณหนึ่งหรือสองปีและต้องผ่านการทดสอบความเค้นและการทดสอบบูรณาการที่มีฐานผู้ใช้ขนาดใหญ่ใช้งานและใจร้อน นั่นคือการทดสอบเดียวที่นับได้จริงๆ
เวกเตอร์

107

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

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

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

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

คุณคิดว่าคุณจะดีบั๊กมากแค่ไหน?

หากฟังดูเหมือนแฟนตาซีคุณพูดถูก แต่ความเป็นจริงไม่แตกต่างกันมาก แทนที่ eyeblink ด้วยเวลาไม่กี่วินาทีและนางฟ้ากับ TDD วินัยและคุณได้รับมัน

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

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


28
ว้าวลุงบ๊อบ? เป็นเรื่องดีที่คุณจะได้รับความคิดของคุณที่นี่ ฉันเห็นด้วยกับคุณเกี่ยวกับประโยชน์ของ TDD ไม่มีข้อโต้แย้งใด ๆ คำถามคือเกี่ยวกับการลงทุนของเวลาและ ROI ฉันไม่ได้คิดเรื่องเหล่านี้เลย ลองนึกภาพโครงการที่จะใช้เวลาให้ฉันกับ TDD มากกว่าที่จะทำได้ 50% และนางฟ้าบอกฉันว่าจะช่วยฉันประหยัดเวลา 10% ในการทดสอบด้วยตนเองในช่วงอายุของโครงการ นั่นอาจดูเหมือนจินตนาการ แต่ฉันเห็นว่าเป็นไปได้ทั้งหมดในบางโครงการ
Ken Pespisa

11
@Ken "ลองคิดดูว่าโครงการจะใช้เวลาอีก 50% ให้ฉันทำงานกับ TDD ให้เสร็จโดยที่ไม่มี" มันฟังดูเหมือนแฟนตาซีอย่างแน่นอน ในความเป็นจริงดูเหมือนว่าคุณเพิ่งสร้างมันขึ้นมาในจุดที่ไม่มีหลักฐานเพื่อสนับสนุน
Rein Henrichs

18
@Rein Henrichs - แน่นอนว่าฉันสร้างตัวเลขขึ้นมามันเป็นคำแถลงสมมุติฐาน ฉันกำลังชี้ให้เห็นว่า TDD เพิ่มเวลาจำนวนมากให้กับโครงการและฉันต้องพิจารณาว่าฉันจะได้รับสิ่งที่มีค่าเท่ากันหรือดีกว่าในทางกลับกัน คุณไม่ต้องโน้มน้าวฉันในคุณค่าของ TDD ฉันเชื่อมั่น แต่มันไม่ใช่ยาครอบจักรวาล
Ken Pespisa

11
@Rein "หลักฐานที่มีอยู่คืออะไร" กรุณาอธิบายอย่างละเอียด
Ken Pespisa

22
@ Uncle Bob "แทนที่ eyeblink ด้วยสองสามวินาที": แน่นอนว่าคุณล้อเล่น TDD เป็นเครื่องมือที่ดี แต่คุณต้องทดสอบเฉพาะส่วนที่เกี่ยวข้องไม่เช่นนั้นคุณจะใช้เวลาในการบำรุงรักษาการทดสอบมากกว่าการพัฒนาอย่างจริงจัง นี่เป็นเรื่องจริงโดยเฉพาะอย่างยิ่งเมื่อความต้องการเปลี่ยนแปลงอย่างรวดเร็ว: คุณกำลังเขียนและทิ้งการทดสอบสำหรับชั้นเรียนที่เปลี่ยนแปลงตลอดเวลา ฉันไม่ได้บอกว่า TDD ไม่ถูกต้องมันต้องถูกใช้อย่างสมเหตุสมผลและไม่ได้ใช้อย่างมีกลไกตามที่คุณแนะนำ
Giorgio

34

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

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

ประการที่สองการเรียกใช้พวกเขาพบข้อบกพร่องที่อาจเกิดขึ้นในการทดสอบ

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

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

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

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


2
@Ken ชุดทดสอบเป็นข้อกำหนดในรูปแบบที่ปฏิบัติการได้

32

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

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

  1. เขียนทดสอบ
  2. ดูมันล้มเหลว (พิสูจน์ว่าคุณมีงานต้องทำ)
  3. เขียนสิ่งที่จำเป็นในการทำแบบทดสอบ - ไม่มาก
  4. ดูมันผ่าน (ใช่!)
  5. Refactor (ปรับปรุงให้ดีขึ้น)
  6. ล้างล้างและทำซ้ำ

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

ตอนนี้คุณต้องทดสอบสิ่งต่างๆเช่นคุณสมบัติ C # หรือไม่ ลองนึกภาพสถานที่ให้บริการที่กำหนดเช่นนี้:

bool IsWorthTesting {get; set;}

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

นอกจากนี้คุณจะพบว่ามีบางส่วนของรหัสของคุณที่ดีมากจะพยายามทดสอบอย่างถูกต้อง หมายความว่าอย่าทำ แต่ให้แน่ใจว่าคุณทดสอบรหัสที่ใช้ / ถูกใช้โดยปัญหาที่ยุ่งยาก:

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

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


24

คุณต้องสมดุลค่าใช้จ่ายในการทดสอบกับค่าของข้อบกพร่อง

การเขียนการทดสอบหน่วย 10 บรรทัดสำหรับฟังก์ชันที่เปิดไฟล์โดยที่ความล้มเหลวคือ "ไม่พบไฟล์" นั้นไม่มีจุดหมาย

ฟังก์ชั่นที่ทำบางสิ่งที่ซับซ้อนให้กับโครงสร้างข้อมูลที่ซับซ้อน - แน่นอนแล้วว่าใช่

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


23

การทดสอบคือการพนัน

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

เช่นเดียวกับการเดิมพันบางครั้งคุณชนะบางครั้งคุณก็แพ้

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

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


3
คำตอบที่ดี. หนึ่งในไม่กี่คนที่ตอบคำถามเดิมของฉัน ฉันจมลงสู่โลกแห่งการทดสอบตั้งแต่เขียนบทความนี้ (ฉันชอบมัน btw.) ฉันต้องเข้าใจมันให้มากขึ้นก่อนที่ฉันจะรู้ว่าจะใช้เมื่อไหร่ (หรือไม่) ด้วยเหตุผลหลายประการที่ระบุไว้ที่นี่ฉันต้องการใช้มันตลอดเวลา แต่ในที่สุดมันก็ขึ้นอยู่กับว่าฉันจะไปถึงมันเร็วแค่ไหนเพราะในที่สุดมันเป็นการพนันของเวลาของฉันซึ่งอยู่ภายใต้การควบคุมของ บริษัท / ลูกค้าของฉันและบ่อยครั้งที่พวกเขาเน้นที่มุมด้านล่างของสามเหลี่ยมโครงการ: en wikipedia.org/wiki/Project_triangle
Ken Pespisa

10

คำแนะนำของฉันคือทดสอบเฉพาะรหัสที่คุณต้องการทำงานอย่างถูกต้อง

อย่าทดสอบรหัสที่คุณต้องการให้เป็นรถและทำให้เกิดปัญหากับคุณ


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

ฉันยอมรับว่าเป็นสิ่งที่ทำให้ฉันคิดว่ามัน ;-)
นิคฮอดจ์ส

8

ฉันมักจะสงสัยว่าฉันควรลองใช้วิธี TDD หรือไม่ ดูเหมือนความคิดที่ดี แต่ฉันก็ไม่สามารถพิสูจน์ได้ว่างานพิเศษที่เกี่ยวข้อง

การทดสอบ TDD และหน่วยไม่เหมือนกัน

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

TDD คือการฝึกการเข้ารหัสในลูปของแสงสีแดง ไฟเขียว. Refactor iterations

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

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


คุณช่วยอธิบายรายละเอียดเกี่ยวกับข้อผิดพลาดแบบหายไปได้อย่างไร คุณกำลังบอกว่าคุณจะได้รับคำตอบที่รวดเร็วกว่าว่าดัชนีของอาร์เรย์นั้นเป็นแบบ zero-based หรือ one-based ผ่านการทดสอบมากกว่าการค้นหาผ่านเอกสารหรือไม่? ดูเหมือนว่าไม่น่าจะเกิดขึ้นกับฉัน - ฉันสวยใน Google :)
Ken Pespisa

1
ที่จริงแล้วการเขียน TDD เป็นวิธีที่ยอดเยี่ยมในการสำรวจ API (รวมถึง codebase ดั้งเดิมสำหรับวัตถุประสงค์ของการทำเอกสาร)
Frank Shearar

นอกจากนี้ยังมีประโยชน์มากหาก API นั้นเปลี่ยนแปลง ... คุณมีการทดสอบที่ล้มเหลว :-)
bitsoflogic

@Ken Pespisa มันเร็วกว่าแน่นอน - เขียนรหัสตามว่าคุณคิดว่ามันเป็น 0 หรือ 1 เรียกใช้แก้ไขถ้าจำเป็น ส่วนใหญ่แล้วคุณจะพูดถูกและไม่ต้องมองหามันหากคุณผิดคุณก็รู้ว่าภายใน 10 วินาที
Paul Butcher

ประโยชน์ที่น่าสนใจมาก ฉันเป็นอย่างนั้น
Ken Pespisa

3

ฉันทำงานบนระบบที่เราทดสอบเกือบทุกอย่าง การประหารชีวิตที่น่าทึ่งในการทดสอบคือรหัสผลลัพธ์ PDF และ XLS

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

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


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

2

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

คิดว่ามัน: ถ้าคุณมีความคุ้มครองคุณลักษณะบางอย่างที่ดีกับการทดสอบของคุณ (เพื่อไม่ให้สับสนกับความคุ้มครองรหัส) และสมมติว่าคุณมี 10 คุณสมบัติ - คลิกที่ปุ่มหมายความว่าคุณมีประมาณ 10 yousอีกครั้งทำแบบทดสอบของคุณ ... ในขณะที่คุณนั่งจิบกาแฟ

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

TL; DRไม่เหมาะเลยจริงๆเพราะผลประโยชน์นั้นดีเกินไป


2

สองคำตอบที่ดีมากที่ฉันเจออยู่ที่นี่:

  1. เมื่อใดถึงการทดสอบหน่วยเทียบกับการทดสอบด้วยตนเอง
  2. สิ่งใดที่ไม่ควรทดสอบเมื่อพูดถึงการทดสอบหน่วย

เหตุผลสำหรับการหลีกเลี่ยงการรับรู้ค่าใช้จ่าย:

  • ประหยัดเวลา / ต้นทุนทันทีสำหรับ บริษัท ของคุณ
  • เวลาที่อาจเกิดขึ้น / การประหยัดต้นทุนในการแก้ไขปัญหา / การบำรุงรักษา / การขยายในระยะยาวแม้หลังจากที่คุณหายไป

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


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

1

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

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

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

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

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


ฉันชอบความคิดในการป้องกันการถดถอยและเพิ่มความมั่นใจ นี่คือเหตุผลที่ฉันต้องการเพิ่มการทดสอบ
Ken Pespisa

1

ดูเหมือนว่าคำตอบส่วนใหญ่คือ pro-TDD แม้ว่าคำถามจะไม่ถามเกี่ยวกับ TDD แต่เกี่ยวกับการทดสอบหน่วยโดยทั่วไป

ไม่มีกฎวัตถุประสงค์ที่สมบูรณ์ที่อยู่เบื้องหลังสิ่งที่ทดสอบหน่วยหรือไม่ทดสอบหน่วย แต่มีสองสามครั้งที่ดูเหมือนว่าโปรแกรมเมอร์จำนวนมากไม่ทดสอบหน่วย:

  1. วิธีการส่วนตัว

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

  1. สิ่งที่คุณรู้อยู่แล้วว่าควรจะทำงาน (หรือสิ่งที่ทดสอบโดยคนอื่น)

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

ทั้งสองอย่างสามารถนำไปใช้ได้ไม่ว่าคุณจะทำ TDD หรือไม่ก็ตาม


0

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

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

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

public interface ITest {
    public string Name {
        get;
    }
    public string Description {
        get;
    }
    public List<ITest> SubTests {
        get;
    }
    public TestResult Execute();
}

public class TestResult {
    public bool Succesful {
        get;
        set;
    }

    public string ResultMessage {
        get;
        set;
    }

    private Dictionary<ITest, TestResult> subTestResults = new Dictionary<ITest, TestResult>();
    public Dictionary<ITest, TestResult> SubTestResults {
        get {
            return subTestResults;
        }
        set {
            subTestResults = value;
        }
    }
}

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

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

โชคดี!


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

ฉันคิดว่าคุณอาจได้รับประโยชน์จากการใช้ Framework เช่น SubSpec (มันเป็นแรงบันดาลใจ BDD) ดังนั้นจะช่วยให้คุณได้รับ Assert ("SubTest") การแยกขณะทำการแชร์การตั้งค่าบริบท
โยฮันเนสรูดอล์ฟ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.