การครอบคลุมเส้นทางรับประกันการค้นหาข้อบกพร่องทั้งหมดหรือไม่


64

หากทุกเส้นทางผ่านโปรแกรมได้รับการทดสอบแล้วไม่รับประกันว่าจะหาข้อบกพร่องทั้งหมดหรือไม่?

ถ้าไม่ทำไมไม่ คุณจะผ่านทุกขั้นตอนการทำงานของโปรแกรมและไม่พบปัญหาหากมีอยู่ได้อย่างไร

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

หมายเหตุ: บทความนี้จะให้ข้อมูลสรุปสั้น ๆ เกี่ยวกับประเภทความคุ้มครองตามที่ฉันคิดถึง


33
นี่คือเทียบเท่ากับลังเลปัญหา

31
จะเกิดอะไรขึ้นถ้ารหัสที่ควรจะอยู่ที่นั่นไม่ใช่
RemcoGerlich

6
@Snowman: ไม่มันไม่ใช่ มันเป็นไปไม่ได้ที่จะแก้ปัญหาการหยุดชะงักสำหรับทุกโปรแกรม แต่สำหรับหลาย ๆ โปรแกรมมันสามารถแก้ไขได้ สำหรับโปรแกรมเหล่านี้เส้นทางของรหัสทั้งหมดสามารถระบุได้ในระยะเวลาที่ จำกัด
Jørgen Fogh

3
@ JørgenFogh แต่เมื่อพยายามหาจุดบกพร่องในโปรแกรมใด ๆมันไม่เป็นที่ทราบแน่ชัดว่าโปรแกรมนั้นหยุดทำงานหรือไม่? คำถามนี้ไม่ใช่คำถามเกี่ยวกับวิธีการทั่วไปของ "การค้นหาข้อบกพร่องทั้งหมดในโปรแกรมใด ๆ ผ่านการครอบคลุมเส้นทาง" หรือไม่? ในกรณีนี้มันไม่คล้ายกับ "การค้นหาว่าโปรแกรมหยุดทำงานหรือไม่"
Andres F.

1
@AndresF ไม่เป็นที่รู้จักเฉพาะในกรณีที่โปรแกรมหยุดทำงานหากชุดย่อยของภาษาที่เขียนนั้นมีความสามารถในการแสดงโปรแกรมที่ไม่หยุดชะงัก หากโปรแกรมของคุณเขียนใน C โดยไม่ต้องใช้ลูป / เรียกซ้ำ / setjmp ฯลฯ หรือใน Coq หรือใน ESSL ก็จะต้องหยุดและเส้นทางทั้งหมดสามารถติดตาม (ทัวริงสมบูรณ์ถูก overrated อย่างจริงจัง)
Leushenko

คำตอบ:


128

หากทุกเส้นทางผ่านโปรแกรมได้รับการทดสอบแล้วไม่รับประกันว่าจะหาข้อบกพร่องทั้งหมดหรือไม่?

ไม่

ถ้าไม่ทำไมไม่ คุณจะผ่านทุกขั้นตอนการทำงานของโปรแกรมและไม่พบปัญหาหากมีอยู่ได้อย่างไร

เพราะแม้ว่าคุณทดสอบเป็นไปได้ทั้งหมดเส้นทางที่คุณยังไม่ได้ทดสอบพวกเขาด้วยความเป็นไปได้ทั้งหมดค่าหรือเป็นไปได้ทั้งหมดรวมกันของค่า ตัวอย่างเช่น (pseudocode):

def Add(x as Int32, y as Int32) as Int32:
   return x + y

Test.Assert(Add(2, 2) == 4) //100% test coverage
Add(MAXINT, 5) //Throws an exception, despite 100% test coverage

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

- EW Dijkstra (เน้นเพิ่มเขียนเมื่อปี 1988 ตอนนี้เป็นเวลามากกว่า 2 ทศวรรษแล้ว)


