Comment tirer la couverture à soi
L’objectif de cet article est de donner quelques éléments sur ce qu’est la couverture de code, ce qu’elle apporte, ses différentes formes et dans quel cadre il est nécessaire de la mettre en œuvre.
Même si les exemples seront basés sur du code Ada, ils peuvent aussi s’appliquer à bien d’autres langages de programmation.
Dans le cadre du développement d’applications critiques, les normes en vigueur (DO-178C, EN-50128, EN-50176 etc.) peuvent exiger ou du moins recommander que le code source soit qualifié en termes de couverture.
Les types de couvertures possibles sont :
- Functions (couverture de fonctions),
- Statement (couverture d’instructions ou STMT),
- Decision (couverture de branches ou DC),
- Modified Condition/Decision Coverage (MC/DC) (couverture MC/DC),
- Multiple Condition Coverage (MCC) (couverture MCC).
Dans la pratique, et pour des hauts niveaux de criticité (DALA et SIL4) il est requis de faire de la couverture Statement+MC/DC sur 100% du code source et pour des logiciels moins critiques, de mettre au minimum en œuvre de la couverture Statement+Decision sur au moins 80% du code source.
Pourquoi faire de la couverture ?¶
La couverture permet de répondre aux deux questions suivantes :
- Mes tests sont-ils suffisamment représentatifs pour exercer l’ensemble du code ?
- Y-a-t-il du code non atteignable ?
Pour rappel, les exigences du logiciel doivent être vérifiées au travers de tests. La couverture du code permet aussi de qualifier de façon indirecte la complétude de la vérification de ces exigences.
Quelques définitions¶
-
Une instruction est l’appel permettant d’opérer un traitement. En Ada, elle se termine par un
;
. -
Une condition est une expression booléenne ne contenant pas d’opérateurs booléens (exemple :
A > 10
). -
Une décision est une expression booléenne contenant des conditions et des opérateurs booléens (exemple :
A > 10 and then B < -100
).
Par ordre de criticité croissante :
- Une couverture Function permet de savoir si les sous-programmes d’un code source ont bien été appelés.
- Une couverture Statement permet de savoir si les instructions du code source ont bien été exécutées.
- Une couverture Decision permet de savoir si les décisions présentes dans le code source ont été respectivement évaluées à TRUE et FALSE.
- Une couverture MC/DC permet de s’assurer que chaque condition d’une décision a bien été respectivement évaluée à TRUE et FALSE et que chaque condition d’une décision a été démontrée comme affectant indépendamment la valeur de cette décision.
- La couverture MCC vient, en plus du MC/DC, s’assurer que les conditions au sein d’une décision ont pris toutes les combinaisons possibles TRUE et FALSE.
Un exemple Statement + MC/DC ¶
Soit le code Ada suivant :
procedure Test is function And_Then (A, B : in Boolean) return Boolean is (A and then B); begin if And_Then (A =\> True, B =\> True) then null; end if; if And_Then (A =\> False, B =\> True) then null; end if; -- if And_Then (A =\> True, B =\> False) then -- null; -- end if; end Test;
Si nous générons la couverture de ce code en Statement+MC/DC avec l’outil GNATCoverage, on obtient :
- 1 statement violation.
- 2 decision violations.
- 1 MCDC violation.
En effet :
À la ligne 5, la décision vaut toujours TRUE et l’instruction de la ligne 6 est couverte 🡪 decision violation.
À la ligne 9, la décision vaut toujours FALSE et l’instruction de la ligne 10 n’est pas couverte 🡪 decision violation + statement violation.
À la ligne 2, la décision comporte deux conditions. Les valeurs possibles pour les paramètres formels A et B sont :
Test | Condition A | Condition B | Décision |
---|---|---|---|
1 | TRUE | TRUE | TRUE |
2 | FALSE | TRUE | FALSE |
3 | TRUE | FALSE | FALSE |
Le test 3 n’a pas été fait et le test 4 est redondant Condition A (test 4) = Condition A (test2) et Condition B (test 4) = Condition B (test3). D’une façon générale, un test MCDC requiert au minimum $nbcond + 1$ test, donc ici 3 tests alors qu’un test MCC aurait requis $2^{nbcond}$ tests, soit ici 4 tests.
Maintenant, si nous modifions notre code pour avoir :
procedure Test is function And_Then (A, B : in Boolean) return Boolean is (A and then B); begin if And_Then (A =\> True, B =\> True) then null; end if; if And_Then (A =\> False, B =\> True) then null; end if; if And_Then (A =\> True, B =\> False) then null; end if; end Test;
Test | Condition A | Condition B | Décision |
---|---|---|---|
1 | TRUE | TRUE | TRUE |
2 | FALSE | TRUE | FALSE |
3 | TRUE | FALSE | FALSE |
Nous obtenons bien :
- 2 statement violations.
- 3 decision violations.
- 0 MCDC violation.
Il y a donc bien complétude du test MC/DC mais les violations concernant les décisions persistent.
Pour finir, si nous avons le code suivant :
procedure Test is function And_Then (A, B : in Boolean) return Boolean is (A and then B); begin for A in Boolean loop for B in Boolean loop if And_Then (A =\> A, B =\> B) then null; end if; end loop; end loop; end Test;
Test | Condition A | Condition B | Décision |
---|---|---|---|
1 | TRUE | TRUE | TRUE |
2 | FALSE | TRUE | FALSE |
3 | TRUE | FALSE | FALSE |
4 | FALSE | FALSE | FALSE |
Nous obtenons bien :
- 0 statement violation.
- 0 decision violation.
- 0 MCDC violation.
Si le MCC était supporté par l’outil, il n’y aurait aucune violation sur ce dernier.
Conclusion¶
La mise en œuvre des tests de couvertures est une technique permettant de satisfaire aux exigences requises par les normes industrielles en termes de sûreté et de sécurité.
Dans cette optique, l’approche MCC est la plus rigoureuse, mais aussi la plus contraignante. C’est pour cela que l’approche MC/DC est un bon compromis entre MCC et DC tout en garantissant une probabilité élevée de détection des erreurs.
Cela étant, même si les tests MC/DC sont moins contraignants que les tests MCC, ils le restent cependant en regard des tests DC. C’est pour cela qu’il est primordial, lors de la phase de codage, de faire en sorte de se ramener à du code dépourvu de conditions multiples et donc de se ramener à de simples tests DC.
Donc, encore une fois, le maître mot est : faites des choses simples !
Références¶
[1] : GNATcoverage User’s Guide
[2] : Wikipedia — couverture de code
[3] : Wikipedia — MC/DC