Цикломатична сложност в софтуерното тестване с пример
⚡ Умно обобщение
Цикломатичната сложност е софтуерна метрика, разработена от Томас Маккейб през 1976 г., която брои независимите пътища през програмата. Тя се изчислява от графика на контролния поток и дава броя на тестовите случаи, необходими за пълно покритие на клоновете.
Каква е цикломатичната сложност на Маккейб?
Цикломатична сложност при тестване на софтуер е показател за тестване, използван за измерване на сложността на софтуерна програма. Това е количествена мярка за независими пътища в изходния код на софтуерна програма. Цикломатичната сложност може да се изчисли чрез използване на графики на контролен поток или по отношение на функции, модули, методи или класове в софтуерна програма.
Независим път се дефинира като път, който има поне един ръб, който не е бил преминаван преди в други пътища.
Този показател е разработен от Thomas J. McCabe през 1976 г. и се основава на представяне на контролния поток на програмата. Контролният поток изобразява програма като графика, която се състои от възли и ръбове.
В графиката възлите представляват задачи за обработка, докато ръбовете представляват контролния поток между възлите.
Нотация на графика на потока за програма
Нотацията на Flow Graph за програма дефинира няколко възела, свързани през краищата. По-долу са диаграми на потока за изрази като 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;
Графиката на потока за тази програма ще бъде
Изчислявайки математически,
- V(G) = 9 – 7 + 2 = 4
- V(G) = 3 + 1 = 4 (възлите на условията са 1,2, 3 и XNUMX възли)
Базов набор, четирите независими пътя на изпълнение:
- 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) е максималният брой независими пътища в графиката
- V (G) >=1
- G ще има един път, ако V (G) = 1
- Често използвано ръководство е V(G) да се поддържа на 10 или по-малко за един модул.
Как този показател е полезен за тестване на софтуер
Тестването на базов път е част от техниката на „бялата кутия“ и гарантира изпълнението на поне едно твърдение по време на тестване. Проверява всеки линейно независим път през програмата, което означава, че броят на необходимите тестови случаи е равен на цикломатичната сложност на програмата.
Този показател е полезен поради свойствата на цикломатичната сложност (M) –
- M може да бъде брой тестови случаи за постигане на покритие на клон (горна граница)
- M може да бъде броят на пътищата през графиките. (Долна граница)
Помислете за този пример –
If (Condition 1) Statement 1 Else Statement 2 If (Condition 2) Statement 3 Else Statement 4
Цикломатичната сложност за тази програма ще бъде 8-7+2=3.
Тъй като сложността е изчислена като 3, три тестови случая са необходими за пълното покритие на пътя за горния пример.
Стъпки, които трябва да се следват
Трябва да се следват следните стъпки за изчисляване на цикломатична сложност и дизайн на тестови случаи.
Стъпка – Изграждане на граф с възли и ребра от кода
Стъпка – Идентифициране на независими пътища
Стъпка – Изчисляване на цикломатична сложност
Стъпка – Дизайн на тестови случаи
След като се формира основният набор, ТЕСТОВИ СЛУЧАИ трябва да се напише за изпълнение на всички пътища.
Още за V (G)
Цикломатичната сложност може да се изчисли ръчно, ако програмата е малка. Трябва да се използват автоматизирани инструменти, ако програмата е много сложна, тъй като това включва повече графики на потока. Въз основа на броя на сложността екипът може да направи заключение за действията, които трябва да бъдат предприети за измерване.
Следната таблица дава общ преглед на числото на сложност и съответното значение на v (G):
| Номер на сложност | Значение |
|---|---|
| 1 да 10 |
Структуриран и добре написан код Висока изпитаемост Разходите и усилията са по-малко |
| 11 да 20 |
Сложен код Средна тестваемост Разходите и усилията са средни |
| 21 да 40 |
Много сложен код Ниска тестваемост Разходите и усилията са високи |
| > 40 |
Изобщо не може да се тества Много високи разходи и усилия |
Инструменти за изчисляване на цикломатична сложност
Налични са много инструменти за определяне на сложността на приложението. Някои инструменти за изчисляване на сложността се използват за специфични технологии. Сложността може да се намери по броя на точките за вземане на решения в програмата. Точките за вземане на решение са изрази if, for, for-each, while, do, catch, case в изходния код.
Примери за инструменти са
- OCLint – Анализатор на статичен код за C и сродни езици
- SonarQube – Отчита цикломатична и когнитивна сложност в повече от 25 езика
- Visual Studio Code Метрики – Вграден цикломатичен анализ на сложността за .NET асембли
- Radon и Lizard – Анализатори на сложността от команден ред за Python и съответно за многоезични проекти
- GMetrics – Намерете показатели в Java свързани приложения
Употреба на цикломатична сложност
Цикломатичната сложност може да се окаже много полезна при
- Помага на разработчиците и тестерите да определят независими изпълнения на пътя
- Разработчиците могат да гарантират, че всички пътища са тествани поне веднъж
- Помага ни да се фокусираме повече върху непокритите пътища
- Подобрете покритието на кода в Софтуерно инженерство
- Оценете риска, свързан с приложението или програмата
- Използването на тези показатели в началото на цикъла намалява повече риска от програмата
Как да намалим цикломатичната сложност
Високото число на сложност е сигнал, а не присъда. Четири рефакторинга са причина за по-голямата част от постижимото на практика намаление.
- Extracт-метод. Преместването на клон в отделна функция разделя сложността между два модула. Общата стойност в системата остава непроменена, но всяка единица става независимо тестваема.
- Заменете условна верига с търсене. Дълга if-else-if стълба, тестваща една и съща променлива, се превръща в карта или превключвател, което обединява много точки на решение в една.
- Използвайте предпазни клаузи. Ранното връщане при невалиден вход премахва влагането, което създава един голям 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 с двадесет прости случая дава резултат 21, но е лесен за четене, докато дълбоко вложен блок, който получава 8, може да бъде много по-труден за разбиране. Използвайте числото, за да намерите кандидати за преглед, а не като цел, която да бъде измамена.



.png)
.png)