Découvrez comment la solution Parasoft Continuous Quality permet de contrôler et de gérer les environnements de test pour fournir des logiciels de haute qualité en toute confiance. Inscrivez-vous pour la démo >>

BLOG

Le problème de la couverture du code de chemin

Le problème de la couverture du code de chemin Temps de lecture : 3 minutes

Pourquoi si peu d'outils disponibles prennent en charge la couverture de chemin?

Nombre élevé de chemins

Le nombre de chemins de code possibles augmente généralement de façon exponentielle avec la complexité cyclomatique d'une méthode. Atteindre un pourcentage élevé de couverture de chemin en écrivant manuellement des cas de test est effectivement impossible pour toute méthode contenant plus qu'une poignée de lignes. Même les outils de génération de tests automatisés peuvent avoir du mal à générer des cas de test pour une couverture complète du chemin, en particulier lorsque des boucles imbriquées sont impliquées. Par exemple, une méthode avec une séquence de 10 instructions non imbriquées si a déjà 1024 (ou 210) chemins possibles. Le chemin de code pour une boucle qui se termine après 499 itérations est différent du chemin de code de la même boucle se terminant après 500 itérations. De même, une opération de magasin de tableaux lançant une exception en raison d'une référence null et cette même opération lançant une ArrayStoreException doivent être traitées comme des chemins de code différents.

Types de couverture de code

La couverture de chemin est l'un des nombreux types de métriques de couverture de code. Pour revoir, voici les types de prise en charge de la couverture par les outils de test Parasoft:

Bloc de base Une séquence d'instructions sans ramification; une séquence linéaire de code sans branchements de route de flux de contrôle.
Expression booléenne En C ++, une expression booléenne est simplement une expression de type «booléen».

En C, le test C ++ traite les éléments suivants comme des expressions booléennes:

  • Un opérateur relationnel (<, <=, ==,>,> =,! =) Avec des arguments non booléens.
  • Chaque argument de l'opérateur booléen (||, &&,!).
  • Condition dans les instructions if, for, while et do-while.
  • Condition dans? opérateur.
État Expression atomique booléenne non constante qui fait partie de la décision MC / DC.

Une sous-expression de la décision MC / DC est considérée comme une condition si elle ne contient pas d'opérateurs booléens (&&, ||,!).

Si une expression atomique donnée apparaît plus d'une fois dans une décision, chaque occurrence est une condition distincte.

Décision / Direction Décision / Branchement est la décision de flux de contrôle possible à prendre au point de branchement dans le code. Le test C ++ considère les instructions if-else, for, while, do-while et switch comme les points de branchement. Le test C ++ ne prend pas en compte ces points de branchement dynamiques en tant que gestionnaires d'exceptions (instructions throw-catch).
 Décision MC / DC Expression booléenne de niveau supérieur composée de conditions et de zéro ou plusieurs opérateurs booléens. Le test C ++ calcule MC / DC et SCC sur toutes les expressions booléennes non constantes dans le code source, à l'exception des initialiseurs de constructeur et des arguments par défaut de la fonction.
Chemin Une séquence unique de blocs de base à partir de l'entrée de fonction jusqu'au point de sortie.

Difficulté à identifier et à parcourir les chemins

Les outils de génération de test automatisés pour la couverture de chemin doivent d'abord déterminer quels chemins de code sont possibles et lesquels ne le sont pas, puis doivent être en mesure de générer des entrées de test qui couvrent tous les chemins possibles. Les deux étapes prennent beaucoup de temps et la précision des résultats ne peut pas vraiment être garantie car l'analyse requise implique des problèmes connus pour être NP-difficiles ou même indécidables (comme le tristement célèbre problème d'arrêt).

Défis de représentation

Contrairement à la couverture de déclaration et de branche, la couverture de chemin est difficile à visualiser. Marquer des lignes ou des expressions avec des couleurs différentes ne suffit pas pour transmettre ce type d'informations de couverture. En raison de ce manque de visualisation facilement compréhensible, la couverture de chemin reste un concept difficile pour de nombreux développeurs.

Les approches pratiques pour atteindre la couverture de chemin sont similaires pour la génération de tests automatisés et manuels. Au lieu d'essayer de trouver tous les chemins de code possibles, il est utile de se concentrer sur les chemins de code «intéressants». Cela n'a guère de sens d'écrire un cas de test qui exécuterait une boucle 499 fois, puis d'ajouter un autre cas de test qui exécute la boucle 500 fois si rien de vraiment différent ne se produit.

Plutôt que d'utiliser une approche descendante, il est souvent plus utile d'utiliser une approche ascendante qui commence aux points d'échec possibles, puis trouve les chemins de code qui conduiraient aux échecs. Les perturbateurs potentiels incluent non seulement des références nulles possibles (NullPointerException), des incompatibilités de type (ClassCastException, ArrayStoreException), des violations de limites de tableau (ArrayIndexOutOfBoundsException), mais également des divisions par zéro (ArithmeticException) ou des problèmes de synchronisation potentiels (IllegalMonitorStateException). La partie délicate est que ces exceptions se produisent comme un effet secondaire des instructions de bytecode de bas niveau et ne sont déclarées nulle part. Les outils de test capables d'effectuer une analyse de flux du code testé peuvent être très utiles pour identifier les chemins de code qui nécessitent des tests supplémentaires.

class Listing4 {public static int add (int a, int b) {return a + b; }} classe publique Listing4Test étend junit.framework.TestCase {public void testAdd0 () {int result = Listing4.add (0, 0); assertEquals (0, résultat); }}

Liste 4: Une méthode qui n'a qu'un seul chemin de code et son test JUnit correspondant

 

class Listing4 // Listing 5, en fait {public static int add (int a, int b) {return 0; }}

Liste 5: Une mise en œuvre simplifiée à l'extrême qui passerait toujours le test

***

Crédit image: mer lumineuse

Écrit par

Parasoft

Les outils de test de logiciels automatisés de pointe de Parasoft prennent en charge l'ensemble du processus de développement logiciel, depuis le moment où le développeur écrit la première ligne de code jusqu'aux tests unitaires et fonctionnels, jusqu'aux tests de performance et de sécurité, en exploitant des environnements de test simulés en cours de route.

Recevez les dernières nouvelles et ressources sur les tests de logiciels dans votre boîte de réception.