อ่าน 4 นาที
การทดสอบแบบสุ่ม
การทดสอบแบบสุ่ม เป็น เทคนิค การทดสอบซอฟต์แวร์ แบบกล่องดำ โดยโปรแกรมจะถูกทดสอบโดย การสร้าง อินพุตแบบสุ่มและเป็นอิสระ...
การทดสอบแบบสุ่ม
การทดสอบแบบสุ่มเป็น เทคนิค การทดสอบซอฟต์แวร์แบบกล่องดำ โดยโปรแกรมจะถูกทดสอบโดยการสร้างอินพุตแบบสุ่มและเป็นอิสระ ผลลัพธ์ของเอาต์พุตจะถูกเปรียบเทียบกับข้อกำหนดของซอฟต์แวร์เพื่อตรวจสอบว่าเอาต์พุตการทดสอบผ่านหรือไม่ผ่าน[ 1 ]ในกรณีที่ไม่มีข้อกำหนด จะใช้ ข้อยกเว้นของภาษา ซึ่งหมายความว่าหากเกิดข้อยกเว้นขึ้นระหว่างการดำเนินการทดสอบ แสดงว่ามีข้อผิดพลาดในโปรแกรม นอกจากนี้ยังใช้เป็นวิธีหลีกเลี่ยงการทดสอบที่มีอคติอีกด้วย
ประวัติการทดสอบแบบสุ่ม
การทดสอบแบบสุ่มสำหรับฮาร์ดแวร์ได้รับการตรวจสอบครั้งแรกโดยMelvin Breuerในปี 1971 และความพยายามเบื้องต้นในการประเมินประสิทธิภาพนั้นดำเนินการโดย Pratima และVishwani Agrawalในปี 1975 [ 2 ]
ในด้านซอฟต์แวร์ Duran และ Ntafos ได้ตรวจสอบการทดสอบแบบสุ่มในปี 1984 [ 3 ]
การใช้การทดสอบสมมติฐานเป็นพื้นฐานทางทฤษฎีสำหรับการทดสอบแบบสุ่มได้รับการอธิบายโดย Howden ในFunctional Testing and Analysisหนังสือเล่มนี้ยังมีการพัฒนาสูตรอย่างง่ายสำหรับการประมาณจำนวนการทดสอบnที่จำเป็นเพื่อให้มีความมั่นใจอย่างน้อย 1-1/ nในอัตราความล้มเหลวไม่เกิน 1/n สูตรนี้คือขอบเขตล่างn log nซึ่งบ่งชี้ถึงจำนวนการทดสอบที่ปราศจากความล้มเหลวจำนวนมากที่จำเป็นเพื่อให้มีความมั่นใจแม้เพียงเล็กน้อยในขอบเขตอัตราความล้มเหลวเพียงเล็กน้อย[ 4 ]
ภาพรวม
พิจารณาฟังก์ชัน C++ ต่อไปนี้:
int myAbs ( int x ) { if ( x > 0 ) { return x ; } else { return x ; // ข้อผิดพลาด: ควรเป็น '-x' } }ตอนนี้ค่าทดสอบแบบสุ่มสำหรับฟังก์ชันนี้อาจเป็น {123, 36, -35, 48, 0} เฉพาะค่า '-35' เท่านั้นที่ทำให้เกิดข้อผิดพลาด หากไม่มีการใช้งานอ้างอิงเพื่อตรวจสอบผลลัพธ์ ข้อผิดพลาดก็อาจยังคงไม่ถูกตรวจพบ อย่างไรก็ตาม สามารถเพิ่ม การตรวจสอบผลลัพธ์ได้ เช่น:
void testAbs ( int n ) { for ( int i = 0 ; i < n ; i ++ ) { int x = getRandomInput (); int result = myAbs ( x ); assert ( result >= 0 ); } }บางครั้งอาจมีตัวอย่างการใช้งานอ้างอิงให้ใช้งานได้ เช่น เมื่อต้องการใช้งานอัลกอริธึมอย่างง่ายในรูปแบบที่ซับซ้อนกว่าเพื่อประสิทธิภาพที่ดีขึ้น ตัวอย่างเช่น ในการทดสอบการใช้งานอัลกอริธึม Schönhage–Strassenสามารถใช้การดำเนินการ "*" มาตรฐานกับจำนวนเต็มได้:
int getRandomInput () { // … }void testFastMultiplication ( int n ) { for ( int i = 0 ; i < n ; i ++ ) { long x = getRandomInput (); long y = getRandomInput (); long result = fastMultiplication ( x , y ); assert ( x * y == result ); } }แม้ว่าตัวอย่างนี้จะจำกัดเฉพาะประเภทง่ายๆ (ซึ่งสามารถใช้ตัวสร้างแบบสุ่มอย่างง่ายได้) แต่โดยทั่วไปแล้วเครื่องมือที่มุ่งเป้าไปที่ภาษาเชิงวัตถุจะสำรวจโปรแกรมเพื่อทดสอบและค้นหาตัวสร้าง (ตัวสร้างหรือเมธอดที่ส่งคืนวัตถุของประเภทนั้น) และเรียกใช้โดยใช้ข้อมูลป้อนเข้าแบบสุ่ม (ไม่ว่าจะสร้างขึ้นด้วยวิธีเดียวกันหรือสร้างขึ้นโดยใช้ตัวสร้างแบบสุ่มเทียมหากเป็นไปได้) จากนั้นวิธีการดังกล่าวจะรักษาพูลของวัตถุที่สร้างขึ้นแบบสุ่มและใช้ความน่าจะเป็นในการนำวัตถุที่สร้างขึ้นมาใช้ซ้ำหรือสร้างวัตถุใหม่[ 5 ]
เกี่ยวกับความสุ่ม
อ้างอิงจากบทความสำคัญเกี่ยวกับการทดสอบแบบสุ่มโดย ดี. แฮมเล็ต
[..] ความหมายทางเทคนิคและคณิตศาสตร์ของ "การทดสอบแบบสุ่ม" หมายถึงการขาด "ระบบ" อย่างชัดเจนในการเลือกข้อมูลทดสอบ ดังนั้นจึงไม่มีความสัมพันธ์ระหว่างการทดสอบต่างๆ[ 1 ]
จุดแข็งและจุดอ่อน
การทดสอบแบบสุ่มได้รับการยกย่องในด้านข้อดีดังต่อไปนี้:
- มันใช้งานได้ราคาถูก: ไม่จำเป็นต้องฉลาดล้ำลึกเกี่ยวกับโปรแกรมที่กำลังทดสอบ
- มันไม่มีอคติใดๆ: ต่างจากการทดสอบด้วยตนเอง มันจะไม่มองข้ามข้อผิดพลาดเพราะความเชื่อมั่นที่ผิดที่ผิดทางในโค้ดบางส่วน
- การค้นหาจุดบกพร่องทำได้อย่างรวดเร็ว โดยปกติแล้วจะใช้เวลาเพียงไม่กี่นาทีในการดำเนินการทดสอบ
- หากซอฟต์แวร์ได้รับการกำหนดคุณสมบัติอย่างถูกต้อง: มันจะสามารถค้นหาข้อผิดพลาดที่แท้จริงได้
จุดอ่อนต่อไปนี้ได้รับการอธิบายไว้แล้ว:
- มันตรวจจับได้เฉพาะข้อผิดพลาดพื้นฐานเท่านั้น (เช่น การเข้าถึง ค่าที่ชี้โดยตัวชี้ว่าง )
- ความแม่นยำนั้นขึ้นอยู่กับข้อกำหนด และโดยทั่วไปแล้วข้อกำหนดมักไม่แม่นยำ
- เมื่อเทียบกับเทคนิคอื่นๆ ในการค้นหาข้อผิดพลาด (เช่นการวิเคราะห์โปรแกรมแบบคงที่ ) แล้ว วิธีนี้มีประสิทธิภาพด้อยกว่า
- หากมีการเลือกอินพุตที่แตกต่างกันแบบสุ่มในแต่ละรอบการทดสอบ อาจทำให้เกิดปัญหาในการบูรณาการอย่างต่อเนื่องเนื่องจากการทดสอบเดียวกันจะผ่านหรือล้มเหลวแบบสุ่ม[ 6 ]
- บางคนโต้แย้งว่าการครอบคลุมกรณีที่เกี่ยวข้องทั้งหมดอย่างรอบคอบด้วยการทดสอบที่สร้างขึ้นด้วยตนเองในลักษณะกล่องขาวจะดีกว่าการพึ่งพาความสุ่ม[ 6 ]
- อาจต้องใช้การทดสอบจำนวนมากเพื่อให้ได้ระดับความเชื่อมั่นในระดับปานกลางในอัตราความล้มเหลวในระดับปานกลาง ตัวอย่างเช่น จะต้องทำการทดสอบที่ไม่มีความล้มเหลว 459 ครั้งเพื่อให้มีความเชื่อมั่นอย่างน้อย 99% ว่าความน่าจะเป็นของความล้มเหลวน้อยกว่า 1/100 [ 4 ]
ประเภทของการทดสอบแบบสุ่ม
เมื่อพิจารณาจากข้อมูลป้อนเข้า
- การสร้างลำดับอินพุตแบบสุ่ม (เช่น ลำดับการเรียกใช้เมธอด)
- ลำดับการป้อนข้อมูลแบบสุ่ม (บางครั้งเรียกว่าการทดสอบแบบสุ่ม) - เช่น ลำดับการเรียกใช้เมธอดแบบสุ่ม
- การเลือกข้อมูลแบบสุ่มจากฐานข้อมูลที่มีอยู่
แบบมีไกด์เทียบกับแบบไม่มีไกด์
- การสร้างชุดทดสอบแบบสุ่มโดยไม่มีทิศทาง - โดยไม่มีฮิวริสติกส์ใด ๆ มาช่วยชี้นำการค้นหา
- การสร้างการทดสอบแบบสุ่มที่กำหนดทิศทาง - เช่น "การสร้างการทดสอบแบบสุ่มที่กำหนดทิศทางตามผลตอบรับ" [ 7 ]และ "การทดสอบแบบสุ่มที่ปรับตัวได้" [ 8 ]
การนำไปใช้
เครื่องมือบางอย่างที่ใช้การทดสอบแบบสุ่ม:
- QuickCheck - เครื่องมือทดสอบที่มีชื่อเสียง ซึ่งเดิมพัฒนาขึ้นสำหรับภาษา Haskellแต่ได้รับการดัดแปลงให้ใช้งานได้กับภาษาอื่นๆ อีกมากมาย โดยจะสร้างลำดับการเรียกใช้ API แบบสุ่มตามแบบจำลอง และตรวจสอบคุณสมบัติของระบบที่ควรเป็นจริงหลังจากการทำงานแต่ละครั้ง
- Randoop - สร้างลำดับของการเรียกใช้เมธอดและคอนสตรัคเตอร์สำหรับคลาสที่กำลังทดสอบ และสร้าง การทดสอบ JUnitจากลำดับเหล่านั้น
- Simulant - เครื่องมือ Clojureที่ใช้จำลองสถานการณ์ของเอเจนต์ต่างๆ (เช่น ผู้ใช้ที่มีพฤติกรรมแตกต่างกัน) โดยอิงตามแบบจำลองทางสถิติของพฤติกรรมนั้น บันทึกการกระทำและผลลัพธ์ทั้งหมดลงในฐานข้อมูลเพื่อการตรวจสอบและยืนยันในภายหลัง
- AutoTest - เครื่องมือที่รวมอยู่ใน EiffelStudio สำหรับทดสอบโค้ด Eiffel โดยอัตโนมัติด้วยสัญญาตามต้นแบบการวิจัยที่มีชื่อเดียวกัน[ 5 ]
- York Extensible Testing Infrastructure (YETI) - เครื่องมือที่ไม่ขึ้นกับภาษาโปรแกรมใดๆ และรองรับภาษาโปรแกรมหลากหลาย (Java, JML, CoFoJa, .NET, C, Kermeta)
- GramTest - เครื่องมือทดสอบแบบสุ่มที่ใช้หลักไวยากรณ์ เขียนด้วยภาษา Java โดยใช้สัญกรณ์ BNF ในการระบุไวยากรณ์อินพุต
วิจารณ์
การทดสอบแบบสุ่มมีขอบเขตการใช้งานเฉพาะทางในทางปฏิบัติเท่านั้น ส่วนใหญ่เป็นเพราะหาออราเคิลที่มีประสิทธิภาพได้ยาก รวมถึงความยากลำบากในการกำหนดรูปแบบการทำงานและการสร้างค่าอินพุตแบบสุ่มเทียม[ 1 ]
เครื่องมือตรวจสอบผลลัพธ์ ( Test Oracle)คือเครื่องมือที่ใช้ตรวจสอบว่าผลลัพธ์ตรงกับข้อกำหนดของโปรแกรมหรือไม่ ส่วนโปรไฟล์การใช้งาน (Operation Profile) คือความรู้เกี่ยวกับรูปแบบการใช้งานของโปรแกรม และส่วนใดมีความสำคัญมากกว่ากัน
สำหรับภาษาโปรแกรมและแพลตฟอร์มที่มีสัญญา (เช่น Eiffel, .NET หรือส่วนขยายต่างๆ ของ Java เช่น JML, CoFoJa...) สัญญาทำหน้าที่เป็นออราเคิลตามธรรมชาติ และวิธีการนี้ได้รับการนำไปใช้อย่างประสบความสำเร็จ[ 5 ]โดยเฉพาะอย่างยิ่ง การทดสอบแบบสุ่มจะพบข้อบกพร่องมากกว่าการตรวจสอบด้วยตนเองหรือรายงานของผู้ใช้ (แม้ว่าจะแตกต่างกันก็ตาม) [ 9 ]
ดูเพิ่มเติม
- การทดสอบแบบฟัซ (Fuzz testing) - การทดสอบแบบสุ่มชนิดหนึ่ง ซึ่งป้อนข้อมูลที่ไม่ถูกต้องเข้าไปในโปรแกรมที่กำลังทดสอบ
- การทดสอบหน่วยแบบเป็นระบบที่ยืดหยุ่น #การทดสอบแบบเป็นระบบ - วิธีการที่เป็นระบบในการสำรวจการเรียกใช้เมธอด "ทั้งหมด" ดังที่นำไปใช้โดยJava Path Finder ของ NASA (ซึ่งผสมผสานการทดสอบกับการตรวจสอบแบบจำลองโดยการจำกัดพื้นที่สถานะให้มีขนาดที่เหมาะสมด้วยวิธีการต่างๆ)
- การสร้างตัวเลขสุ่มแบบมีข้อจำกัดใน SystemVerilog
- กรณีพิเศษ
- กรณีพิเศษ
- การทดสอบ Concolic
ลิงก์ภายนอก
- การทดสอบแบบสุ่มโดย Andrea Arcuri
- การทดสอบแบบสุ่มโดย Richard Hamlet ศาสตราจารย์กิตติคุณแห่งมหาวิทยาลัย Portland State University; รายชื่อแหล่งข้อมูลที่มีประโยชน์ในตอนท้ายของเอกสาร
- วิกิการทดสอบแบบสุ่มที่ Cunningham & Cunningham, Inc.
สรุปเนื้อหา
ข้อมูลสำคัญจากบทความ
ข้อมูลสำคัญเกี่ยวกับ การทดสอบแบบสุ่ม
การทดสอบแบบสุ่ม เป็น เทคนิค การทดสอบซอฟต์แวร์ แบบกล่องดำ โดยโปรแกรมจะถูกทดสอบโดย การสร้าง อินพุตแบบสุ่มและเป็นอิสระ...
ประวัติการทดสอบแบบสุ่ม
การทดสอบแบบสุ่มสำหรับฮาร์ดแวร์ได้รับการตรวจสอบครั้งแรกโดย Melvin Breuer ในปี 1971 และความพยายามเบื้องต้นในการประเมินประสิทธิภาพนั้นดำเนินการโดย Pratima และ Vishwani Agrawal ในปี 1975 [ 2 ]
เกี่ยวกับความสุ่ม
อ้างอิงจากบทความสำคัญเกี่ยวกับการทดสอบแบบสุ่มโดย ดี. แฮมเล็ต
จุดแข็งและจุดอ่อน
การทดสอบแบบสุ่มได้รับการยกย่องในด้านข้อดีดังต่อไปนี้: