ความซับซ้อนเชิงวัฏจักรในการทดสอบซอฟต์แวร์ พร้อมตัวอย่าง
⚡ สรุปอย่างชาญฉลาด
ความซับซ้อนเชิงวัฏจักร (Cyclomatic Complexity) เป็นตัวชี้วัดทางซอฟต์แวร์ที่พัฒนาโดย Thomas McCabe ในปี 1976 ซึ่งนับจำนวนเส้นทางอิสระในการทำงานของโปรแกรม โดยคำนวณจากกราฟการไหลของควบคุม และให้จำนวนกรณีทดสอบที่จำเป็นสำหรับการครอบคลุมสาขาอย่างสมบูรณ์

ความซับซ้อนของไซโคลมาติกของ McCabe คืออะไร?
ความซับซ้อนของไซโคลมาติกในการทดสอบซอฟต์แวร์ เป็นตัวชี้วัดการทดสอบที่ใช้ในการวัดความซับซ้อนของโปรแกรมซอฟต์แวร์ เป็นการวัดเชิงปริมาณของเส้นทางอิสระในโค้ดต้นฉบับของโปรแกรมซอฟต์แวร์ ความซับซ้อนแบบไซโคลมาติกสามารถคำนวณได้โดยใช้กราฟกระแสควบคุมหรือโดยคำนึงถึงฟังก์ชัน โมดูล วิธีการ หรือคลาสภายในโปรแกรมซอฟต์แวร์
เส้นทางอิสระถูกกำหนดให้เป็นเส้นทางที่มีขอบอย่างน้อยหนึ่งเส้นซึ่งไม่เคยถูกสำรวจมาก่อนในเส้นทางอื่น
ตัวชี้วัดนี้ได้รับการพัฒนาโดย Thomas J. McCabe ในปี 1976 และขึ้นอยู่กับการแสดงโฟลว์การควบคุมของโปรแกรม โฟลว์การควบคุมแสดงโปรแกรมเป็นกราฟซึ่งประกอบด้วยโหนดและขอบ
ในกราฟ โหนดแสดงถึงงานการประมวลผล ในขณะที่ขอบแสดงถึงโฟลว์การควบคุมระหว่างโหนด
สัญกรณ์กราฟการไหลสำหรับโปรแกรม
สัญลักษณ์โฟลว์กราฟสำหรับโปรแกรมจะกำหนดโหนดต่างๆ ที่เชื่อมต่อผ่านขอบ ด้านล่างนี้คือไดอะแกรมโฟลว์สำหรับคำสั่งต่างๆ เช่น if-else, While, until และลำดับโฟลว์ปกติ
วิธีการคำนวณความซับซ้อนของไซโคลมาติก
การเป็นตัวแทนทางคณิตศาสตร์:
ในทางคณิตศาสตร์ มันคือเซตของเส้นทางอิสระที่ผ่านแผนภาพกราฟ Code ความซับซ้อนของโปรแกรมสามารถกำหนดได้โดยใช้สูตร –
V(G) = E - N + 2
ที่ไหน
E – จำนวนขอบ
N – จำนวนโหนด
V (G) = P + 1
โดยที่ P = จำนวนโหนดเพรดิเคต (โหนดที่มีเงื่อนไข)
ตัวอย่าง -
i = 0; n=4; //N-Number of nodes present in the graph while (i<n-1) do j = i + 1; while (j<n) do if A[i]<A[j] then swap(A[i], A[j]); end do; j=j+1; end do;
Flow Graph ของโปรแกรมนี้จะเป็น
การคำนวณทางคณิตศาสตร์
- วี(ก) = 9 – 7 + 2 = 4
- V(G) = 3 + 1 = 4 (โหนดเงื่อนไขคือ 1,2 และ 3 โหนด)
ชุดฐานเส้นทางการดำเนินการอิสระทั้งสี่เส้นทาง:
- 1, 7
- 1, 2, 6, 1, 7
- รถประจำทางสาย 1, 2, 3, 4, 5, 2, 6, 1, 7
- 1, 2, 3, 5, 2, 6, 1, 7
คุณสมบัติของความซับซ้อนเชิงไซโคลมาติก
ต่อไปนี้เป็นคุณสมบัติของความซับซ้อนของไซโคลมาติก:
- V (G) คือจำนวนเส้นทางอิสระสูงสุดในกราฟ
- วี (ช) >=1
- G จะมีเส้นทางเดียวถ้า V (G) = 1
- แนวทางปฏิบัติที่ใช้กันทั่วไปคือการรักษาระดับ V(G) ให้อยู่ที่ 10 หรือต่ำกว่าสำหรับโมดูลเดียว
ตัวชี้วัดนี้มีประโยชน์อย่างไรต่อการทดสอบซอฟต์แวร์
การทดสอบ Basis Path เป็นหนึ่งในเทคนิค White box และรับประกันว่าจะมีการดำเนินการอย่างน้อยหนึ่งคำสั่งในระหว่างการทดสอบ โดยจะตรวจสอบแต่ละเส้นทางที่เป็นอิสระเชิงเส้นผ่านโปรแกรม ซึ่งหมายความว่า จำนวนกรณีทดสอบที่จำเป็นเท่ากับความซับซ้อนเชิงวัฏจักรของโปรแกรม.
เมตริกนี้มีประโยชน์เนื่องจากคุณสมบัติของความซับซ้อนของไซโคลมาติก (M) –
- M สามารถเป็นจำนวนกรณีทดสอบเพื่อให้ครอบคลุมสาขา (Upper Bound)
- M สามารถเป็นจำนวนเส้นทางผ่านกราฟได้ (ขอบเขตล่าง)
ลองพิจารณาตัวอย่างนี้ -
If (Condition 1) Statement 1 Else Statement 2 If (Condition 2) Statement 3 Else Statement 4
ความซับซ้อนของไซโคลมาติกสำหรับโปรแกรมนี้จะเป็น 8-7+2=3
เนื่องจากความซับซ้อนคำนวณไว้ที่ 3 จึงจำเป็นต้องมีกรณีทดสอบ XNUMX กรณีเพื่อให้ครอบคลุมเส้นทางทั้งหมดสำหรับตัวอย่างข้างต้น
ขั้นตอนที่ต้องปฏิบัติตาม
ควรปฏิบัติตามขั้นตอนต่อไปนี้สำหรับการคำนวณความซับซ้อนของ Cyclomatic และการออกแบบกรณีทดสอบ
ขั้นตอนที่ 1 – การสร้างกราฟด้วยโหนดและขอบจากโค้ด
ขั้นตอนที่ 2 – การระบุเส้นทางที่เป็นอิสระ
ขั้นตอนที่ 3 – การคำนวณความซับซ้อนของไซโคลมาติก
ขั้นตอนที่ 4 – การออกแบบกรณีทดสอบ
เมื่อสร้างชุดพื้นฐานแล้ว กรณีทดสอบ ควรเขียนเพื่อดำเนินการทุกเส้นทาง
ข้อมูลเพิ่มเติมเกี่ยวกับวี (G)
หากโปรแกรมมีขนาดเล็ก ความซับซ้อนของไซโคลมาติกสามารถคำนวณได้ด้วยตนเอง หากโปรแกรมมีความซับซ้อนมาก จำเป็นต้องใช้เครื่องมืออัตโนมัติ เนื่องจากต้องมีกราฟการไหลจำนวนมาก ทีมงานสามารถสรุปการดำเนินการที่ต้องดำเนินการเพื่อวัดผลได้จากจำนวนความซับซ้อน
ตารางต่อไปนี้แสดงภาพรวมของหมายเลขความซับซ้อนและความหมายที่สอดคล้องกันของ v (G):
| จำนวนความซับซ้อน | ความหมาย |
|---|---|
| เพื่อ 1 10 |
โค้ดที่มีโครงสร้างและเขียนอย่างดี ความสามารถในการทดสอบสูง ต้นทุนและความพยายามน้อยลง |
| เพื่อ 11 20 |
รหัสที่ซับซ้อน ความสามารถในการทดสอบปานกลาง ค่าใช้จ่ายและความพยายามอยู่ในระดับปานกลาง |
| เพื่อ 21 40 |
โค้ดที่ซับซ้อนมาก ความสามารถในการทดสอบต่ำ ค่าใช้จ่ายและความพยายามสูง |
| > 40 |
ไม่สามารถทดสอบได้เลย ต้นทุนและความพยายามสูงมาก |
เครื่องมือสำหรับการคำนวณความซับซ้อนเชิงวัฏจักร
มีเครื่องมือมากมายสำหรับการกำหนดความซับซ้อนของแอปพลิเคชัน เครื่องมือคำนวณความซับซ้อนบางตัวใช้สำหรับเทคโนโลยีเฉพาะ ความซับซ้อนสามารถพบได้จากจำนวนจุดตัดสินใจในโปรแกรม จุดตัดสินใจได้แก่ คำสั่ง if, for, for-each, while, do, catch, case ในโค้ดต้นฉบับ
ตัวอย่างเครื่องมือได้แก่
- โอคลินท์ – ตัววิเคราะห์โค้ดแบบคงที่สำหรับ C และภาษาที่เกี่ยวข้อง
- SonarQube – รายงานความซับซ้อนทางด้านวัฏจักรและด้านการรับรู้ในกว่า 25 ภาษา
- Visual Studio Code ตัวชี้วัด – การวิเคราะห์ความซับซ้อนเชิงวัฏจักรในตัวสำหรับแอสเซมบลี .NET
- Radon และ Lizard – เครื่องมือวิเคราะห์ความซับซ้อนแบบบรรทัดคำสั่งสำหรับ Python และสำหรับโครงการหลายภาษาตามลำดับ
- จีเมตริกส์ – ค้นหาตัวชี้วัดใน Java แอปพลิเคชันที่เกี่ยวข้อง
การใช้งานความซับซ้อนเชิงวัฏจักร
ความซับซ้อนของไซโคลมาติกอาจพิสูจน์ได้ว่ามีประโยชน์มากใน
- ช่วยให้นักพัฒนาและผู้ทดสอบกำหนดการดำเนินการตามเส้นทางที่เป็นอิสระ
- นักพัฒนาสามารถมั่นใจได้ว่าเส้นทางทั้งหมดได้รับการทดสอบอย่างน้อยหนึ่งครั้งแล้ว
- ช่วยให้เรามุ่งความสนใจไปที่เส้นทางที่เปิดกว้างมากขึ้น
- ปรับปรุงการครอบคลุมโค้ดใน วิศวกรรมซอฟต์แวร์
- ประเมินความเสี่ยงที่เกี่ยวข้องกับแอปพลิเคชันหรือโปรแกรม
- การใช้ตัวชี้วัดเหล่านี้ตั้งแต่เนิ่นๆ ของวงจรจะช่วยลดความเสี่ยงของโปรแกรมได้มากขึ้น
วิธีการลดความซับซ้อนเชิงวัฏจักร
ตัวเลขความซับซ้อนสูงเป็นเพียงสัญญาณบ่งชี้ ไม่ใช่ข้อสรุป การปรับโครงสร้างใหม่สี่ครั้งนั้นคิดเป็นส่วนใหญ่ของการลดความซับซ้อนที่สามารถทำได้ในทางปฏิบัติ
- Extracวิธี t การแยกสาขาออกไปอยู่ในฟังก์ชันของตัวเองจะแบ่งความซับซ้อนออกเป็นสองโมดูล ความซับซ้อนโดยรวมของระบบยังคงไม่เปลี่ยนแปลง แต่แต่ละหน่วยจะสามารถทดสอบได้อย่างอิสระ
- แทนที่การเชื่อมโยงเงื่อนไขด้วยการค้นหาข้อมูล โครงสร้างเงื่อนไข if-else-if ที่ยาวเหยียดซึ่งทดสอบตัวแปรเดียวกัน จะกลายเป็นแผนผังหรือสวิตช์ ซึ่งช่วยลดจุดตัดสินใจหลายจุดให้เหลือเพียงจุดเดียว
- ใช้เงื่อนไขป้องกัน (guard clause) การคืนค่ากลับทันทีเมื่อได้รับข้อมูลที่ไม่ถูกต้องจะช่วยขจัดความซับซ้อนของคำสั่ง if-else ขนาดใหญ่เพียงคำสั่งเดียว โดยไม่เปลี่ยนแปลงพฤติกรรม
- แทนที่เงื่อนไขด้วยโพลีมอร์ฟิซึม ในกรณีที่เงื่อนไขขึ้นอยู่กับประเภท การย้ายแต่ละสาขาไปอยู่ในคลาสของตัวเองจะช่วยขจัดความจำเป็นในการตัดสินใจออกไปโดยสิ้นเชิง
ก่อนหน้านี้ เมื่อ V(G) = 4:
if (user != null) { if (user.isActive()) { if (user.hasRole("admin")) { return grantAccess(); } } } return denyAccess();
หลังจากนั้น โดยที่พฤติกรรมยังคงเหมือนเดิม แต่ได้เอาส่วนที่เป็นรังออกไปแล้ว:
if (user == null) return denyAccess(); if (!user.isActive()) return denyAccess(); if (!user.hasRole("admin")) return denyAccess(); return grantAccess();
ข้อควรระวังเกี่ยวกับตัวชี้วัดนี้ ความซับซ้อนเชิงวัฏจักรนับจำนวนการตัดสินใจ ไม่ใช่ความยาก คำสั่ง switch ที่มี 20 กรณีง่ายๆ ได้คะแนน 21 แต่ก็ยังอ่านง่าย ในขณะที่บล็อกซ้อนกันหลายชั้นได้คะแนน 8 อาจเข้าใจยากกว่ามาก ควรใช้ตัวเลขนี้เพื่อค้นหาตัวอย่างที่ควรตรวจสอบ ไม่ใช่ใช้เป็นเป้าหมายในการโกงคะแนน


.png)
.png)