Niveaux de granularité dans la couverture du code

Par Parasoft

18 août 2011

3  min lire

La granularité de la couverture de code est un aspect important des outils automatisés qui mesurent les métriques de couverture de code à des fins de test, mais tous les outils ne fournissent pas le même niveau d'informations sur la couverture de code.

Pour déterminer le niveau de granularité pris en charge, posez-vous la question «Quelle est la plus petite unité de code dont je peux déterminer le statut de couverture sans ambiguïté?» Pour de nombreux outils disponibles, la granularité est limitée à des lignes individuelles. Cela peut être une limitation plus grande qu'il n'y paraît à première vue. Le problème principal est que Java, comme la plupart des langages de programmation populaires, est un langage de forme libre. Un développeur peut écrire une classe Java complète sous la forme d'une très longue ligne de code. Si un outil de couverture qui offre une granularité de couverture basée sur les lignes indique que cette classe à une seule ligne est «couverte», qu'est-ce que cela signifie exactement? Cela signifie-t-il que chaque expression de cette ligne a été couverte ou une couverture de 100% est-elle signalée si au moins une expression de la ligne était couverte?

Certes, l'exemple d'une classe Java écrite comme une seule ligne de code est quelque peu artificiel, et un tel style de programmation serait déjà une source de préoccupation. Cependant, la granularité basée sur les lignes peut atteindre ses limites pour certains idiomes assez courants. Considérez la méthode de la liste 1.

Public class Listing1 {static int minOrMax (boolean minimum, int a, int b) {return minimum? Math.min (a, b): Math.max (a, b); }}

Liste 1: Une classe démontrant les limites de la granularité de la couverture basée sur les lignes

Un seul test est nécessaire pour couvrir partiellement la ligne contenant l'instruction return, mais au moins deux cas de test sont nécessaires pour couvrir les deux alternatives de l'expression conditionnelle. Même sans utiliser l'opérateur conditionnel, il n'est pas difficile de créer des situations où une ligne de code n'est que partiellement couverte. Les exceptions pendant l'exécution du programme peuvent toujours laisser des parties d'une ligne sans couverture. La granularité de la couverture basée sur les lignes est suffisante dans la plupart des cas, à condition que l'outil de couverture ne signale pas une couverture complète pour les lignes qui, en réalité, ne sont que partiellement couvertes. En outre, il peut être difficile de déterminer pourquoi une ligne particulière n'est pas entièrement couverte et quels tests doivent être ajoutés pour obtenir une couverture complète.

Les outils de couverture qui signalent la couverture pour des expressions individuelles facilitent l'identification des cas de test manquants. La visualisation de la granularité de la couverture basée sur l'expression est un peu plus intrusive. La couverture basée sur des lignes peut facilement être affichée dans une règle latérale de l'éditeur de source, tandis que la couverture basée sur des expressions nécessite des marqueurs (comme la coloration ou le soulignement) dans le code source lui-même.

Dans de rares cas, une expression apparemment atomique se traduit par plusieurs instructions exécutables, dont certaines peuvent ne pas être couvertes dans certaines circonstances. Idéalement, la granularité de la couverture atteint le niveau des instructions individuelles. En fait, de nombreux outils de couverture collectent des informations sur l'exécution ou non d'instructions individuelles. Cependant, la granularité des données collectées peut être réduite à une couverture basée sur des expressions ou sur des lignes lorsqu'elles sont signalées à l'utilisateur.

Les raisons de la couverture Low Code

Le problème de l'augmentation de la couverture des tests peut généralement être réduit à trois scénarios:

  • Les tests disponibles n'utilisent pas de valeurs d'entrée qui entraîneront des expressions de contrôle pour les conditions dans le code à exercer toutes les branches.
  • Les expressions de contrôle dans une fonction testée dépendent des valeurs renvoyées par d'autres fonctions, donc de l'état du programme / code lors de l'exécution du test.
  • Les tests disponibles n'utilisent pas la configuration appropriée pour le code en cours de test, donc l'exécution d'un test entraîne une exception, interrompant le flux d'exécution au point de l'exception.

Selon la structure du code, les expressions de contrôle peuvent être triviales (par exemple, une instruction if / else par fonction) ou non (conditionnelles de boucle imbriquée avec des expressions de contrôle qui sont des retours d'appels de fonction mélangés avec des expressions de branche). Sur la base de ces scénarios, différentes techniques de contrôle des conditions dans le cadre de test sont appropriées dans chaque cas.

La couverture n'est pas tout

Il est courant de penser à tort que la couverture est la seule qualité de conduite métrique. Une fois que les équipes sont en mesure de mesurer la couverture, il n'est pas rare que les managers veuillent augmenter le nombre, car «une couverture plus élevée, c'est mieux, n'est-ce pas? Finalement, le nombre lui-même devient plus important que le test. C'est là que réside le problème - la couverture doit refléter une utilisation réelle et significative du code, sinon ce n'est que du bruit. À moins que certains types et niveaux ne soient exigés par une norme industrielle, un produit doit se conformer à la couverture du code, tandis que les éléments importants nécessitent une approche pragmatique.

Il est important de comprendre que le coût de la couverture augmente à mesure que la couverture augmente. L'augmentation de la couverture signifie de nouveaux tests qui doivent être maintenus à l'avenir. Le besoin de nouveaux tests doit être justifié par rapport au projet global et aux objectifs de qualité. La création de tests dans le seul but d'augmenter la couverture entraîne des coûts et une dette technique.

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.