การทดสอบยูนิต
ส่วนหนึ่งของซีรีส์เรื่อง |
การพัฒนาซอฟต์แวร์ |
---|
การทดสอบยูนิตหรือที่เรียกว่า การทดสอบ ส่วนประกอบหรือโมดูลเป็นรูปแบบหนึ่งของการทดสอบซอฟต์แวร์โดยจะทดสอบโค้ด ต้นฉบับที่แยกออกมาเพื่อตรวจสอบพฤติกรรมที่คาดหวัง [1]
การทดสอบยูนิตอธิบายการทดสอบที่ดำเนินการในระดับยูนิตเพื่อเปรียบเทียบการทดสอบในระดับการบูรณาการหรือระดับ ระบบ
ประวัติศาสตร์
การทดสอบยูนิตเป็นหลักการในการทดสอบส่วนย่อยแยกกันของระบบซอฟต์แวร์ขนาดใหญ่ซึ่งมีมาตั้งแต่ยุคแรกๆ ของวิศวกรรมซอฟต์แวร์ ในเดือนมิถุนายน พ.ศ. 2500 HD Benington ได้นำเสนอโครงการSAGEและแนวทางตามข้อมูลจำเพาะในงานสัมมนาเรื่องวิธีการเขียนโปรแกรมขั้นสูงสำหรับคอมพิวเตอร์ดิจิทัลของกองทัพเรือสหรัฐฯ โดยขั้นตอนการเข้ารหัสจะตามด้วย "การทดสอบพารามิเตอร์" เพื่อตรวจสอบโปรแกรมย่อยของส่วนประกอบตามข้อมูลจำเพาะ จากนั้นจึงตามด้วย "การทดสอบการประกอบ" สำหรับส่วนประกอบที่ประกอบเข้าด้วยกัน[2] [3]
ในปี 1964 มีการอธิบายแนวทางที่คล้ายกันสำหรับซอฟต์แวร์ของโครงการ Mercuryโดยที่หน่วยแต่ละหน่วยที่พัฒนาโดยโปรแกรมต่างๆ จะต้องผ่าน "การทดสอบหน่วย" ก่อนที่จะรวมเข้าด้วยกัน[4] ในปี 1969 วิธีการทดสอบดูเหมือนจะมีโครงสร้างมากขึ้น โดยมีการทดสอบหน่วย การทดสอบส่วนประกอบ และการทดสอบการรวมเข้าด้วยกันเพื่อจุดประสงค์ในการตรวจสอบชิ้นส่วนแต่ละชิ้นที่เขียนแยกกันและการประกอบชิ้นส่วนเหล่านั้นเป็นบล็อกที่ใหญ่ขึ้น[5] มาตรฐานสาธารณะบางมาตรฐานได้รับการนำมาใช้ในช่วงปลายทศวรรษปี 1960 เช่น MIL-STD-483 [6]และ MIL-STD-490 ซึ่งยิ่งส่งผลให้การทดสอบหน่วยในโครงการขนาดใหญ่ได้รับการยอมรับอย่างกว้างขวางยิ่งขึ้น
การทดสอบยูนิตในสมัยนั้นเป็นแบบโต้ตอบ[3]หรืออัตโนมัติ[7] โดยใช้การทดสอบแบบเข้ารหัสหรือเครื่องมือทดสอบการบันทึกและเล่นซ้ำ ในปี 1989 Kent Beckได้อธิบายกรอบการทดสอบสำหรับSmalltalk (ต่อมาเรียกว่าSUnit ) ใน "Simple Smalltalk Testing: With Patterns" ในปี 1997 Kent BeckและErich Gammaได้พัฒนาและเผยแพร่JUnitซึ่งเป็นกรอบการทดสอบยูนิตที่ได้รับความนิยมในหมู่ผู้พัฒนาJava [8] Googleเริ่มนำการทดสอบอัตโนมัติมาใช้ในช่วงปี 2005–2006 [9]
หน่วย
หน่วยถูกกำหนดให้เป็นพฤติกรรมเดี่ยวที่แสดงโดยระบบภายใต้การทดสอบ (SUT) ซึ่งโดยปกติจะสอดคล้องกับข้อกำหนด แม้ว่าอาจหมายถึงว่าเป็นฟังก์ชันหรือโมดูล (ในการเขียนโปรแกรมเชิงขั้นตอน ) หรือเป็นวิธีการหรือคลาส (ในการเขียนโปรแกรมเชิงวัตถุ ) แต่ไม่ได้หมายความว่าฟังก์ชัน/วิธีการ โมดูลหรือคลาสจะสอดคล้องกับหน่วยเสมอ จากมุมมองของข้อกำหนดของระบบ มีเพียงขอบเขตของระบบเท่านั้นที่เกี่ยวข้อง ดังนั้น จุดเข้าสู่พฤติกรรมของระบบที่มองเห็นได้จากภายนอกเท่านั้นที่จะกำหนดหน่วย[10]
การดำเนินการ
การทดสอบยูนิตสามารถดำเนินการได้ด้วยตนเองหรือผ่าน การดำเนินการ ทดสอบอัตโนมัติการทดสอบอัตโนมัติมีข้อดี เช่น การดำเนินการทดสอบบ่อยครั้ง การดำเนินการทดสอบโดยไม่ต้องเสียค่าเจ้าหน้าที่ และการทดสอบที่สม่ำเสมอและทำซ้ำได้
การทดสอบมักจะดำเนินการโดยโปรแกรมเมอร์ที่เขียนและแก้ไขโค้ดที่ทดสอบ การทดสอบยูนิตอาจถือได้ว่าเป็นส่วนหนึ่งของกระบวนการเขียนโค้ด
เกณฑ์การทดสอบ
ในระหว่างการพัฒนา โปรแกรมเมอร์อาจเข้ารหัสเกณฑ์ หรือผลลัพธ์ที่ทราบว่าดี ลงในการทดสอบ เพื่อตรวจสอบความถูกต้องของหน่วย
ระหว่างการดำเนินการทดสอบ เฟรมเวิร์กจะบันทึกการทดสอบที่ไม่ผ่านเกณฑ์ใดๆ และรายงานผลในสรุป
แนวทางที่ใช้กันทั่วไปที่สุดสำหรับเรื่องนี้คือ การทดสอบ - ฟังก์ชัน - ค่าที่คาดหวัง
กรณีทดสอบ
ทดสอบคู่
การทดสอบแบบพารามิเตอร์
การทดสอบแบบกำหนดพารามิเตอร์คือการทดสอบที่ยอมรับชุดค่าที่สามารถใช้เพื่อให้การทดสอบทำงานด้วยค่าอินพุตที่แตกต่างกันหลายค่า กรอบการทำงานการทดสอบที่รองรับการทดสอบแบบกำหนดพารามิเตอร์รองรับวิธีการเข้ารหัสชุดพารามิเตอร์และเรียกใช้การทดสอบด้วยชุดพารามิเตอร์แต่ละชุด
การใช้การทดสอบแบบกำหนดพารามิเตอร์สามารถลดการซ้ำซ้อนของโค้ดทดสอบได้
การทดสอบแบบพารามิเตอร์ได้รับการรองรับโดยTestNG , JUnit , [13] XUnitและNUnitเช่นเดียวกับกรอบงานการทดสอบ JavaScript ต่างๆ[ จำเป็นต้องอ้างอิง ]
พารามิเตอร์สำหรับการทดสอบยูนิตอาจเขียนโค้ดด้วยตนเองหรือในบางกรณีกรอบการทดสอบจะสร้างขึ้นโดยอัตโนมัติ ในช่วงไม่กี่ปีที่ผ่านมา มีการเพิ่มการสนับสนุนสำหรับการเขียนการทดสอบยูนิตที่มีประสิทธิภาพมากขึ้น โดยใช้ประโยชน์จากแนวคิดของทฤษฎี กรณีทดสอบที่ดำเนินการตามขั้นตอนเดียวกัน แต่ใช้ข้อมูลทดสอบที่สร้างขึ้นในระหว่างการทำงาน ซึ่งแตกต่างจากการทดสอบแบบพารามิเตอร์ทั่วไปที่ใช้ขั้นตอนการดำเนินการเดียวกันโดยมีชุดอินพุตที่กำหนดไว้ล่วงหน้า[ จำเป็นต้องอ้างอิง ]
คล่องตัว
บางครั้งในการพัฒนาซอฟต์แวร์แบบคล่องตัว การทดสอบยูนิตจะดำเนินการตามเรื่องราวของผู้ใช้และจะเกิดขึ้นในช่วงครึ่งหลังของสปรินต์ หลังจากการรวบรวมข้อกำหนดและการพัฒนาเสร็จสิ้น โดยปกติ นักพัฒนาหรือสมาชิกคนอื่นๆ จากทีมพัฒนา เช่นที่ปรึกษาจะเขียน "สคริปต์ทดสอบ" ทีละขั้นตอนเพื่อให้นักพัฒนานำไปปฏิบัติในเครื่องมือ สคริปต์ทดสอบมักถูกเขียนขึ้นเพื่อพิสูจน์การทำงานที่มีประสิทธิภาพและทางเทคนิคของฟีเจอร์ที่พัฒนาขึ้นเฉพาะในเครื่องมือ ซึ่งแตกต่างจากกระบวนการทางธุรกิจเต็มรูปแบบที่ผู้ใช้ปลายทาง จะเชื่อมต่อ ซึ่งโดยปกติแล้วจะทำในระหว่างการทดสอบการยอมรับของผู้ใช้หากสามารถดำเนินการสคริปต์ทดสอบได้อย่างสมบูรณ์ตั้งแต่ต้นจนจบโดยไม่มีเหตุการณ์ใดๆ การทดสอบยูนิตจะถือว่า "ผ่าน" มิฉะนั้น จะถือว่ามีข้อผิดพลาด และเรื่องราวของผู้ใช้จะถูกย้ายกลับไปยังการพัฒนาในสถานะ "อยู่ระหว่างดำเนินการ" เรื่องราวของผู้ใช้ที่ผ่านการทดสอบยูนิตสำเร็จจะถูกย้ายไปยังขั้นตอนสุดท้ายของสปรินต์ ซึ่งได้แก่ การตรวจสอบโค้ด การตรวจสอบโดยเพื่อนร่วมงาน และสุดท้ายคือเซสชัน "แสดงให้ผู้มีส่วนได้ส่วนเสียเห็น" เครื่องมือที่พัฒนาขึ้น
การพัฒนาที่ขับเคลื่อนด้วยการทดสอบ
ในการพัฒนาที่ขับเคลื่อนด้วยการทดสอบ (TDD) การทดสอบยูนิตจะถูกเขียนในขณะที่โค้ดการผลิตถูกเขียนขึ้น เริ่มต้นด้วยโค้ดที่ใช้งานได้ นักพัฒนาจะเพิ่มโค้ดทดสอบสำหรับพฤติกรรมที่จำเป็น จากนั้นจึงเพิ่ม โค้ด ให้เพียงพอเพื่อให้การทดสอบผ่าน จากนั้นจึงรีแฟกเตอร์โค้ด (รวมถึงโค้ดทดสอบ) ตามความเหมาะสม จากนั้นจึงทำซ้ำโดยเพิ่มการทดสอบอีกครั้ง
ค่า
การทดสอบยูนิตมีวัตถุประสงค์เพื่อให้แน่ใจว่ายูนิตต่างๆ ตรงตามการออกแบบและทำงานตามที่ตั้งใจไว้[14]
การเขียนการทดสอบก่อนสำหรับหน่วยที่ทดสอบได้เล็กที่สุด จากนั้นจึงทำการทดสอบพฤติกรรมรวมระหว่างหน่วยเหล่านั้น จะทำให้สามารถสร้างการทดสอบที่ครอบคลุมสำหรับแอปพลิเคชันที่ซับซ้อนได้[14]
เป้าหมายหนึ่งของการทดสอบยูนิตคือการแยกแต่ละส่วนของโปรแกรมและแสดงให้เห็นว่าส่วนต่างๆ นั้นถูกต้อง[1]การทดสอบยูนิตจะกำหนดสัญญาที่ เป็นลายลักษณ์อักษรที่เข้มงวด ซึ่งชิ้นส่วนของโค้ดจะต้องเป็นไปตามนั้น
การตรวจจับปัญหาในระยะเริ่มต้นในวงจรการพัฒนา
การทดสอบยูนิตจะค้นหาปัญหาตั้งแต่ช่วงต้นของวงจรการพัฒนาซึ่งรวมถึงทั้งจุดบกพร่องในการใช้งานของโปรแกรมเมอร์และข้อบกพร่องหรือส่วนที่ขาดหายไปของข้อกำหนดสำหรับยูนิต กระบวนการเขียนชุดการทดสอบที่ครอบคลุมบังคับให้ผู้เขียนต้องคิดผ่านอินพุต เอาต์พุต และเงื่อนไขข้อผิดพลาด และด้วยเหตุนี้ จึงสามารถกำหนดพฤติกรรมที่ต้องการของยูนิตได้ชัดเจนยิ่งขึ้น[ จำเป็นต้องอ้างอิง ]
ลดต้นทุน
ต้นทุนในการค้นหาจุดบกพร่องก่อนเริ่มเขียนโค้ดหรือเมื่อเขียนโค้ดครั้งแรกนั้นต่ำกว่าต้นทุนในการตรวจจับ ระบุ และแก้ไขจุดบกพร่องในภายหลังอย่างมาก จุดบกพร่องในโค้ดที่เผยแพร่ยังอาจทำให้เกิดปัญหาที่ต้องเสียค่าใช้จ่ายสูงสำหรับผู้ใช้ปลายทางของซอฟต์แวร์อีกด้วย[15] [16] [17]โค้ดอาจทดสอบยูนิตไม่ได้หรือยากหากเขียนไม่ดี ดังนั้น การทดสอบยูนิตจึงสามารถบังคับให้ผู้พัฒนาต้องจัดโครงสร้างฟังก์ชันและอ็อบเจ็กต์ให้ดีขึ้น
ออกบ่อยขึ้น
การทดสอบยูนิตช่วยให้สามารถเผยแพร่ซอฟต์แวร์ได้บ่อยขึ้น โดยการทดสอบส่วนประกอบแต่ละส่วนแยกกัน นักพัฒนาสามารถระบุและแก้ไขปัญหาได้อย่างรวดเร็ว ส่งผลให้รอบการทำซ้ำและการเผยแพร่เร็วขึ้น[18]
อนุญาตให้ทำการรีแฟกเตอร์โค้ด
การทดสอบยูนิตช่วยให้โปรแกรมเมอร์สามารถรีแฟกเตอร์โค้ดหรืออัปเกรดไลบรารีระบบในภายหลัง และตรวจสอบว่าโมดูลยังคงทำงานได้อย่างถูกต้อง (เช่น ในการทดสอบการถดถอย ) ขั้นตอนคือการเขียนกรณีทดสอบสำหรับฟังก์ชันและวิธีการ ทั้งหมด เพื่อให้สามารถระบุได้อย่างรวดเร็วเมื่อการเปลี่ยนแปลงทำให้เกิดข้อผิดพลาด
ตรวจจับการเปลี่ยนแปลงที่อาจละเมิดสัญญาการออกแบบ
การทดสอบยูนิตตรวจจับการเปลี่ยนแปลงซึ่งอาจละเมิดสัญญาการออกแบบ
ลดความไม่แน่นอน
การทดสอบยูนิตอาจช่วยลดความไม่แน่นอนในยูนิตต่างๆ ได้ และสามารถใช้ใน แนวทางการทดสอบ แบบล่างขึ้นบนได้การทดสอบส่วนต่างๆ ของโปรแกรมก่อนแล้วจึงทดสอบผลรวมของส่วนต่างๆ จะทำให้ การทดสอบบูรณาการง่ายขึ้นมาก[ จำเป็นต้องมีการอ้างอิง ]
เอกสารประกอบพฤติกรรมระบบ
โปรแกรมเมอร์บางคนโต้แย้งว่าการทดสอบยูนิตเป็นรูปแบบหนึ่งของเอกสารประกอบของโค้ด นักพัฒนาที่ต้องการเรียนรู้ว่ายูนิตมีฟังก์ชันการทำงานอะไรบ้าง และจะใช้งานอย่างไร สามารถทบทวนการทดสอบยูนิตเพื่อทำความเข้าใจได้[ จำเป็นต้องอ้างอิง ]
กรณีทดสอบสามารถแสดงถึงลักษณะเฉพาะที่สำคัญต่อความสำเร็จของหน่วย ลักษณะเฉพาะเหล่านี้อาจบ่งชี้ถึงการใช้หน่วยอย่างเหมาะสม/ไม่เหมาะสม ตลอดจนพฤติกรรมเชิงลบที่หน่วยนั้นจะต้องเผชิญ กรณีทดสอบจะบันทึกลักษณะเฉพาะที่สำคัญเหล่านี้ แม้ว่าสภาพแวดล้อมการพัฒนาซอฟต์แวร์จำนวนมากจะไม่พึ่งพาโค้ดเพียงอย่างเดียวในการบันทึกผลิตภัณฑ์ในการพัฒนาก็ตาม[ จำเป็นต้องมีการอ้างอิง ]
ในบางกระบวนการ การเขียนการทดสอบและโค้ดที่ทดสอบ รวมถึงการปรับโครงสร้างใหม่ที่เกี่ยวข้องอาจเข้ามาแทนที่การออกแบบอย่างเป็นทางการ การทดสอบยูนิตแต่ละครั้งสามารถมองได้ว่าเป็นองค์ประกอบการออกแบบที่ระบุคลาส วิธีการ และพฤติกรรมที่สังเกตได้[ จำเป็นต้องอ้างอิง ]
ข้อจำกัดและข้อเสีย
การทดสอบจะไม่สามารถตรวจจับข้อผิดพลาดทั้งหมดในโปรแกรมได้ เนื่องจากไม่สามารถประเมินเส้นทางการทำงานทั้งหมดในโปรแกรมใดๆ ได้ ยกเว้นโปรแกรมที่ไม่สำคัญที่สุดปัญหา นี้ เป็นปัญหาย่อยของปัญหาการหยุดทำงานซึ่งไม่สามารถตัดสินใจได้เช่นเดียวกับการทดสอบยูนิต นอกจากนี้ ตามคำจำกัดความ การทดสอบยูนิตจะทดสอบเฉพาะฟังก์ชันการทำงานของยูนิตเท่านั้น ดังนั้น การทดสอบยูนิตจะไม่สามารถตรวจจับข้อผิดพลาดในการรวมระบบหรือข้อผิดพลาดในระดับระบบที่กว้างขึ้นได้ (เช่น ฟังก์ชันที่ดำเนินการในยูนิตหลายยูนิต หรือพื้นที่การทดสอบที่ไม่ใช่ฟังก์ชัน เช่นประสิทธิภาพ ) การทดสอบยูนิตควรทำร่วมกับ กิจกรรม การทดสอบซอฟต์แวร์ อื่นๆ เนื่องจากกิจกรรมเหล่านี้สามารถแสดงการมีอยู่หรือไม่มีข้อผิดพลาดเฉพาะเท่านั้น ไม่สามารถพิสูจน์ได้ว่าไม่มีข้อผิดพลาดอย่างสมบูรณ์ เพื่อรับประกันการทำงานที่ถูกต้องสำหรับเส้นทางการทำงานและอินพุตที่เป็นไปได้ทั้งหมด และเพื่อให้แน่ใจว่าไม่มีข้อผิดพลาด จำเป็นต้องใช้เทคนิคอื่นๆ เช่น การใช้วิธีการอย่างเป็นทางการเพื่อพิสูจน์ว่าส่วนประกอบซอฟต์แวร์ไม่มีพฤติกรรมที่ไม่คาดคิด[ จำเป็นต้องอ้างอิง ]
ลำดับชั้นที่ซับซ้อนของการทดสอบยูนิตไม่ได้เท่ากับการทดสอบบูรณาการ การบูรณาการกับยูนิตรอบข้างควรรวมอยู่ในการทดสอบบูรณาการ แต่ไม่ใช่ในการทดสอบยูนิต[ จำเป็นต้องมีการอ้างอิง ]การทดสอบบูรณาการโดยทั่วไปยังคงต้องอาศัยการทดสอบโดยมนุษย์ด้วยมือ เป็นอย่างมาก การทดสอบระดับสูงหรือขอบเขตทั่วโลกอาจทำอัตโนมัติได้ยาก ดังนั้นการทดสอบด้วยตนเองจึงมักดูเร็วกว่าและถูกกว่า[ จำเป็นต้องมีการอ้างอิง ]
การทดสอบซอฟต์แวร์เป็นปัญหาเชิงผสมผสาน ตัวอย่างเช่น คำสั่งการตัดสินใจแบบบูลีนทุกคำสั่งต้องมีการทดสอบอย่างน้อย 2 ครั้ง ครั้งหนึ่งมีผลลัพธ์เป็น "จริง" และอีกครั้งมีผลลัพธ์เป็น "เท็จ" ดังนั้น โปรแกรมเมอร์จึงมักต้องใช้โค้ดทดสอบ 3 ถึง 5 บรรทัดสำหรับการเขียนโค้ดทุกบรรทัด[ จำเป็นต้องมีการอ้างอิง ]เห็นได้ชัดว่าต้องใช้เวลา และการลงทุนอาจไม่คุ้มกับความพยายาม มีปัญหาบางอย่างที่ไม่สามารถทดสอบได้อย่างง่ายดาย เช่น ปัญหาที่ไม่แน่นอนหรือเกี่ยวข้องกับเธรด หลายเธรด นอกจากนี้ โค้ดสำหรับการทดสอบยูนิตก็มีแนวโน้มที่จะมีข้อบกพร่องเช่นเดียวกับโค้ดที่กำลังทดสอบFred BrooksในThe Mythical Man-Monthกล่าวไว้ว่า: "อย่าออกทะเลพร้อมกับนาฬิกาจับเวลา 2 เรือน ให้ใช้เรือนเดียวหรือ 3 เรือน" [19]หมายความว่า หากนาฬิกาจับเวลา 2 เรือนขัดแย้งกัน คุณจะรู้ได้อย่างไรว่าเรือนไหนถูกต้อง
ความยากลำบากในการตั้งค่าการทดสอบที่สมจริงและเป็นประโยชน์
ความท้าทายอีกประการหนึ่งที่เกี่ยวข้องกับการเขียนการทดสอบยูนิตคือความยากลำบากในการตั้งค่าการทดสอบที่สมจริงและเป็นประโยชน์ จำเป็นต้องสร้างเงื่อนไขเริ่มต้นที่เกี่ยวข้องเพื่อให้ส่วนของแอปพลิเคชันที่กำลังทดสอบทำงานเหมือนเป็นส่วนหนึ่งของระบบทั้งหมด หากไม่ได้ตั้งค่าเงื่อนไขเริ่มต้นเหล่านี้อย่างถูกต้อง การทดสอบจะไม่ใช้โค้ดในบริบทที่สมจริง ซึ่งจะทำให้คุณค่าและความถูกต้องของผลลัพธ์การทดสอบยูนิตลดลง[ จำเป็นต้องอ้างอิง ]
ต้องมีวินัยตลอดกระบวนการพัฒนา
เพื่อให้ได้รับประโยชน์ตามที่ต้องการจากการทดสอบยูนิต จำเป็นต้องมีวินัยที่เข้มงวดตลอดกระบวนการพัฒนาซอฟต์แวร์
ต้องมีการควบคุมเวอร์ชัน
จำเป็นต้องเก็บบันทึกอย่างระมัดระวังไม่เพียงแต่การทดสอบที่ดำเนินการเท่านั้น แต่ยังรวมถึงการเปลี่ยนแปลงทั้งหมดที่เกิดขึ้นกับโค้ดต้นฉบับของหน่วยนี้หรือหน่วยอื่นใดในซอฟต์แวร์ การใช้ ระบบ ควบคุมเวอร์ชันเป็นสิ่งที่จำเป็น หากหน่วยเวอร์ชันใหม่กว่าไม่ผ่านการทดสอบเฉพาะที่เคยผ่านมา ซอฟต์แวร์ควบคุมเวอร์ชันสามารถให้รายการการเปลี่ยนแปลงโค้ดต้นฉบับ (หากมี) ที่ใช้กับหน่วยตั้งแต่นั้นเป็นต้นมา[ จำเป็นต้องอ้างอิง ]
ต้องมีการตรวจสอบเป็นประจำ
นอกจากนี้ ยังจำเป็นที่จะต้องนำกระบวนการที่ยั่งยืนมาใช้เพื่อให้แน่ใจว่าความล้มเหลวของกรณีทดสอบได้รับการตรวจสอบอย่างสม่ำเสมอและดำเนินการแก้ไขทันที[20]หากไม่ได้นำกระบวนการดังกล่าวมาใช้และฝังไว้ในเวิร์กโฟลว์ของทีม แอปพลิเคชันจะพัฒนาไปโดยไม่สอดคล้องกับชุดการทดสอบยูนิต ส่งผลให้ผลลัพธ์บวกปลอมเพิ่มขึ้นและประสิทธิภาพของชุดการทดสอบลดลง
ข้อจำกัดของซอฟต์แวร์ระบบฝังตัว
การทดสอบยูนิตของซอฟต์แวร์ระบบฝังตัวนำเสนอความท้าทายที่ไม่เหมือนใคร เนื่องจากซอฟต์แวร์กำลังได้รับการพัฒนาบนแพลตฟอร์มที่แตกต่างจากแพลตฟอร์มที่จะใช้งานในที่สุด ดังนั้น คุณจึงไม่สามารถรันโปรแกรมทดสอบในสภาพแวดล้อมการปรับใช้จริงได้ทันที ซึ่งเป็นไปได้กับโปรแกรมเดสก์ท็อป[21]
ข้อจำกัดสำหรับการทดสอบการรวมเข้ากับระบบภายนอก
การทดสอบยูนิตมักจะง่ายที่สุดเมื่อวิธีการมีพารามิเตอร์อินพุตและเอาต์พุตบางส่วน การสร้างการทดสอบยูนิตนั้นไม่ใช่เรื่องง่ายเมื่อฟังก์ชันหลักของวิธีการคือการโต้ตอบกับสิ่งภายนอกแอปพลิเคชัน ตัวอย่างเช่น วิธีการที่จะทำงานกับฐานข้อมูลอาจต้องสร้างแบบจำลองการโต้ตอบฐานข้อมูล ซึ่งอาจจะไม่ครอบคลุมเท่ากับการโต้ตอบฐานข้อมูลจริง[22] [ ต้องการแหล่งข้อมูลที่ดีกว่า ]
ตัวอย่าง
จูนิต
ด้านล่างนี้เป็นตัวอย่างชุดการทดสอบ JUnit ซึ่งเน้นที่Adder
คลาส
คลาส Adder { สาธารณะint add ( int a , int b ) { กลับa + b ; } }
ชุดการทดสอบใช้ คำสั่ง assertเพื่อตรวจสอบผลลัพธ์ที่คาดหวังของค่าอินพุตต่างๆ ไปยังsum
วิธีการ
นำเข้าorg.junit.Assert.assertEquals แบบคง ที่; นำเข้าorg.junit.Test ; สาธารณะคลาสAdderUnitTest { @Test สาธารณะvoid sumReturnsZeroForZeroInput () { Adder adder = new Adder (); assertEquals ( 0 , adder .add ( 0 , 0 )); }
@Test
public void sumReturnsSumOfTwoPositiveNumbers () { Adder adder = new Adder ( ); assertEquals ( 3 , adder .add ( 1 , 2 )); }
@Test
public void sumReturnsSumOfTwoNegativeNumbers () { Adder adder = new Adder (); assertEquals ( - 3 , adder.add ( - 1 , - 2 ) ) ; }
@Test
public void sumReturnsSumOfLargeNumbers ( ) { Adder adder = new Adder ( ); assertEquals ( 2222 , adder.add ( 1234,988 ) ) ; } }
ตามข้อกำหนดที่สามารถปฏิบัติได้
การใช้การทดสอบยูนิตเป็นข้อกำหนดการออกแบบมีข้อได้เปรียบที่สำคัญเหนือวิธีการออกแบบอื่นๆ ประการหนึ่ง นั่นคือ สามารถใช้เอกสารการออกแบบ (การทดสอบยูนิตเอง) เพื่อตรวจสอบการใช้งานได้ด้วยตัวเอง การทดสอบจะไม่ผ่านเว้นแต่ผู้พัฒนาจะนำโซลูชันตามการออกแบบไปใช้
การทดสอบยูนิตขาดการเข้าถึงข้อมูลบางส่วนจากไดอะแกรม เช่น ไดอะแกรม UMLแต่ข้อมูลเหล่านี้อาจสร้างขึ้นจากการทดสอบยูนิตโดยใช้เครื่องมืออัตโนมัติ ภาษาสมัยใหม่ส่วนใหญ่มีเครื่องมือฟรี (โดยปกติมีให้ใช้งานเป็นส่วนขยายของIDE ) เครื่องมือฟรี เช่น เครื่องมือที่ใช้ เฟรมเวิร์ก xUnitจะส่งการแสดงผลกราฟิกของมุมมองให้ระบบอื่นใช้งานแทน
แอปพลิเคชั่น
การเขียนโปรแกรมแบบเอ็กซ์ตรีม
การทดสอบยูนิตเป็นรากฐานสำคัญของการเขียนโปรแกรมขั้นสูงซึ่งต้องอาศัยกรอบงานการทดสอบยูนิต อัตโนมัติ กรอบงานการทดสอบยูนิตอัตโนมัตินี้สามารถเป็นของบุคคลภายนอก เช่นxUnitหรือสร้างขึ้นภายในกลุ่มพัฒนาก็ได้
การเขียนโปรแกรมแบบ Extreme จะใช้การสร้างการทดสอบยูนิตสำหรับการพัฒนาที่ขับเคลื่อนด้วยการทดสอบนักพัฒนาเขียนการทดสอบยูนิตที่เปิดเผยข้อกำหนดของซอฟต์แวร์หรือข้อบกพร่อง การทดสอบนี้จะล้มเหลวเนื่องจากข้อกำหนดยังไม่ได้รับการนำไปใช้งานหรือเนื่องจากเปิดเผยข้อบกพร่องในโค้ดที่มีอยู่โดยตั้งใจ จากนั้น นักพัฒนาจึงเขียนโค้ดที่ง่ายที่สุดเพื่อให้การทดสอบผ่านพร้อมกับการทดสอบอื่นๆ
โค้ดส่วนใหญ่ในระบบได้รับการทดสอบยูนิต แต่ไม่จำเป็นต้องทดสอบทุกเส้นทางผ่านโค้ด การเขียนโปรแกรมแบบเอ็กซ์ตรีมกำหนดให้ใช้กลยุทธ์ "ทดสอบทุกสิ่งที่อาจทำลายระบบได้" มากกว่าวิธีการแบบเดิม "ทดสอบทุกเส้นทางการทำงาน" ซึ่งทำให้ผู้พัฒนาต้องพัฒนาการทดสอบน้อยกว่าวิธีแบบคลาสสิก แต่จริงๆ แล้วนี่ไม่ใช่ปัญหา แต่เป็นการระบุข้อเท็จจริงใหม่ เนื่องจากวิธีแบบคลาสสิกแทบจะไม่เคยถูกปฏิบัติตามอย่างเป็นระบบเพียงพอที่จะทดสอบเส้นทางการทำงานทั้งหมดได้อย่างละเอียดถี่ถ้วน[ จำเป็นต้องอ้างอิง ]การเขียนโปรแกรมแบบเอ็กซ์ตรีมตระหนักดีว่าการทดสอบนั้นไม่สามารถทำได้หมด (เนื่องจากมักมีค่าใช้จ่ายสูงและใช้เวลานานเกินกว่าจะคุ้มทุน) และให้คำแนะนำเกี่ยวกับวิธีการมุ่งเน้นทรัพยากรที่มีอยู่อย่างจำกัดอย่างมีประสิทธิภาพ
สิ่งสำคัญคือโค้ดทดสอบถือเป็นสิ่งประดิษฐ์ระดับโปรเจ็กต์ชั้นหนึ่ง เนื่องจากโค้ดดังกล่าวได้รับการดูแลรักษาให้มีคุณภาพเทียบเท่ากับโค้ดที่ใช้งานจริง โดยไม่มีการซ้ำซ้อนใดๆ นักพัฒนาจะเผยแพร่โค้ดทดสอบยูนิตไปยังที่เก็บโค้ดร่วมกับโค้ดที่ทดสอบ การทดสอบยูนิตอย่างละเอียดถี่ถ้วนของ Extreme Programming ช่วยให้ได้รับประโยชน์ที่กล่าวถึงข้างต้น เช่น การพัฒนาและการรีแฟกเตอร์ โค้ดที่ง่ายและมั่นใจมากขึ้น การรวมโค้ดที่เรียบง่ายขึ้น เอกสารประกอบที่แม่นยำ และการออกแบบโมดูลาร์มากขึ้น การทดสอบยูนิตเหล่านี้ยังดำเนินการอย่างต่อเนื่องเป็นรูปแบบหนึ่งของการทดสอบการถดถอย
การทดสอบยูนิตยังมีความสำคัญต่อแนวคิดของการออกแบบแบบฉุกเฉินเนื่องจากการออกแบบแบบฉุกเฉินนั้นขึ้นอยู่กับการรีแฟกเตอร์เป็นอย่างมาก การทดสอบยูนิตจึงเป็นส่วนประกอบที่สำคัญ[ จำเป็นต้องมีการอ้างอิง ]
กรอบการทำงานการทดสอบอัตโนมัติ
กรอบการทำงานการทดสอบอัตโนมัติมีคุณลักษณะสำหรับการดำเนินการทดสอบอัตโนมัติและสามารถเร่งความเร็วในการเขียนและการรันการทดสอบได้ กรอบการทำงานได้รับการพัฒนาสำหรับ ภาษาการเขียน โปรแกรม ที่หลากหลาย
โดยทั่วไป เฟรมเวิร์กจะเป็นของบุคคลที่สามไม่ได้แจกจ่ายพร้อมกับคอมไพเลอร์หรือสภาพแวดล้อมการพัฒนาแบบบูรณาการ (IDE)
การทดสอบสามารถเขียนได้โดยไม่ต้องใช้กรอบงานเพื่อใช้ทดสอบโค้ดโดยใช้การยืนยันการจัดการข้อยกเว้นและ กลไก การควบคุมการไหล อื่นๆ เพื่อตรวจสอบพฤติกรรมและรายงานความล้มเหลว บางคนสังเกตว่าการทดสอบโดยไม่ใช้กรอบงานนั้นมีประโยชน์เนื่องจากมีอุปสรรคในการนำกรอบงานมาใช้ การมีการทดสอบบางอย่างดีกว่าไม่มีเลย แต่เมื่อมีกรอบงานแล้ว การเพิ่มการทดสอบอาจทำได้ง่ายขึ้น[23]
ในกรอบงานบางกรอบไม่มีฟีเจอร์การทดสอบขั้นสูงและจะต้องเขียนโค้ดด้วยมือ
การรองรับการทดสอบหน่วยระดับภาษา
ภาษาการเขียนโปรแกรมบางภาษารองรับการทดสอบยูนิตโดยตรง ไวยากรณ์ของภาษาเหล่านี้ช่วยให้สามารถประกาศการทดสอบยูนิตได้โดยตรงโดยไม่ต้องนำเข้าไลบรารี (ไม่ว่าจะเป็นไลบรารีของบุคคลที่สามหรือมาตรฐาน) นอกจากนี้ เงื่อนไขบูลีนของการทดสอบยูนิตสามารถแสดงในรูปแบบเดียวกับนิพจน์บูลีนที่ใช้ในโค้ดที่ไม่ใช่การทดสอบยูนิต เช่นคำสั่ง
ที่ใช้สำหรับ if
อะไรwhile
ภาษาที่มีการรองรับการทดสอบยูนิตในตัวได้แก่:
ภาษาที่มีการสนับสนุนกรอบการทดสอบยูนิตมาตรฐาน ได้แก่:
ภาษาบางภาษาไม่มีการรองรับการทดสอบยูนิตในตัว แต่มีไลบรารีหรือกรอบงานสำหรับการทดสอบยูนิตที่จัดทำขึ้น ภาษาเหล่านี้ได้แก่:
- เอบีเอพี
- ซี++
- ซี#
- โคลจูร์[33]
- ยาอายุวัฒนะ
- ชวา
- จาวาสคริปต์
- วัตถุประสงค์-C
- เพิร์ล
- พีเอชพี
- พาวเวอร์เชลล์[34]
- Rกับการทดสอบว่า
- สกาล่า
- ทีซีแอล
- วิชวลเบสิค .NET
- Xojoกับ XojoUnit
ดูเพิ่มเติม
- การทดสอบการยอมรับ
- การทดสอบลักษณะเฉพาะ
- การทดสอบการใช้งานตามส่วนประกอบ
- การออกแบบคำทำนาย
- ออกแบบตามสัญญา
- การเขียนโปรแกรมแบบเอ็กซ์ตรีม
- การทดสอบฟังก์ชัน
- การทดสอบการบูรณาการ
- รายชื่อกรอบการทำงานการทดสอบยูนิต
- การทดสอบการถดถอย
- โบราณคดีซอฟต์แวร์
- การทดสอบซอฟต์แวร์
- การทดสอบระบบ
- กรณีทดสอบ
- การพัฒนาที่ขับเคลื่อนด้วยการทดสอบ
- xUnit – กลุ่มกรอบการทำงานสำหรับการทดสอบยูนิต
อ้างอิง
- ^ โดย Kolawa, Adam; Huizinga, Dorota (2007). การป้องกันข้อบกพร่องอัตโนมัติ: แนวทางปฏิบัติที่ดีที่สุดในการจัดการซอฟต์แวร์ . Wiley-IEEE Computer Society Press. หน้า 75 ISBN 978-0-470-04212-0-
- ^ Benington, Herbert D. (1956). "การผลิตโปรแกรมคอมพิวเตอร์ขนาดใหญ่" เอกสารการประชุมเชิงปฏิบัติการเรื่องวิธีการเขียนโปรแกรมขั้นสูงสำหรับคอมพิวเตอร์ดิจิทัล วอชิงตัน ดี.ซี. 28-29 มิถุนายน 1956สำนักงานวิจัยกองทัพเรือ กองทัพเรือ: 15–28
- ^ ab Benington, HD (1 มีนาคม 1987). "การผลิตโปรแกรมคอมพิวเตอร์ขนาดใหญ่ (พิมพ์ซ้ำเอกสารปี 1956 พร้อมคำนำที่ปรับปรุงใหม่)" Proceedings of the 9th International Conference on Software Engineering ICSE '87. Washington, DC, USA: IEEE Computer Society Press: 299–310. ISBN 978-0-89791-216-7-
- ^ Donegan, James J.; Packard, Calvin; Pashby, Paul (1 มกราคม 1964). "ประสบการณ์กับระบบคอมพิวเตอร์ Goddard ระหว่างภารกิจการบินอวกาศที่มีมนุษย์ควบคุม" Proceedings of the 19th ACM national conference 1964 ACM '64. นครนิวยอร์ก รัฐนิวยอร์ก สหรัฐอเมริกา: สมาคมเครื่องจักรคำนวณ หน้า 12.101–12.108 doi :10.1145/800257.808889 ISBN 978-1-4503-7918-2-
- ^ Zimmerman, Norman A. (26 สิงหาคม 1969). "System integration as a programming function". Proceedings of the 1969 24th national conference . ACM '69. New York, NY, USA: Association for Computing Machinery. pp. 459–467. doi :10.1145/800195.805951. ISBN 978-1-4503-7493-4-
- ^ MIL-STD-483 มาตรฐานทางทหาร: แนวทางการจัดการการกำหนดค่าสำหรับระบบ อุปกรณ์ อาวุธ และโปรแกรมคอมพิวเตอร์สหรัฐอเมริกา กระทรวงกลาโหม 31 ธันวาคม 1970 หน้า 3.4.7.2
ผู้รับเหมาจะต้องเข้ารหัสและทดสอบหน่วยซอฟต์แวร์ และป้อนรหัสต้นฉบับและรหัสวัตถุ และรายการที่เกี่ยวข้องของแต่ละหน่วยที่ทดสอบสำเร็จลงในการกำหนดค่าการพัฒนา
{{cite book}}
: CS1 maint: date and year (link) - ^ Tighe, Michael F. (1 มกราคม 1978). "คุณค่าของวิธีการประกันคุณภาพซอฟต์แวร์ที่เหมาะสม". ACM SIGMETRICS Performance Evaluation Review . 7 (3–4): 165–172. doi :10.1145/1007775.811118. ISSN 0163-5999.
- ^ Gulati, Shekhar (2017). Java Unit Testing with JUnit 5 : Test Driven Development with JUnit 5. Rahul Sharma. Berkeley, CA: Apress. หน้า 8 ISBN 978-1-4842-3015-2.OCLC1012347252 .
- ^ Winters, Titus (2020). วิศวกรรมซอฟต์แวร์ที่ Google: บทเรียนที่เรียนรู้จากการเขียนโปรแกรมในช่วงเวลาต่างๆ . Tom Manshreck, Hyrum Wright (พิมพ์ครั้งที่ 1). Sebastopol, CA: O'Reilly. ISBN 978-1-4920-8274-3.OCLC1144086840 .
- ^ เบ็ค, เคนท์ (2002). การพัฒนาที่ขับเคลื่อนด้วยการทดสอบโดยตัวอย่าง . แอดดิสัน-เวสลีย์ISBN 978-0321146533-
- ^ ระบบและวิศวกรรมซอฟต์แวร์ -- คำศัพท์ . Iso/Iec/IEEE 24765:2010(E). 1 ธันวาคม 2010. หน้า 1–418. doi :10.1109/IEEESTD.2010.5733835. ISBN 978-0-7381-6205-8-
- ^ Kaner, Cem (พฤษภาคม 2003). "What Is a Good Test Case?" (PDF) . STAR East : 2.
- ^ Gulati & Sharma 2560, หน้า 133–137, บทที่ §7 โมเดลส่วนขยาย JUnit 5 - การทดสอบพารามิเตอร์
- ^ ab Hamill, Paul (2004). กรอบการทดสอบยูนิต: เครื่องมือสำหรับการพัฒนาซอฟต์แวร์คุณภาพสูง O'Reilly Media, Inc. ISBN 9780596552817-
- ^ Boehm, Barry W. ; Papaccio, Philip N. (ตุลาคม 1988). "การทำความเข้าใจและการควบคุมต้นทุนซอฟต์แวร์" (PDF) . IEEE Transactions on Software Engineering . 14 (10): 1462–1477. doi :10.1109/32.6191. เก็บถาวรจากแหล่งเดิม(PDF)เมื่อ 9 ตุลาคม 2016 . สืบค้นเมื่อ 13 พฤษภาคม 2016 .
- ^ "ทดสอบอย่างรวดเร็วและบ่อยครั้ง". Microsoft
- ^ “พิสูจน์ว่ามันใช้งานได้: การใช้กรอบการทำงานการทดสอบยูนิตสำหรับการทดสอบและการตรวจสอบซอฟต์แวร์” National Instruments . 21 สิงหาคม 2017.
- ^ Erik (10 มีนาคม 2023). "คุณยังไม่รู้วิธีทำการทดสอบยูนิต (และความลับของคุณก็ปลอดภัยกับฉัน)". Stackify . สืบค้นเมื่อ10 มีนาคม 2023 .
- ^ Brooks, Frederick J. (1995) [1975]. The Mythical Man-Month . Addison-Wesley. หน้า 64. ISBN 978-0-201-83595-3-
- ^ daVeiga, Nada (6 กุมภาพันธ์ 2008). "เปลี่ยนโค้ดโดยไม่ต้องกลัว : ใช้ตาข่ายนิรภัยการถดถอย" สืบค้นเมื่อ8 กุมภาพันธ์ 2008
- ^ Kucharski, Marek (23 พฤศจิกายน 2011). "การทำให้การทดสอบยูนิตเป็นประโยชน์สำหรับการพัฒนาแบบฝังตัว" สืบค้นเมื่อ20 กรกฎาคม 2020
- ^ "การทดสอบยูนิตและฐานข้อมูล" . สืบค้นเมื่อ29 มกราคม 2024 .
- ^ Bullseye Testing Technology (2006–2008). "Intermediate Coverage Goals" . สืบค้นเมื่อ24 มีนาคม 2009 .
- ^ "Unit Tests - D Programming Language". D Programming Language . D Language Foundation . สืบค้นเมื่อ5 สิงหาคม 2017 .
- ^ Steve Klabnik และ Carol Nichols พร้อมด้วยความช่วยเหลือจาก Rust Community (2015–2023). "How to Write Tests" สืบค้นเมื่อ21 สิงหาคม 2023
- ^ "Crystal Spec". crystal-lang.org . สืบค้นเมื่อ18 กันยายน 2017 .
- ^ "การทดสอบ - ภาษาการเขียนโปรแกรม Go". golang.org . สืบค้นเมื่อ3 ธันวาคม 2013 .
- ^ "การทดสอบยูนิต · ภาษาจูเลีย". docs.julialang.org . สืบค้นเมื่อ15 มิถุนายน 2022 .
- ^ เอกสาร Python (2016). "unittest -- กรอบการทำงานการทดสอบยูนิต" . สืบค้นเมื่อ18 เมษายน 2016 .
- ^ Welsh, Noel; Culpepper, Ryan. "RackUnit: การ ทดสอบยูนิต". PLT Design Inc. สืบค้นเมื่อ26 กุมภาพันธ์ 2019
- ^ Welsh, Noel; Culpepper, Ryan. "แพ็คเกจ RackUnit Unit Testing ส่วนหนึ่งของระบบจำหน่ายหลักของ Racket". PLT Design Inc. สืบค้นเมื่อ26กุมภาพันธ์2019
- ^ "มินิเทส (Ruby 2.0)" Ruby-Doc.org
- ^ Sierra, Stuart. "API สำหรับclojure.test - Clojure v1.6 (เสถียร)" สืบค้นเมื่อ11 กุมภาพันธ์ 2558
- ^ "Pester Framework". GitHub . สืบค้นเมื่อ28 มกราคม 2016 .
อ่านเพิ่มเติม
- Feathers, Michael C. (2005). การทำงานอย่างมีประสิทธิภาพด้วย Legacy Codeอัปเปอร์แซดเดิลริเวอร์ รัฐนิวเจอร์ซี: Prentice Hall Professional Technical Reference ISBN 978-0131177055-
- Gulati, Shekhar; Sharma, Rahul (2017). การทดสอบยูนิต Java ด้วย JUnit 5 . Apress .
ลิงค์ภายนอก
- การพัฒนาที่ขับเคลื่อนด้วยการทดสอบ (Ward Cunningham's Wiki)