Complexité cyclomatique dans les tests logiciels : un exemple

⚡ Résumé intelligent

La complexité cyclomatique est une métrique logicielle développée par Thomas McCabe en 1976 qui compte les chemins indépendants à travers un programme. Elle est calculée à partir d'un graphe de flux de contrôle et indique le nombre de cas de test nécessaires pour une couverture complète des branches.

  • (I.e. Deux formules : V(G) = E – N + 2 à partir du graphique, ou V(G) = P + 1 à partir du nombre de points de décision.
  • 🧮 Signification directe : Cette valeur correspond au nombre maximal de chemins indépendants, et donc au nombre de cas de test nécessaires.
  • Base du graphique : Les nœuds représentent les étapes de traitement et les arêtes représentent le flux de contrôle entre elles.
  • 🟢 1 à 10: Code structuré et bien écrit, hautement testable et à faible coût de maintenance.
  • 🟠 21 à 40: Code très complexe avec une faible testabilité, où la refactorisation coûte généralement moins cher que les tests.
  • Outillage: SonarQube, Visual Studio Code Metrics, Radon et Lizard le calculent automatiquement.

Complexité cyclomatique dans les tests logiciels

Quelle est la complexité cyclomatique de McCabe ?

Complexité cyclomatique dans les tests logiciels est une métrique de test utilisée pour mesurer la complexité d'un programme logiciel. Il s'agit d'une mesure quantitative des chemins indépendants dans le code source d'un logiciel. La complexité cyclomatique peut être calculée à l'aide de graphiques de flux de contrôle ou par rapport aux fonctions, modules, méthodes ou classes d'un programme logiciel.

Un chemin indépendant est défini comme un chemin comportant au moins un bord qui n’a jamais été traversé auparavant par d’autres chemins.

Cette métrique a été développée par Thomas J. McCabe en 1976 et est basée sur une représentation de flux de contrôle du programme. Le flux de contrôle représente un programme sous la forme d'un graphique composé de nœuds et de bords.

Dans le graphique, les nœuds représentent les tâches de traitement tandis que les bords représentent le flux de contrôle entre les nœuds.

Complexité cyclomatique de McCabe

Notation graphique de flux pour un programme

La notation Flow Graph pour un programme définit plusieurs nœuds connectés via les arêtes. Vous trouverez ci-dessous des diagrammes de flux pour des instructions telles que if-else, While, jusqu'à et la séquence normale de flux.

Notation de graphique de flux pour un programme

Comment calculer la complexité cyclomatique

Représentation mathématique :

Mathématiquement, il s'agit d'un ensemble de chemins indépendants à travers le diagramme graphique. Code La complexité du programme peut être définie à l'aide de la formule –

V(G) = E - N + 2

Où,

E – Nombre d’arêtes

N – Nombre de nœuds

V (G) = P + 1

Où P = Nombre de nœuds de prédicat (nœud qui contient la condition)

Exemple -

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;

Le graphique de flux pour ce programme sera

Calculer la complexité cyclomatique

Calculer mathématiquement,

  • V(G) = 9 – 7 + 2 = 4
  • V(G) = 3 + 1 = 4 (les nœuds de condition sont 1,2 et 3 nœuds)

Ensemble de base, les quatre voies d'exécution indépendantes :

  • 1, 7
  • 1, 2, 6, 1, 7
  • 1, 2, 3, 4, 5, 2, 6, 1, 7
  • 1, 2, 3, 5, 2, 6, 1, 7

Propriétés de la complexité cyclomatique

Voici les propriétés de la complexité cyclomatique :

  1. V (G) est le nombre maximum de chemins indépendants dans le graphique
  2. V (G) >=1
  3. G aura un chemin si V (G) = 1
  4. Une règle généralement utilisée consiste à maintenir V(G) à 10 ou moins pour un seul module

En quoi cette métrique est-elle utile pour les tests logiciels ?

Le test de chemin de base est une technique de boîte blanche qui garantit l'exécution d'au moins une instruction lors du test. Il vérifie chaque chemin linéairement indépendant à travers le programme, ce qui signifie que Le nombre de cas de test nécessaires est égal à la complexité cyclomatique du programme..

Cette métrique est utile en raison des propriétés de complexité cyclomatique (M) –

  1. M peut être le nombre de cas de test pour atteindre la couverture des branches (limite supérieure)
  2. M peut être le nombre de chemins à travers les graphiques. (Borne inférieure)

Considérez cet exemple -

If (Condition 1)
Statement 1

Else
Statement 2

If (Condition 2)
Statement 3

Else
Statement 4

La complexité cyclomatique pour ce programme sera de 8-7+2=3.

Comme la complexité est calculée à 3, trois cas de test sont nécessaires pour couvrir complètement le chemin pour l'exemple ci-dessus.

Étapes à suivre

Les étapes suivantes doivent être suivies pour le calcul de la complexité cyclomatique et la conception des cas de test.

Étape 1 – Construction de graphe avec nœuds et arêtes à partir du code

Étape 2 – Identification de chemins indépendants

Étape 3 – Calcul de complexité cyclomatique

Étape 4 – Conception de cas de tests

Une fois l’ensemble de base constitué, CAS DE TEST doit être écrit pour exécuter tous les chemins.

En savoir plus sur V (G)

La complexité cyclomatique peut être calculée manuellement si le programme est petit. Des outils automatisés doivent être utilisés si le programme est très complexe, car cela implique davantage de graphiques de flux. Sur la base du nombre de complexité, l'équipe peut conclure sur les actions qui doivent être prises pour mesurer.

Le tableau suivant donne un aperçu du nombre de complexité et de la signification correspondante de v (G) :

Numéro de complexité Sens
1 à 10 ans, qui

Code structuré et bien écrit

Haute testabilité

Le coût et les efforts sont moindres.

11 à 20 ans, qui

Code complexe

testabilité moyenne

Le coût et l'effort sont moyens

21 à 40 ans, qui

Code très complexe

Faible testabilité

Le coût et l'effort sont élevés

> 40

Pas du tout testable

Coût et effort très élevés

Outils de calcul de la complexité cyclomatique

De nombreux outils sont disponibles pour déterminer la complexité de l'application. Certains outils de calcul de complexité sont utilisés pour des technologies spécifiques. La complexité peut être détectée par le nombre de points de décision dans un programme. Les points de décision sont les instructions if, for, for-each, while, do, catch, case dans un code source.

Des exemples d'outils sont

  • OCLint – Analyseur de code statique pour C et langages associés
  • SonarQube – Analyse la complexité cyclomatique et cognitive dans plus de 25 langues
  • Visual Studio Code Métriques – Analyse intégrée de la complexité cyclomatique pour les assemblys .NET
  • Radon et Lizard – Analyseurs de complexité en ligne de commande pour Python et pour les projets multilingues respectivement
  • Gmétriques – Trouver des métriques dans Java applications associées

Utilisations de la complexité cyclomatique

La complexité cyclomatique peut s'avérer très utile dans

  • Aide les développeurs et les testeurs à déterminer des exécutions de chemin indépendantes
  • Les développeurs peuvent ainsi garantir que tous les chemins ont été testés au moins une fois.
  • Nous aide à nous concentrer davantage sur les chemins découverts
  • Améliorer la couverture du code dans Génie logiciel
  • Évaluer le risque associé à l’application ou au programme
  • L'utilisation de ces mesures au début du cycle réduit davantage les risques du programme

Comment réduire la complexité cyclomatique

Un indice de complexité élevé est un signal, pas une conclusion. Quatre refactorisations permettent d'obtenir la majeure partie de la réduction réalisable en pratique.

  • Extracméthode t. Déplacer une branche dans sa propre fonction répartit la complexité entre deux modules. La complexité totale du système reste inchangée, mais chaque unité devient testable indépendamment.
  • Remplacez une chaîne conditionnelle par une recherche. Une longue série de conditions « si-sinon si » testant la même variable se transforme en une structure de type « map » ou « switch », ce qui réduit de nombreux points de décision à un seul.
  • Utilisez des clauses de garde. Le fait de renvoyer une valeur invalide dès le début permet d'éliminer l'imbrication créée par un seul bloc if-else de grande taille, sans modifier le comportement.
  • Remplacez les conditions par du polymorphisme. Lorsqu'une conditionnelle dépend d'un type, déplacer chaque branche dans sa propre classe supprime complètement la décision.

Auparavant, avec V(G) = 4 :

if (user != null) {
    if (user.isActive()) {
        if (user.hasRole("admin")) {
            return grantAccess();
        }
    }
}
return denyAccess();

Ensuite, avec le même comportement et l'imbrication supprimée :

if (user == null) return denyAccess();
if (!user.isActive()) return denyAccess();
if (!user.hasRole("admin")) return denyAccess();
return grantAccess();

Une mise en garde concernant cette mesure. La complexité cyclomatique prend en compte le nombre de décisions, et non la difficulté. Une instruction switch comportant vingt cas simples obtient un score de 21 tout en restant facile à lire, tandis qu'un bloc profondément imbriqué, avec un score de 8, peut s'avérer bien plus complexe à comprendre. Utilisez ce score pour identifier les cas à examiner, et non comme un objectif à manipuler.

FAQ

On recommande généralement de ne pas dépasser dix modules par classe. Entre onze et vingt modules, le code est complexe mais gérable. Au-delà de vingt modules, la testabilité chute brutalement, et au-delà de quarante, le module est généralement considéré comme non testable en l'état.

Les deux méthodes donnent le même résultat. P + 1 est plus rapide pour un calcul manuel car on ne compte que les points de décision. E – N + 2 est la méthode utilisée par les outils, puisqu'ils construisent déjà le graphe de flux de contrôle.

Pas nécessairement. La complexité cyclomatique prend en compte le nombre de décisions plutôt que la difficulté ; ainsi, un commutateur simple avec vingt cas simples obtient un score élevé tout en restant facile à lire. Considérez ce nombre comme un indicateur pour une révision.

Ils combinent ces données avec la fréquence des modifications et l'historique des défauts pour classer les modules présentant le plus de risques, orientant ainsi les efforts de revue et de test vers le code le plus susceptible de dysfonctionner.

Oui. Les assistants IA proposent des clauses de protection, par exempletracUtilisez des méthodes simplifiées et des tables de consultation pour réduire le nombre d'éléments. Vérifiez le comportement avec la suite de tests existante, car une refactorisation qui modifie la logique serait contre-productive.

Résumez cet article avec :