จะปรับปรุงการครอบคลุมโค้ดอย่างมากได้อย่างไร?


21

ฉันได้รับมอบหมายให้รับแอปพลิเคชันรุ่นเก่าภายใต้การทดสอบหน่วย เริ่มจากพื้นฐานเกี่ยวกับแอปพลิเคชั่น: เป็นฐานรหัส LOC Java RCP 600k ที่มีปัญหาสำคัญเหล่านี้

  • การทำสำเนารหัสจำนวนมาก
  • ไม่มีการห่อหุ้มข้อมูลส่วนตัวส่วนใหญ่สามารถเข้าถึงได้จากภายนอกข้อมูลทางธุรกิจบางส่วนยังสร้างซิงเกิลตันดังนั้นจึงไม่เพียง แต่เปลี่ยนแปลงจากภายนอก แต่ยังมาจากทุกที่
  • ไม่มี abstractions (เช่นไม่มีโมเดลธุรกิจข้อมูลธุรกิจถูกเก็บไว้ใน Object [] และ double [] []) ดังนั้นจึงไม่มี OO

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

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


ทำไมไม่สร้างการทดสอบการถดถอยโดยอัตโนมัติและตรวจสอบทีละรายการ? ต้องเร็วกว่าการเขียนทั้งหมดด้วยมือ
Robert Harvey

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

1
@dodgy_coder ปกติแล้วเห็นด้วย แต่ฉันหวังว่า QA แบบดั้งเดิมที่ทำงานได้อย่างมีประสิทธิภาพจะปลอดภัยฉันสักครู่
Peter Kofler

1
@dodgy_coder Michael C. Feathers ผู้แต่งทำงานอย่างมีประสิทธิภาพด้วยรหัส Legacy กำหนดรหัส Legacy เป็น "รหัสโดยไม่ต้องทดสอบ" มันทำหน้าที่เป็นคำจำกัดความที่มีประโยชน์
StuperUser

คำตอบ:


10

ฉันเชื่อว่ามีสองแกนหลักพร้อมรหัสที่สามารถวางเมื่อมันมาถึงการแนะนำการทดสอบหน่วย: ก) รหัสทดสอบได้อย่างไร? และ B) มันมีเสถียรภาพแค่ไหน (เช่นต้องมีการทดสอบอย่างเร่งด่วน) หรือไม่? ดูที่สุดขั้วเท่านั้นผลตอบแทนนี้มี 4 หมวดหมู่:

  1. รหัสที่ง่ายต่อการทดสอบและเปราะ
  2. รหัสที่ง่ายต่อการทดสอบและมีเสถียรภาพ
  3. รหัสที่ยากต่อการทดสอบและเปราะ
  4. รหัสที่ยากต่อการทดสอบและเสถียร

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


ยอดเยี่ยม ฉันมีความคิดว่าจะตรวจสอบได้อย่างไรว่าง่ายต่อการตรวจสอบโดยการวิเคราะห์แบบสแตติกเช่นจำนวนการพึ่งพา / Testability Explorer แต่ฉันจะทราบได้อย่างไรว่ารหัสเปราะ? ฉันไม่สามารถจับคู่ข้อบกพร่องกับหน่วยเฉพาะ (เช่นคลาส) และถ้าเป็นหมายเลข 3 ของหลักสูตร (god คลาส / singletons) ดังนั้นจำนวนเช็คอิน (ฮอตสปอต) อาจจะเป็นจำนวน?
Peter Kofler

1
@Peter Kofler: การกำหนดฮอตสปอตเป็นความคิดที่ดี แต่แหล่งข้อมูลที่มีค่าที่สุดของความรู้ประเภทนี้จะเป็นนักพัฒนาซอฟต์แวร์ที่ทำงานกับโค้ด
Michael Borgwardt

1
@ Peter - เหมือนกับที่ Michael กล่าวว่านักพัฒนาซอฟต์แวร์ที่ทำงานกับโค้ด ทุกคนที่ทำงานกับ codebase ขนาดใหญ่ในเวลาพอสมควรจะรู้ว่าส่วนไหนของกลิ่น หรือหากสิ่งที่ทั้งกลิ่นซึ่งบางส่วนของมันจริงๆกลิ่นเหม็น
Carson63000

15

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

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

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

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

เป้าหมายที่สมจริงคือ "ตั้งแต่เราติดตั้ง UT แล้วการแทรกข้อบกพร่องในโมดูลภายใต้การทดสอบได้ลดลงเหลือ x% ของที่ไม่ได้อยู่ภายใต้ UT" (ในอุดมคติ x คือตัวเลข <100)


+1 คุณไม่สามารถทดสอบบางสิ่งได้อย่างมีประสิทธิภาพหากไม่มีมาตรฐานที่แข็งแกร่งกว่าโค้ด
dan_waterworth

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

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

2

ฉันเตือนว่าไม่ต้องกังวลเกี่ยวกับประตูโรงนาเมื่อม้าได้ปิดแล้ว

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

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

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

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


1

วิธีหนึ่งในการปรับปรุงความครอบคลุมคือการเขียนการทดสอบเพิ่มเติม

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

ลองนึกภาพคุณมีบล็อคโค้ด 3 แบบคือ a, b และ b 'โดยที่ b' คือสำเนาที่ซ้ำกัน (สำเนาที่ถูกต้องหรือใกล้พลาด) ของ B และคุณมีความครอบคลุมใน a และ b แต่ไม่ใช่ b 'กับการทดสอบ T

หาก refactor ฐานรหัสเพื่อกำจัด b 'โดยการแยก commonality จาก b และ b' เป็น B ตอนนี้รหัสฐานดูเหมือน a, b0, B, b'0 โดยที่ b0 ประกอบด้วยรหัสที่ไม่ได้รับการจัดสรรด้วย b'0 และรอง ในทางกลับกันและทั้ง b0 และ b'0 นั้นเล็กกว่า B มากและเรียกใช้ / ใช้ B

ตอนนี้ฟังก์ชั่นของโปรแกรมไม่เปลี่ยนแปลงและไม่มีการทดสอบ T ดังนั้นเราจึงสามารถรัน T อีกครั้งและคาดว่าจะผ่าน รหัสที่ครอบคลุมในขณะนี้คือ a, b0 และ B แต่ไม่ใช่ b'0 รหัสฐานมีขนาดเล็กลง (b'0 น้อยกว่า b '!) และเรายังคงครอบคลุมสิ่งที่เราครอบคลุมในตอนแรก อัตราส่วนความครอบคลุมของเราเพิ่มขึ้น

ในการทำเช่นนี้คุณต้องหา b, b 'และ B เพื่อให้ refactoring เครื่องมือCloneDRของเราสามารถทำได้หลายภาษาโดยเฉพาะรวมถึง Java คุณว่าฐานรหัสของคุณมีรหัสซ้ำกันมากมาย นี่อาจเป็นวิธีที่ดีในการจัดการกับผลประโยชน์ของคุณ

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

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