7
@digitgopher: ฉันคิดว่า แต่ถ้าโปรแกรมไม่มีอินพุตมันมีประโยชน์อะไรบ้าง?
Mason Wheeler

34
นอกจากนี้ยังมีความเป็นไปได้ของการทดสอบการรวมที่ขาดหายไปข้อบกพร่องในการทดสอบข้อบกพร่องในการอ้างอิงข้อบกพร่องในระบบการสร้าง / การปรับใช้หรือข้อบกพร่องในข้อกำหนด / ข้อกำหนดดั้งเดิม คุณไม่สามารถรับประกันได้ว่าจะพบข้อบกพร่องทั้งหมด
Ixrec

11
@Ixrec: SQLite ใช้ความพยายามอย่างกล้าหาญ แต่ดูสิว่าความพยายามครั้งใหญ่มันคืออะไร! ไม่น่าจะปรับขนาดได้ดีกับฐานรหัสขนาดใหญ่
Mason Wheeler

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

14
ความทรงจำของฉัน (สนับสนุนโดยงานเขียนเช่นนี้ ) คือ Dijkstra เชื่อว่าในการปฏิบัติการเขียนโปรแกรมที่ดีหลักฐานที่แสดงว่าโปรแกรมนั้นถูกต้อง (ภายใต้เงื่อนไขทั้งหมด) ควรเป็นส่วนสำคัญของการพัฒนาโปรแกรมในตอนแรก เมื่อมองจากมุมมองนั้นการทดสอบก็เหมือนการเล่นแร่แปรธาตุ ฉันคิดว่านี่เป็นความเห็นที่แข็งแกร่งมากในภาษาที่แข็งแกร่ง
David K

71

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

ลองนึกภาพคุณมี testuite ที่ครอบคลุมเส้นทาง 100% ตอนนี้ลบการยืนยันทั้งหมดและเรียกใช้ Testuite อีกครั้ง ตอนนี้, Testuite ยังคงมีความครอบคลุมเส้นทาง 100% แต่มันไม่มีอะไรทดสอบอย่างแน่นอน


2
มันสามารถตรวจสอบให้แน่ใจว่าไม่มีข้อยกเว้นเมื่อเรียกรหัสที่ทดสอบแล้ว (โดยมีพารามิเตอร์ในการทดสอบ) นี่เป็นอะไรที่มากกว่าเล็กน้อย
Paŭlo Ebermann

7
@ PaŭloEbermannเห็นด้วยเล็กน้อยมากกว่าอะไร อย่างไรก็ตามมันน้อยกว่า "การค้นหาข้อบกพร่องทั้งหมด";)
Andres F.

1
@ PaŭloEbermann: ข้อยกเว้นเป็นเส้นทางรหัส หากรหัสสามารถโยน แต่ด้วยข้อมูลการทดสอบบางอย่างไม่ได้โยนการทดสอบจะไม่ได้รับความครอบคลุมเส้นทาง 100% สิ่งนี้ไม่เฉพาะเจาะจงกับข้อยกเว้นในฐานะกลไกการจัดการข้อผิดพลาด Visual Basic ของยังเป็นเส้นทางที่เป็นซีON ERROR GOTO if(errno)
MSalters

1
@Malters ฉันกำลังพูดถึงรหัสที่ (ตามข้อกำหนด) ไม่ควรโยนข้อยกเว้นใด ๆ โดยไม่คำนึงถึงการป้อนข้อมูล ถ้ามันพ่นใด ๆ นั่นจะเป็นข้อผิดพลาด แน่นอนถ้าคุณมีรหัสที่ระบุให้มีข้อยกเว้นควรทดสอบ (และแน่นอนตามที่Jörgพูดเพียงตรวจสอบว่ารหัสไม่ได้เกิดข้อยกเว้นมักจะไม่เพียงพอที่จะตรวจสอบให้แน่ใจว่ามันทำในสิ่งที่ถูกต้องแม้สำหรับรหัสที่ไม่ได้ขว้างทิ้ง) และข้อยกเว้นบางอย่างอาจถูกโยนโดย - เส้นทางรหัสที่มองเห็นได้เช่นสำหรับตัวชี้โมฆะ null หรือการหารด้วยศูนย์ เครื่องมือครอบคลุมเส้นทางของคุณจับสิ่งเหล่านั้นหรือไม่
Paŭlo Ebermann

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

