2.3 Etat de l’art sur la synth`ese de test
2.3.2 G´en´eration combinatoire de tests
Dans le domaine de la g´en´eration de tests, une mani`ere simple de g´en´erer un grand
nombre de tests est d’utiliser des techniques combinatoires. Ces techniques, contrairement
`a la g´en´eration de tests `a partir de sp´ecifications, se basent uniquement sur la signature
des op´erations (leurs entr´ees) pour g´en´erer des tests. ´Evidemment, elles souffrent d’un gros
probl`eme : l’explosion du nombre de tests.
JMLUnit
Bas´e sur le framework de test JUnit [JUn], JMLUnit [CL02b] est un outil de g´en´eration
combinatoire de tests unitaires pour les programmes Java. La conception de cet outil se place
dans une optique “extreme programming” ou les d´eveloppeurs font des tests unitaires (test
d’un appel de m´ethode) au fur et `a mesure qu’ils d´eveloppent. Comme le code source de
l’application ´evolue continuellement, la maintenance des tests est particuli`erement lourde et
p´enible.
L’outil propose donc de faciliter ce travail en se basant sur deux ´el´ements. Tout d’abord,
l’existence d’une sp´ecification JML [LBR99, LBR02] qui pourra servir d’oracle pour le
tests grˆace `a un outil permettant d’ex´ecuter la sp´ecification en mˆeme temps que
l’applica-tion [Bho00, CL02a]. Ensuite l’outil JMLUnit offre aux utilisateurs des facilit´es de cr´eal’applica-tion
de tests.
L’outil de g´en´eration de tests permet une maintenance ais´ee des tests en g´en´erant
auto-matiquement des tests ex´ecutables avec JUnit. L’utilisateur peut se concentrer sur les aspects
cr´eatifs du test limit´es ici `a la s´election des valeurs de tests et `a la d´efinition des ´etats initiaux.
L’outil permet de d´efinir le contexte d’appel de la m´ethode test´ee. L’utilisateur configure,
par des appels de m´ethodes et de constructeurs, l’´etat dans lequel sera appel´ee la m´ethode. Il
d´efinit ensuite des tableaux de valeurs pour les diff´erents param`etres de la m´ethode sous test.
L’outil g´en`ere, en faisant le produit cart´esien des diff´erentes valeurs, l’ensemble des appels
`a la dite m´ethode. Il g´en`ere un fichier de test JUnit contenant tous les cas de tests ainsi
g´en´er´es. N´eanmoins, cette m´ethode ne g´en`ere que des tests constitu´es d’un unique appel de
m´ethode.
Lors de l’ex´ecution des tests, la sp´ecification JML est ´evalu´ee et sert d’oracle. Son
uti-lisation permet de simplifier la maintenance des tests. En effet, lorsque l’on utilise JUnit
seul, les valeurs attendues doivent ˆetre d´efinies `a la main. L’utilisateur doit donc ´ecrire, pour
chaque test, les valeurs attendues. De plus, lorsque la structure des r´esultats change, il faut
corriger tous les tests pr´ec´edemment ´ecrits. L’utilisation de JML permet de centraliser les
modifications, d’´eviter les oublis, et d’offrir `a l’utilisateur la possibilit´e d’´ecrire plus de tests
puisqu’il n’a pas `a se soucier de leur maintenance.
UniTesk
UniTesk [Kul04, BKKP02, KKP02] est un framework de test qui se veut g´en´erique,
c’est-`a-dire applicable `a n’importe quel type d’application. Il n’est pas tr`es clair de savoir
ce qui est construit `a la main par l’utilisateur et ce qui est produit automatiquement par
l’outil mais l’id´ee g´en´erale est la suivante : le framework se base sur une machine d’´etats
finie repr´esentant le syst`eme sous test. Des crit`eres de couverture sont ensuite utilis´es pour
partitionner les domaines des entr´ees de l’application.
´
Etant donn´es ces partitions et le mod`ele du syst`eme, l’objectif est de passer au moins une
fois par chaque transition et de tirer au moins une valeur dans chaque partition. Pour cela,
l’utilisateur doit construire un it´erateur qui, ´etant donn´e un ´etat, va produire un symbole,
c’est-`a-dire un appel de fonction. Pour construire cet it´erateur, l’utilisateur doit d´efinir toutes
les entr´ees possibles de chaque fonction, ou donner au moins une entr´ee par partition. Il doit
de plus d´efinir manuellement l’algorithme de parcours de la machine d’´etats finie.
L’outil utilise ensuite une sp´ecification ex´ecutable, au moins en partie, pour produire
l’oracle du test.
Cet outil poss`ede donc un aspect combinatoire pour ce qui est de la production des
entr´ees. Cet aspect est pond´er´e par le fait de vouloir exercer un nombre fini de transitions
et au final obtenir une certaine couverture de l’application. Le framework utilise de plus
des sp´ecifications formelles (par exemple d´ecrites en VDM-SL) afin de produire un oracle
automatique pour le test.
Korat et TestEra
Korat [BKM02] et TestEra [MK01] sont deux outils de g´en´eration automatique de tests
visant `a tester des op´erations manipulant des structures de donn´ees complexes en Java.
Tout comme JMLUnit, Korat et TestEra adoptent une g´en´eration combinatoire de tests
unitaires. L’originalit´e de ces deux outils r´eside dans le fait qu’ils construisent de mani`ere
semi-automatique des donn´ees de test qui sont des structures Java, telles qu’un arbre binaire,
un tableau, etc.
TestEra et Korat utilisent tous deux un langage de sp´ecification permettant de sp´ecifier,
pour chaque op´eration test´ee, d’une part les entr´ees valides, d’autre part l’oracle.
TestEra utilise le langage Alloy [JSS01] et son analyseur de contraintes ALCOA [Jac00,
JSS00]. L’utilisateur sp´ecifie en Alloy des invariants structurels qui permettent `a ALCOA de
g´en´erer des instances valides de la sp´ecification et donc des structures de donn´ees. ALCOA
a besoin pour cela d’une borne d´efinie par un nombre d’atomes, c’est-`a-dire un nombre fini
d’´el´ements constituant la structure de donn´ees. Par exemple on va demander `a ALCOA de
g´en´erer un arbre comportant trois nœuds diff´erents. L’analyseur de contraintes va, `a partir
de cette donn´ee et des diff´erentes valeurs de nœuds possibles, g´en´erer toutes les structures de
donn´ees non isomorphes. Dans notre exemple, il va g´en´erer tous les arbres non isomorphes
comportant trois nœuds. Ce mˆeme langage est utilis´e pour sp´ecifier les r´esultats attendus,
autrement dit, l’oracle.
Les langages Alloy et Java ´etant diff´erents, l’outil TestEra requiert une fonction de
concr´etisation et une fonction d’abstraction. La premi`ere permet de traduire les donn´ees
d’entr´ee g´en´er´ees par ALCOA en Alloy en des instances Java utilisables par la m´ethode sous
test. La fonction d’abstraction fait le travail inverse et permet de traduire en Alloy le r´esultat
du test ex´ecut´e en Java. Une fois le r´esultat traduit en Alloy, ALCOA permet de v´erifier, en
fonction des param`etres d’entr´ee, la correction du r´esultat par rapport `a la sp´ecification.
Korat reprend la mˆeme id´ee que TestEra mais int`egre le tout directement en Java. Pour
cela, l’utilisateur doit d´ecrire en Java l’invariant structurel permettant d’identifier les
ins-tances valides utilis´ees en param`etre. L`a aussi, l’utilisateur doit borner le nombre d’atomes
de la structure et pr´eciser les valeurs que ceux-ci peuvent prendre. `A partir de ces
infor-mations, Korat g´en`ere toutes les instances, non isomorphes, d’entr´ees valides. Par exemple,
pour le test d’une fonction permettant de supprimer un ´el´ement pass´e en param`etre d’un
arbre binaire de taille born´ee, Korat g´en`ere tous les couples (arbre, element) tels que arbre
est un arbre binaire de taille born´ee et element est pr´esent dans l’arbre. Si Korat a `a sa
disposition une sp´ecification JML de la m´ethode sous test, il peut v´erifier que le r´esultat
obtenu satisfait bien la sp´ecification. Si aucune sp´ecification n’est donn´ee, Korat v´erifie au
moins que l’invariant structurel est satisfait.
AETG
Le principe de l’outil AETG System [CDFP97] est de ne pas couvrir toutes les
combi-naisons possibles de tous les param`etres mais de couvrir toutes les combicombi-naisons de couples
de param`etres en un minimum de tests. AETG se base sur l’hypoth`ese suivante : une erreur
r´esulte d’une combinaison d’au plus deux param`etres d’entr´ee. En cons´equence, une suite de
test est pertinente si, pour chaque valeur de chaque param`etre, celui-ci est associ´e au moins
une fois avec chaque valeur des autres param`etres. Cette hypoth`ese est v´erifi´ee si
l’appari-tion d’une erreur ne d´epend que d’une combinaison particuli`ere de deux des param`etres et
si cette erreur est ind´ependante des valeurs des autres param`etres. En g´en´eral la mise en
œuvre de cette technique se fait sur la base de consid´erations empiriques ou pragmatiques.
Cette hypoth`ese permet de r´eduire consid´erablement le nombre de configurations de valeurs
`a prendre en compte. AETG est configurable et il permet de consid´erer des couples, des
triplets, des n-uplets, etc.
Le tableau 2.2 d´ecrit trois param`etres A, B et C qui peuvent chacun prendre les valeurs
0 ou 1. Il existe huit combinaisons possibles de valeurs entre ces trois param`etres. Si nous
souhaitons couvrir seulement les combinaisons deux `a deux des param`etres, nous pouvons
dans ce cas nous contenter des lignes 2, 3, 4 et 5. Nous aurions aussi bien pu consid´erer les
lignes 1, 4 , 6 et 7.
sans interactions interactions 2 `a 2
Ligne A B C AB BC AC
1 0 0 0 - -
-2 0 0 1 00 01 01
3 0 1 0 01 10 00
4 0 1 1 - -
-5 1 0 0 10 00 10
6 1 0 1 - -
-7 1 1 0 - -
-8 1 1 1 11 11 11
Tab.2.2 – Combinatoire sur trois param`etres binaires.
K. Burr et W. Young [BY98] pr´esentent l’exemple d’une m´ethode avec 13 param`etres
pouvant tous prendre 3 valeurs diff´erentes. L’ensemble des combinaisons repr´esente 1 594
323 cas de test. La couverture par paires d’AETG permet de r´eduire le nombre de cas de
test n´ecessaires `a seulement 19 cas de test.
Dans le document
Outils pour la synthèse de tests et la maîtrise de l'explosion combinatoire.
(Page 36-39)