- เป็นบทความที่ค่อนข้างมีประโยชน์สำหรับตัวเอง
- เก็บบันทึก log ตัวเองไว้ก่อนเลย
การทดสอบ (Test) โปรแกรมที่เราเขียนว่าทำงานได้อย่างถูกต้องหรือไม่นั้น ถือว่าเป็นขั้นตอนที่สำคัญขั้นตอนหนึ่งในการพัฒนาซอฟแวร์ (Software Development) การทดสอบโปรแกรมก็มีหลายระดับด้วยกันตั้งแต่ ทดสอบโปรแกรมย่อย (Unit Test) ไปจนถึงทดสอบระบบโดยรวมทั้งหมด (System Test)
ปกติ แล้วการทดสอบโปรแกรมแต่ละครั้งเราจะต้องเขียนสิ่งที่เราจะทดสอบและขั้นตอน การทดสอบอย่างละเอียดไว้ก่อนที่เราจะทดสอบโปรแกรม ซึ่งเราเรียกสิ่งนี้ว่า เทสเคส (Test Case) แล้วเทสเคสกับทฤษฎีกราฟ (Graph Theory) มาเกี่ยวกันได้ยังไงนั้น เรามาดูกัน
ซอสโค้ด = กราฟ
ซอสโค้ด (Source Code) ของโปรแกรมที่เราเขียนขึ้นนั้น เราสามารถที่จะเปลี่ยนคำสั่งต่างๆ ให้อยู่ในรูปของกราฟได้ โดยให้แต่ละคำสั่งเป็นโหนด (Node) ของกราฟและเส้นทางที่แต่ละคำสั่งถูกเรียกเป็นเส้นเชื่อมระหว่างโหนด (Edge) ดังรูปที่ 1
ลองมาดูตัวอย่างต่อไปนี้กัน ผมจะสร้างกราฟจากซอสโค้ดชุดหนึ่งซึ่งประกอบไปด้วย คำสั่งที่เป็นเงื่อนไขและคำนวนตัวเลขต่างๆ ดังนี้
if(score >= 80)
{
printf(”Grade A”);
}
else if((score => 60) && (score < 80))
{
printf(”Grade B”);
}
else
{
printf(”Grade C”);
}
จากซอสโค้ดข้างต้นเราจะเปลี่ยนแต่ละคำสั่งไปเป็นโหนด เราจะได้ 6 โหนดด้วยกันคือ
- score >= 80
- printf(”Grade A”)
- score => 60
- score <>
- printf(”Grade B”)
- printf(”Grade C”)
หลังจากที่เราได้โหนดแล้วเราก็มาสร้างเส้นเชื่อมแต่ละโหนดกัน โดยสร้างจากเส้นทาง (Path) ทั้งหมดที่เป็นไปได้ที่แต่ละคำสั่งจะถูกเรียก กราฟที่เราจะใช้หาเทสเคสจะต้องเป็นกราฟแบบมีทิศทาง ซึ่งจะได้ผลลัพธ์ดังรูปที่ 2
กราฟ = เทสเคส
ขั้นตอนต่อมาเราก็จะใช้กราฟที่ได้นั้นมาหาเทสเคสที่เป็นไปได้ทั้งหมด โดยการท่องไปแต่ละโหนดของกราฟ (Graph Traversing) แบบเชิงลึก (Depth-First Search) หลักการง่ายๆของการท่องกราฟแบบเชิงลึกก็คือ ถ้าเราพบว่าโหนดที่เรามาถึงมีเส้นเชื่อมต่ออยู่กับโหนดอื่นก็ให้ท่องไปยัง โหนดนั้นต่อ ทำอย่างนี้ไปเรื่อยๆ จนกระทั้งไม่มีโหนดให้เราท่องอีกต่อไป ถ้าโหนดนั้นมีเส้นเชื่อมมากกว่าหนึ่ง เราก็อาจจะไปทางขวาหรือทางซ้ายล่างสุดที่ต่อกับโหนดนั้นก่อนแล้วค่อยกลับมา ที่โหนดเดิมแล้วเริ่มท่องไปยังเส้นเชื่อมถัดไป
เราลองมาท่องกราฟใน รูปที่ 2 ดูกัน โดยไปทางขวาสุดก่อน เราจะพบว่ามีเส้นทางที่เป็นไปได้ 3 เส้นทางด้วยกัน ซึ่งแต่ละเส้นทางเท่ากับ 1 เทสเคสนั้นเอง
- (1) -> (2)
- (1) -> (3) -> (4) -> (5)
- (1) -> (3) -> (6)
จากเส้นทางที่ได้ทั้งหมดข้างต้นนั้น เราจะเห็นได้ว่ามีหลายเส้นทางที่มีลำดับของโหนดเหมือนกันบางส่วน เช่น (1) -> (3) ตรงส่วนที่เหมือนกันนี้จะเป็นประโยชน์ในเวลาที่เราเขียนสิ่งที่จะต้องทดสอบ ในแต่ละเทสเคส ช่วยลดความซ้ำซ้อนของสิ่งที่จะต้องทดสอบได้ สุดท้ายเราก็จะได้เทสเคสดังตัวอย่างตามตารางข้างล่างนี้
เทสเคสที่ | เงื่อนไข | ผลลัพธ์ |
---|---|---|
1 | score >= 80 | พิมพ์ “Grade A” |
2 | score >= 60 และ score <> | พิมพ์ “Grade B” |
3 | score <> | พิมพ์ “Grade C” |
การ ใช้กราฟในการหาเทสเคสนั้นอาจจะดูยุ่งยากในตอนแรก แต่ถ้าเราใช้จนชำนาญแล้วจะพบว่ามีประโยชน์มากๆ และทำให้เทสเคสทั้งหมดของเราครอบคลุมการทำงานที่เป็นไปได้ทั้งหมดของโปรแกรม ช่วยลดความผิดพลาดของโปรแกรมได้ดียิ่งขึ้นในเวลาที่ใช้งาน
ก่อนจบบทความนี้มีเรื่องที่ต้องเน้นไว้นิดหนึ่งว่า เวลาที่เราแปลงคำสั่งที่มีตัวดำเนินการทางตรรกะ (Logical Operator) เช่น && หรือ || มาเกี่ยวข้องนั้น จะทำให้ได้เส้นทางของกราฟต่างกัน เช่น ในซอสโค้ดตัวอย่างก่อนหน้านี้ถ้าเรา เปลี่ยนจาก (score >= 60) && (score <>= 60) || (score <>
ใน รูปที่ 3 เราจะเห็นเส้นประจากโหนดที่ 3 ไปยังโหนดที่ 6 ก็เพราะว่า || ทำให้เส้นทางไปยังโหนดที่ 6 หายไป เนื่องจากทุกๆ ค่าของ score จะทำให้เส้นทางไปสิ้นสุดที่โหนด 2 และ 5 เท่านั้น
No comments:
Post a Comment