34

นี่เป็นตัวอย่างที่ง่ายกว่าในการปัดเศษสิ่งต่างๆออก พิจารณาอัลกอริทึมการเรียงลำดับต่อไปนี้ (ใน Java):

int[] sort(int[] x) { return new int[] { x[0] }; }

ตอนนี้มาทดสอบกัน:

sort(new int[] { 0xCAFEBABE });

ตอนนี้ให้พิจารณาว่า (A) การเรียกเฉพาะนี้เพื่อsortส่งกลับผลลัพธ์ที่ถูกต้อง (B) การทดสอบโค้ดทั้งหมดได้รับการครอบคลุม

แต่เห็นได้ชัดว่าโปรแกรมไม่ได้เรียงลำดับ

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


12

พิจารณาabsฟังก์ชั่นที่คืนค่าสัมบูรณ์ของตัวเลข นี่คือการทดสอบ (Python ลองนึกภาพกรอบการทดสอบบางส่วน):

def test_abs_of_neg_number_returns_positive():
    assert abs(-3) == 3

การใช้งานนี้ถูกต้อง แต่ได้รับความคุ้มครองรหัส 60% เท่านั้น:

def abs(x):
    if x < 0:
        return -x
    else:
        return x

การใช้งานนี้ผิด แต่ได้รับการครอบคลุมโค้ด 100%:

def abs(x):
    return -x

2
นี่คือการติดตั้งอื่น ๆ ที่ผ่านการทดสอบ (โปรดยกโทษให้กับผู้ที่ไม่ได้ใช้งานทางสายโทรศัพท์): def abs(x): if x == -3: return 3 else: return 0คุณสามารถแยกelse: return 0ส่วนและรับความคุ้มครองได้ 100% แต่ฟังก์ชั่นจะไร้ประโยชน์เป็นหลักแม้ว่ามันจะผ่านการทดสอบหน่วย
CVn

7

นอกจากนี้อีกคำตอบของเมสันพฤติกรรมของโปรแกรมอาจขึ้นอยู่กับสภาพแวดล้อมรันไทม์

รหัสต่อไปนี้มี Use-After-Free:

int main(void)
{
    int* a = malloc(sizeof(a));
    int* b = a;
    *a = 0;
    free(a);
    *b = 12; /* UAF */
    return 0;
}

รหัสนี้เป็นพฤติกรรมที่ไม่ได้กำหนดขึ้นอยู่กับการกำหนดค่า (release | debug), ระบบปฏิบัติการและคอมไพเลอร์มันจะให้ผลพฤติกรรมที่แตกต่างกัน ไม่เพียง แต่ครอบคลุมพื้นที่เท่านั้นไม่รับประกันว่าคุณจะพบ UAF แต่ชุดทดสอบของคุณจะไม่ครอบคลุมพฤติกรรมที่เป็นไปได้ของ UAF ที่ขึ้นอยู่กับการกำหนดค่า

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

int main(int a, int b)
{
    if (a != b) {
        if (cryptohash(a) == cryptohash(b)) {
            return ERROR;
        }
    }
    return 0;
} 

หากชุดทดสอบของคุณสามารถสร้างเส้นทางทั้งหมดสำหรับสิ่งนี้แสดงความยินดีกับคุณว่าเป็นผู้เข้ารหัส


ง่ายสำหรับจำนวนเต็มขนาดเล็กที่เพียงพอ :)
CodesInChaos

