Dans cet article, je vous propose de vous présenter les techniques de test issues de l’analyse du flot de contrôle. Ces techniques, dites boites blanches, peuvent s’avérer très utiles pour construire un socle de test unitaire permettant de répondre aux exigences de couverture de code requises pour un produit logiciel.
Présentation générale
L’ISTQB définit le flot de contrôle comme « une représentation abstraite de toutes les séquences d’événements (chemins) dans l’exécution d’un composant ou système » (ISO-29119).
Le test par flot de contrôle regroupent plusieurs techniques de test dites boites blanches: le test des instructions, le test des décisions, le test des conditions, le test des chemins.
Bien que ces techniques puissent être applicables à tous les niveaux de test, elles le sont particulièrement au niveau unitaire et c’est souvent le code qui constitue la base de test pour ces techniques.
C’est pourquoi je parlerais de couverture de code qui est définie par l’ISTQB comme « une méthode d’analyse qui détermine quelles parties du logiciel ont été exécutées (couvertes) par une suite de tests et quelles parties ne l’ont pas été, p.ex. couverture des instructions, des décisions ou des conditions. »
Toutes les techniques présentées ci-dessous vous permettront de construire un patrimoine de tests unitaires avec lequel vous pourrez apporter un indicateur de couverture. Cela vous sera utile pour certains contextes où la sûreté des individus est une exigence forte (comme dans l’aéronautique avec l’ED 12 ou la DO–178C).
Ces techniques peuvent être mise en oeuvre quelque soit votre contexte projet:
- projet de maintenance logiciel avec un code existant: ce dernier pourra être étudié et les techniques vous aideront à augmenter la couverture de code par les tests unitaires.
- projet « from scratch » en cycle en V ou agile avec du BDD/TDD: je vous conseille de rédiger les tests unitaires avec ces techniques en ayant écrit le pseudo code au préalable. Cela va dans le sens du TDD et vous permettra d’écrire uniquement le code utile pour répondre aux exigences du logiciel.
Je vais vous présenter ces techniques par ordre de couverture croissante. Il faut comprendre que la couverture des instructions est plus faible que la couverture des décisions, elle même plus faible que la couverture des conditions et enfin la plus forte étant la couverture des chemins.
Le test des instructions
Le test d’instruction est « une technique de conception de tests boîte-blanche dans laquelle les cas de tests sont conçus pour exécuter des instructions » (ISTQB).
Nous parlons souvent de couverture des instructions qui est « le pourcentage des instructions exécutables qui ont été exécutées par une suite de tests » (ISTQB).
Mais au fait, qu’est-ce qu’une instruction ?
L’ISTQB la définit comme « une entité dans un langage de programmation, qui est typiquement la plus petite unité indivisible d’exécution. »
Prenons l’exemple suivant:
1 . Si il pleut
2 .___Je prends mon parapluie
3 . Fin Si
4 . Je sors de la maison
Les lignes 2 et 4 sont des instructions.
Afin de faciliter l’identification des cas de test pour couvrir toutes les instructions du code précédent, il est préférable de représenter ce pseudo-code par un diagramme comme suit:
Notre ligne 1 est représentée par le losange et on verra par la suite que c’est une décision. En général, on ne représente pas la fin du SI dans le diagramme mais je vous conseille de l’indiquer clairement dans votre pseudo-code pour faciliter la lecture.
Dans notre exemple, un seul test suffira pour couvrir nos deux instructions.
Synonymes : Déclarations, statement (anglais)
Certification ISTQB: niveau Fondation
Le test des décisions
Le test des décisions est « une technique de conception de tests boîte blanche selon laquelle les cas de tests sont conçus pour exécuter les résultats de décisions » (ISQTB).
Nous parlons de couverture des décisions qui est le pourcentage des résultats des décisions qui ont été exécutées par une suite de tests.
Une décision est « un type d’instruction dans lequel le choix entre deux ou plusieurs résultats possibles contrôle l’ensemble des actions qui en résulte » (ISTQB).
Concrètement, les instructions conditionnelles sont des décisions: IF, SWITCH, FOR, WHILE, …
Reprenons notre exemple précédent pour lequel nous avons identifié un test pour couvrir 100% des instructions. Nous pouvons remarquer que ce même test couvre partiellement la décision 1 en passant par le VRAI.
Pour obtenir une couverture de 100% de notre décision, il nous faut un second test pour passer par le FAUX de notre décision 1.
Prenons un exemple plus complexe avec le pseudo-code suivant:
1. Si il pleut
2. ___Si J’ai mon parapluie
3. _______Je sors dehors
4. ___Sinon
5. _______Je ne sors pas dehors
6. ___Fin si
7. Sinon
8. ___Je sors dehors
9. Fin si
Ce pseudo-code aura besoin de 3 tests pour couvrir 100% des décisions.
Dans ce diagramme, j’ai explicitement indiqué les lignes FIN SI et omis les lignes SINON pour une meilleure lisibilité.
Voici un autre exemple avec une boule FOR:1.Lire P
2.For i = 0; i < 2 ; i++
3. ___Si P = i
4. ______P = 2*i
5. ____Fin si
6.Fin For
7.Afficher P
1 seul test suffit pour couvrir toutes les décisions et instructions. Mais attention, il faut correctement choisir la valeur de P, en l’occurrence, P=1. Voici le diagramme qui illustre cet exemple avec en vert, le test passant par la boucle avec i=0, en bleu avec i = 1 et en rouge avec i=2 qui permet de sortir de la boucle.
Synonymes : Branche, decision (anglais), branch (anglais)
Certification ISTQB: niveau Fondation
Le test des conditions
Allons plus loin dans le niveau de couverture en regardant l’intérieur d’une décision.
Cette dernière peut contenir une ou plusieurs conditions qui est définie par l’ISTQB comme « une expression logique qui peut être évaluée à Vrai ou Faux, p.ex. A>B. »
Prenons un exemple simple:
Deux tests pour couvrir mes deux conditions A et B et atteindre 100% de couverture des conditions.
Mais cet exemple contredit le début de l’article sur la couverture des conditions qui est plus forte que les couvertures de décisions et instructions. Et oui, le parfait contre-exemple mais plus votre décision sera complexe, plus la couverture de conditions permettra d’atteindre aussi 100% de couverture des décisions et donc des instructions.
Synonymes : condition de branchement
Certification ISTQB: niveau avancé Technical Test Analyst
Afin de palier à cette incertitude et renforcer le niveau de couverture, vous pouvez mettre en oeuvre les couvertures suivantes encore plus complexes: couverture des décisions conditions, couverture des conditions/décisions modifiées, et enfin la couverture des conditions multiples.
Couverture des décisions conditions
Il s’agit de trouver des tests de tel sorte que la couverture des conditions soient satisfaites mais aussi la couverture des décisions.
Sur l’exemple suivant, deux tests permettent d’obtenir 100% de couverture de décisions et de 100% de couverture des conditions.
Certification ISTQB: niveau avancé Technical Test Analyst
Couverture des conditions/décisions modifiées
Définition ISTQB: La couverture des conditions/décisions modifiées atteint la couverture des décisions et conditions, mais demande ensuite à ce que ce qui suit soit satisfait :
1. Au moins un test pour lequel le résultat de la décision changerait si la condition atomique X était à VRAI
2. Au moins un test pour lequel le résultat de la décision changerait si la condition atomique X était à FAUX
3. Chacune des différentes conditions atomiques a des tests qui satisfont les exigences 1 et 2
Cette couverture cherche à trouver les bons tests pour identifier des défauts dans certaines conditions. En effet, imaginons une condition qui renvoi le mauvais résultat mais cela n’influe pas le résultat de la décision, nous aurions tous les tests en succès et pourtant un défaut est toujours présent dans le code.
Pour illustrer cette technique, je reprends l’exemple fourni par l’ISTQB dans le diagramme suivant.
La couverture des décisions est atteinte (le résultat du prédicat de décision est VRAI et FAUX), et la couverture des conditions est atteinte (A, B, et C prennent tous les deux valeurs VRAI et FAUX).
Dans le test violet, A est VRAI et la sortie est VRAI. Si A est changé à FAUX, le résultat devient FAUX. Idem dans le test vert, Si A passe à VRAI, la décision devient VRAI.
Dans le test rouge, B est VRAI et la sortie est VRAI. Si B est changé à FAUX, le résultat devient FAUX. Idem dans le test vert, Si B passe à VRAI, la décision devient VRAI.
Dans le test violet, C est VRAI et la sortie est VRAI. Si C est changé à FAUX la sortie devient FAUX. Idem dans le test jaune, Si C passe à VRAI, la décision devient VRAI.
Cette technique est très difficile à mettre en oeuvre et elle se complexifie en fonction du nombre de conditions dans la décision. En général, il faut N+1 tests pour obtenir 100% de couverture de condition/décisions modifiées avec N conditions.
Synonymes: modified condition / decision coverage (MC/DC) (anglais)
Certification ISTQB: niveau avancé Technical Test Analyst
Couverture des conditions multiples
Il s’agit tout simplement de faire la combinatoire de chaque résultat de chaque conditions.
Il faut donc 2n tests pour atteindre cette couverture d’une décision à N conditions.
Cette technique est coûteuse et ne devrait être mise en oeuvre que dans des cas où le logiciel doit être fiable sans planter pendant de longues périodes de temps.
Synonymes: multiple condition coverage (anglais)
Certification ISTQB: niveau avancé Technical Test Analyst
Le test des chemins
L’ISTQB défini un chemin comme « une séquence d’événements, p.ex instructions exécutables, d’un composant ou système d’un point d’entrée jusqu’à un point de sortie ».
Le test des chemins consiste à identifier les chemins au travers du code et à créer ensuite les tests les couvrant.
Boris Beizer propose une approche pour réaliser cette couverture en laissant de coté les problématiques de boucle infinie.
Les tests sont créés de façon à suivre plusieurs chemins au travers du module, de l’entrée à la sortie. il préconise la procédure suivante:
1. Choisissez comme premier chemin, le chemin le plus simple pour une fonctionnalité sensible, de l’entrée à la sortie.
2. Choisissez chaque chemin supplémentaire comme une petite variation du chemin précédent. Essayez de changer seulement une branche dans le chemin qui est différent pour chaque test successif. Lorsque cela est possible, privilégiez les chemins courts plutôt que les longs. Privilégiez les chemins qui donnent un sens fonctionnel à ceux qui n’en donnent pas.
3. Ne choisissez de chemins ne donnant pas de sens fonctionnel que lorsque cela est requis pour la couverture. Beizer note dans cette règle que de tels chemins peuvent être hors sujet et devraient être questionnés.
4. Utilisez l’intuition lors du choix des chemins (c.à.d., quels chemins ont le plus de chances d’être exécutés).
Synonyme: Chemin de flot de contrôle, Path (anglais), control flow path (anglais)
Certification ISTQB: niveau avancé Technical Test Analyst
Conclusion
Au delà d’atteindre un certain niveau de couverture imposé par une réglementation, ces techniques sont particulièrement utiles pour construire un patrimoine de tests unitaires robuste et pertinent.
La couverture des chemins me semble particulièrement pertinente dans une approche BDD. Chaque cas d’usage représentant un ou plusieurs chemins dans le logiciel.
Une couverture des décisions voir conditions dans une approche TDD vous permettra d’optimiser et simplifier votre code tout en maintenant un bon niveau de couverture.
L’addition des deux réduira le taux de défauts dans le code et les testeurs pourront se concentrer sur la couverture des API au niveau intégration puis aux tests de bout-en-bout/cas d’usage (niveau système et acceptation) avec du test exploratoire.
SOURCES ET REMERCIEMENTS
Le syllabus ISTQB niveau avancé Test Analyste traduit en français par le CFTL
Le glossaire ISTQB traduit en français par le CFTL
La norme BS-7925-2 « Software component testing standard »
Boris Beizer, Software Testing techniques
Merci à Marc Hage Chahine pour sa relecture.