cryptohashเป็นการยากที่จะพูดว่า "พอเพียงเล็กน้อย" โดยไม่รู้อะไรเลย อาจใช้เวลาสองวันในการดำเนินการกับ supercalculator แต่ใช่จะกลับออกไปจะเป็นเพียงเล็กน้อยint short
dureuill

ด้วยจำนวนเต็ม 32 บิตและแฮชการเข้ารหัสลับทั่วไป (SHA2, SHA3 เป็นต้น) การคำนวณนี้น่าจะค่อนข้างถูก สองสามวินาทีหรือมากกว่านั้น
CodesInChaos

7

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

อีกวิธีหนึ่งในการตอบคำถามนี้คือจากการปฏิบัติ:

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

คำถามที่เกี่ยวข้องจึงคือ:

จุดครอบคลุมของเครื่องมือครอบคลุมโค้ดคืออะไร?

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

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

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

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

นั่นคือเทียบเท่ากับกิริยาตอบสนองที่เหมาะสมกับการเย็บการตรวจสอบการสะกดคำว่ามันทุกคำสภาพอากาศหรือปมมันเป็นคำที่เหมาะสมทั้งหมด ผลที่ได้คือความสับสน

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


+1 ฉันชอบคำตอบนี้เพราะมันสร้างสรรค์และกล่าวถึงประโยชน์ของการครอบคลุม
Andres F.

4

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


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

@eis - คุณไม่เห็นปัญหากับผลิตภัณฑ์ที่เอกสารระบุว่าทำ X ได้จริงหรือไม่? นั่นเป็นคำจำกัดความที่ค่อนข้างแคบของ "บั๊ก" เมื่อฉันจัดการ QA สำหรับสายผลิตภัณฑ์ C ++ ของ Borland เราไม่ได้ใจดีขนาดนั้น
Pete Becker

ฉันไม่เห็นสาเหตุที่เอกสารจะบอกว่าทำ X หากไม่เคยนำมาใช้เลย
eis

@eis - หากการออกแบบดั้งเดิมเรียกว่าสำหรับฟีเจอร์ X เอกสารอาจจบลงด้วยการอธิบายฟีเจอร์ X หากไม่มีใครใช้มันนั่นเป็นข้อผิดพลาดและการครอบคลุมเส้นทาง (หรือการทดสอบกล่องดำชนิดอื่น) จะไม่พบมัน
Pete Becker

อ๊ะครอบคลุมเส้นทางเป็นกล่องสีขาวการทดสอบไม่ได้กล่องดำ การทดสอบกล่องสีขาวไม่สามารถตรวจพบคุณสมบัติที่ขาดหายไป
Pete Becker

4

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

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


ตกลงว่าเป็นส่วนหนึ่งของปัญหา แต่ปัญหาที่แท้จริงเป็นพื้นฐานมากกว่านั้น แม้ว่าจะมีคอมพิวเตอร์เชิงทฤษฎีที่มีหน่วยความจำที่ไม่มีที่สิ้นสุดและไม่มีการทำงานพร้อมกัน แต่การครอบคลุมการทดสอบ 100% ไม่ได้หมายความว่าไม่มีข้อบกพร่อง ตัวอย่างเล็กน้อยของคำตอบมากมายที่นี่ แต่นี่เป็นอีก: ถ้าโปรแกรมของฉันtimes_two(x) = x + 2นี้จะถูกครอบคลุมโดยชุดทดสอบassert(times_two(2) == 4)แต่นี่ก็ยังเป็นรหัสรถ! ไม่ต้องการหน่วยความจำรั่ว :)
Andres F.

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

จุดดี. ตกลง
Andres F.

3

หากทุกเส้นทางผ่านโปรแกรมได้รับการทดสอบแล้วไม่รับประกันว่าจะหาข้อบกพร่องทั้งหมดหรือไม่?

ดังที่ได้กล่าวไปแล้วคำตอบคือไม่

ถ้าไม่ทำไมไม่

นอกจากสิ่งที่กำลังพูดมีข้อบกพร่องปรากฏในระดับต่าง ๆ ซึ่งไม่สามารถทดสอบด้วยการทดสอบหน่วย เพียงพูดถึงไม่กี่:

  • ข้อบกพร่องติดกับการทดสอบการรวม (การทดสอบหน่วยไม่ควรใช้ทรัพยากรจริงหลังจากทั้งหมด)
  • ข้อบกพร่องในความต้องการ
  • ข้อบกพร่องในการออกแบบและสถาปัตยกรรม

2

การทดสอบทุกเส้นทางหมายความว่าอย่างไร

คำตอบอื่น ๆ นั้นยอดเยี่ยม แต่ฉันต้องการเพิ่มว่าเงื่อนไข "ทุกเส้นทางผ่านโปรแกรมที่ถูกทดสอบ" นั้นไม่ชัดเจน

พิจารณาวิธีนี้:

def add(num1, num2)
  foo = "bar"  # useless statement
  $global += 1 # side effect
  num1 + num2  # actual work
end

หากคุณเขียนการทดสอบที่ยืนยันadd(1, 2) == 3เครื่องมือครอบคลุมรหัสจะบอกคุณว่ามีการใช้งานทุกบรรทัด แต่คุณไม่ได้ยืนยันอะไรเลยเกี่ยวกับผลข้างเคียงของโลกหรือการมอบหมายที่ไร้ประโยชน์ บรรทัดเหล่านั้นดำเนินการแล้วแต่ยังไม่ได้รับการทดสอบจริง ๆ

การทดสอบการกลายพันธุ์จะช่วยค้นหาปัญหาเช่นนี้ เครื่องมือทดสอบการกลายพันธุ์จะมีรายการวิธีที่กำหนดไว้ล่วงหน้าเพื่อ "กลายพันธุ์" รหัสและดูว่าการทดสอบยังคงผ่าน ตัวอย่างเช่น:

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

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

การทดสอบทุกครั้งที่เราทำได้คือการวิเคราะห์พฤติกรรมเพื่อไปยังโปรแกรมที่ปราศจากข้อบกพร่อง ไม่มีอะไรสมบูรณ์แบบ.


0

ดี ... ใช่จริง ๆ ถ้าทุกเส้นทาง "ผ่าน" โปรแกรมจะถูกทดสอบ แต่นั่นหมายความว่าทุกเส้นทางที่เป็นไปได้ผ่านพื้นที่ทั้งหมดของสถานะที่เป็นไปได้ทั้งหมดที่โปรแกรมสามารถมีได้รวมถึงตัวแปรทั้งหมด แม้แต่โปรแกรมที่เรียบง่ายที่รวบรวมแบบสแตติก - กล่าวคือ cruncher number ของ Fortran เก่า - ที่ไม่สามารถทำได้แม้ว่าอย่างน้อยก็สามารถจินตนาการได้: ถ้าคุณมีตัวแปรจำนวนเต็มสองตัวคุณจะต้องจัดการกับวิธีที่เป็นไปได้ทั้งหมด กริดสองมิติ จริง ๆ แล้วมันดูเหมือนพนักงานขายเดินทาง สำหรับnตัวแปรเช่นคุณจะจัดการกับnพื้นที่มิติดังนั้นสำหรับโปรแกรมใด ๆ ที่จริงงานคือ untractable สมบูรณ์

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


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

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

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

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

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


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

@MatthewRead: หากคุณใช้สิ่งนี้ดังนั้น "พื้นที่ข้อผิดพลาด" เป็นพื้นที่ย่อยที่เหมาะสมของพื้นที่ของทุกรัฐ แน่นอนว่ามันเป็นสมมติฐานเพราะแม้แต่รัฐ“ ที่ถูกต้อง” ก็ยังมีพื้นที่ขนาดใหญ่เกินไปที่จะทำการทดสอบได้อย่างละเอียดถี่ถ้วน
leftaroundabout
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.