4.2 Principes du langage de synth`ese de tests
4.2.4 Langage de sch´ema de tests
Le langage de sch´ema de tests permet, `a partir des ´el´ements d´efinis ci-dessus, de d´ecrire
de mani`ere synth´etique un ensemble de s´equences abstraites pouvant ensuite ˆetre traduites
en s´equences de test ex´ecutables.
Grammaire du langage
Le langage se compose de quatre op´erateurs qui sont le s´equencement, l’alternative, la
co-r´egion et la boucle. Ces quatre op´erateurs permettent de composer les ´el´ements de base du
langage que sont les appels de m´ethodes. Nous pr´esentons, table 4.1 la grammaire abstraite
du langage de sch´ema de tests.
Sch´ema : := S´equence k Sch´ema
| S´equence
S´equence : := Structure; S´equence
| (Sch´ema); S´equence
| Structure
Structure : := Boucle
| Cor´egion
| Appel
Cor´egion : := <Appel>Cor´egion
| <Appel><Appel>
Boucle : := Appel∧
entier..entier
| (Sch´ema)∧
entier..entier
Appel : := inst !inst.groupe
Tab. 4.1 – Grammaire du langage de sch´emas de test.
L’alternative , repr´esent´ee par le mot cl´e ”k” exprime un choix non-d´eterministe entre
deux s´equences d’appels.
Le s´equencement , repr´esent´e par le mot cl´e ”;”, est l’op´eration de base des sch´emas de
test.
La cor´egion , repr´esent´ee par le mot clef ”<>” est un m´ecanisme permettant de repr´esenter
le caract`ere parall`ele d’une ex´ecution. Si nous avons par exemple<app1><app2><app3>,
cela signifie que nous n’imposons pas d’ordre dans la transmission des appels de m´ethode
app1, app2 etapp3.
Les boucles permettent de r´ep´eter plusieurs fois un mˆeme appel de m´ethode ou un mˆeme
sch´ema dans un intervalle donn´e. Si nous avons par exemple : app ∧2..4
, cela signifie que nous
avons deux, trois ou quatre appels successifs `a app.
Instances et groupes inst correspond aux instances. Dans un sch´ema de tests, une
ins-tance peut ˆetre clairement identifi´ee ou remplac´ee par ”*”. Dans ce cas, nous rempla¸cons
l’´etoile par toutes les instances pouvant correspondre aux m´ethodes qui sont associ´ees au
groupe lors de la g´en´eration des s´equences de tests.
L’alternative et la cor´egion sont des cas `a part. En effet, ces constructions peuvent assez
naturellement s’interpr´eter par une g´en´eration de tests non-d´eterministes. Nous reviendrons
sur ce point `a la section 4.2.5.
`
A partir des instances d´efinies pour la campagne de tests, des groupes et du langage de
sch´ema de tests, nous pouvons d´efinir divers sch´emas :
S1 = MTC!sch1.newRdyP12^2..2 ; MTC!sch1.rdySwapP13^2..3
S2 = MTC!sch1.newRdyP12 ; <MTC!sch1.newRdyP12><MTC!sch1.rdySwapP13> ;
MTC!sch1.rdySwapP13^2..2
S3 = MTC!sch1.newRdyP12 ; (MTC!sch1.newRdyP12 || MTC!sch1.rdySwapP13) ;
MTC!sch1.rdySwapP13^2..2
Dans ces sch´emas, nous voyons apparaˆıtre l’instance MTC (Main Test Component). Cette
instance est une instance g´en´erique d´esignant le testeur ou le programme qui ex´ecutera les
tests.
Le sch´ema S1 est un cas typique de sch´ema de tests utilis´e pour g´en´erer des s´equences
de test. Les sch´emas S2 et S3 sont d´efinis ici pour illustrer la mani`ere dont nous pouvons
utiliser les constructeurs d’alternative et de cor´egion lors de la g´en´eration de tests.
G´en´eration des tests `a partir de S1
newRdyP12 ={new(x), rdy(x)} avec x={p1, p2}
RdySwapP13 ={rdy(y), swap()}avec y ={p1, p2, p3}
Le premier sch´ema, S1, fait deux appels au groupe newRdyP12 suivis de deux `a trois
appels au groupe rdySwapP13. Si nous suivons la s´emantique du langage de sch´ema de
tests, nous devons d´eplier les diff´erents groupes. Ainsi, MTC !sch1.newRdyP12 va produire
quatre appels diff´erents : MTC !sch1.new(p1), MTC !sch1.new(p2), MTC !sch1.rdy(p1) et
MTC !sch1.rdy(p2). De mˆeme, MTC !sch1.rdySwapP13 va produire les quatres appels
sui-vants : MTC !sch1.rdy(p1),
MTC !sch1.rdy(p2), MTC !sch1.rdy(p3) etMTC !sch1.swap().
La boucle, born´ee par les entiers 2..2, portant sur l’appel au groupe newRdyP12 va
pro-duire 16 s´equences diff´erentes. En effet, comme nous avons deux appels au groupe en question
et que le groupe, une fois d´epli´e, produit quatre appels, nous avons 4∗4 combinaisons.
La boucle, born´ee par les entiers 2..3, portant sur le groupe rdySwapP13 va produire 80
appels diff´erents : 16(4∗4) appels sont g´en´er´es par la succession de deux appels au groupe,
auxquels il faut ajouter les 64 (4∗4∗4) appels g´en´er´es par la succession de trois appels au
groupe.
Comme les deux boucles sont en s´equence, le nombre de tests g´en´er´es est la combinaison
des ensembles g´en´er´es `a partir des deux boucles. Ce qui nous donne 16∗80 = 1280 tests.
Voici quelques exemples de tests abstraits g´en´er´es :
seq 11 = MTC!Sch1.new(p1) ; MTC!Sch1.new(p1) ; MTC!Sch1.rdy(p1) ;
MTC!Sch1.rdy(p1)
seq 12 = MTC!Sch1.new(p1) ; MTC!Sch1.new(p1) ; MTC!Sch1.rdy(p1) ;
MTC!Sch1.rdy(p2)
...
seq 1i = MTC!Sch1.new(p2) ; MTC!Sch1.rdy(p2) ; MTC!Sch1.swap() ;
MTC!Sch1.rdy(p1)
...
seq 1k = MTC!Sch1.rdy(p1) ; MTC!Sch1.new(p1) ; MTC!Sch1.rdy(p1) ;
MTC!Sch1.rdy(p3) ; MTC!Sch1.rdy(p1)
...
Fonction de traduction
Soit T une fonction de traduction prenant en entr´ee un sch´ema de tests S ainsi qu’un
d´eploiement I et retournant un ensemble Seqa de s´equences abstraites dont la grammaire
est donn´ee table 4.2. Ces s´equences abstraites peuvent ensuite ˆetre traduites en objectifs de
test sous la forme d’iolts ou, en s´equences de test VDM ou Java. Compte tenu des diff´erents
langages cibles possibles, les op´erateurs de cor´egion et d’alternative ne sont pas directement
interpr´et´es `a la g´en´eration. Ceci nous permet de leur attribuer diff´erentes s´emantiques en
fonction du langage cibl´e.
1. TSchema(Seq1 k Sch1) = {s1ks2|s1∈TSequence(Seq1)∧s2∈TSchema(Sch1)}
2. TSchema(Seq1) = TSequence(Seq1)
3. TSequence(Struct1 ; Seq1) = {s1;s2|s1∈TStructure(Struct1)∧s2∈TSequence(Seq1)}
4. TSequence((Sch1); Seq1 ) = {(s1);s2|s1∈TSchema(Sch1)∧s2∈TSequence(Seq1)}
5. TSequence(Struct1) = {s1|s1∈TStructure(Struct1)}
7. TStructure(Cor1) = TCoregion(Cor1)
8. TStructure(App1) = TAppel(App1)
9. TCoregion(<appel1><appel2>) = {< a1 >< a2 > |a1 ∈ TAppel(appel1) ∧ a2 ∈
TAppel(appel2)}
10. TCoregion(<appel1>Cor1) = {< a1> c1|a1∈TAppel(appel1)∧c1∈TCoregion(Cor1)}
Les premi`eres r`egles appliquent r´ecursivement le d´epliage des sch´emas, des s´equences,
des structures et des co-r´egions. Les r`egles 11 et 12 traitent le cas des boucles en
uti-lisant la fonctionitere(voir plus loin). La r`egle 13 correspond au d´epliage d’un groupe.
11. TBoucle(App1∧
binf..bsup) = itere(TAppel(App1), binf, bsup)
12. TBoucle((S1)∧
binf..bsup) = itere({(s1)|s1∈TSchema(S1)}, binf, bsup)
13. TAppel(Appelant !Appel´e.Groupe) = degroupe(Appelant, Appel´e, Groupe) Appel´e
et Appelant peuvent soit ˆetre une instance deI soit *. Dans le dernier cas, cela signifie
que toutes les instances de I doivent ˆetre consid´er´ees lors de la g´en´eration.
– Soit N omM ethodes: Groupe → N omM ethode une fonction qui prend un groupe en
param`etre et renvoie l’ensemble des noms de m´ethode du groupe.
– Soit M ethodes : Groupe×N omM ethode → M ethodesG une fonction qui prend en
param`etre un groupe et un nom de m´ethode et renvoie la signature de la m´ethode de
nom N omM ethode appartenant au groupe pass´e en param`etre.
– Soit P arametres : M ethodesG → PmG une fonction qui prend, en param`etre, la
si-gnature d’une m´ethode appartenant `a un groupe et renvoie un tuple contenant les
ensembles de valeurs d´efinies pour cette m´ethode.
– Soit Π le produit cart´esien entre n ensembles.
Par exemple, soit g1 =f oo(x, y), bar(x) avec x={a, b, c} ety={1,2} :
1. N omM ethodes(g1) renvoie l’ensemble de noms de m´ethodes {f oo, bar}
2. M ethodes(g1, f oo) renvoie la m´ethode f oo({a, b, c},{1,2})
3. P arametres(f oo({a, b, c},{1,2})) renvoye le tuple ({a, b, c},{1,2})
4. Π({a, b, c},{1,2}) renvoie {(a,1),(a,2),(b,1),(b,2),(c,1),(c,2)}
Ces quatre premi`eres fonctions servent de base `a la g´en´eration des tests puisqu’elles
permettent de d´eplier le contenu des groupes. Les trois fonctions suivantes permettent de
d´eplier les boucles d’appels et d’instancier les appels de m´ethodes en fonction des instances
d´efinies dans la campagne de tests.
– Soit itere(S Seq, b inf , b sup) :ensembledeSeqa×borne×borne → ensembledeSeqa
une fonction qui permet de d´eplier les boucles. Cette fonction va ainsi g´en´erer toutes les
s´equences compos´ees deb inf`ab sup´el´ements de l’ensemble pass´e en param`etres. Cette
fonction s’appuie sur la fonctiongenere(S Seq, nb):ensembledeSeqa×entier →ensemble
de Seq aqui, pour un nombrenbdonn´e pass´e en param`etre et un ensemble de s´equences
S Seq va g´en´erer toutes les combinaisons de nb s´equences de S Seq. Par exemple,
itere({a,b},1,2) va renvoyer l’ensemble {”a”,”b”,”a ;a”,”a ;b”,”b ;b”,”b ;a”}.
– Soit degroupe :instance × instance × Groupe → ensemble de Seq a une fontion qui
va permettre, d’instancier tous les appels d´efinis par un groupe donn´e en param`etre.
Cette fonction prend en param`etre une instance de d´epartiDep, une instance d’arriv´ee
iDeset un groupeG. Elle va g´en´erer toutes les instanciations de m´ethode pour chaque
m´ethode et chaque valeur de param`etre contenues dansG. Nous effectuons donc, pour
une m´ethode donn´ee, la combinaisons de toutes ses valeurs de param`etres. `A partir de
cet ensemble de m´ethodes dont les param`etres sont instanci´es, la fonction va construire
les appels de m´ethodes en fonction deiDesetiDep, en respectant les r`egles suivantes :
1. chaque appel de m´ethode s’effectue sur une instance dont la classe poss`ede la dite
m´ethode ;
2. chaque appel de m´ethode s’effectue `a partir d’une instance de classe en relation
avec l’instance d’arriv´ee ;
3. lorsque iDep(respectivement iDes) est ´egal `a *, on prend en consid´eration toutes
les instances d´efinies dans la campagne comme ´etant potentiellement une instance
de d´epart (respectivement d’arriv´ee).
genere : ensemble de Seq a × entier → ensemble de Seq a
genere(S Seq,nb) =
d´ebut
si nb= 1
alors
/**
* Lorsque nb vaut 1, cela signifie qu’il n’y a pas de r´ep´etition
* donc qu’il n’y a pas de combinaisons entre les ´el´ements de
* l’ensemble de d´epart. On le renvoie donc tel quel.
*/
retourner S Seq
sinon
/**
* nb ne pouvant ˆetre n´egatif o`u nul, il faut effectuer toutes
* les combinaisons de nb ´el´ements de l’ensemble S Seq.
* Ces combinaisons se font par s´equencement entre chaque
* s´equence de S Seq et toutes les combinaisons de nb-1 ´el´ements
* de l’ensemble S Seq
*/
retourner {"s1;s2"| s1 ∈ S Seq ∧ s2 ∈ genere(S Seq, nb−1)}
fin
itere : ensemble de Seq a × borne × borne → ensemble de Seq a
itere(S Seq, b inf , b sup) =
d´ebut
SRes = {}
pour i allant de b inf `a b sup
* Nous g´en´erons toutes les combinaisons de i ´el´ements
* parmi les ´el´ements de l’ensemble de d´epart
*/
SRes = SRes S
genere(S Seq, i)
retourner SRes
fin
degroupe : instance × instance × Groupe → ensemble de Seq a
degroupe(iDep, iDes, G) =
d´ebut
//On commence par d´eplier les appels `a partir du groupe
appels = {m(v1, v2, ..., vn) | m ∈ N omM ethodes(G)
& (v1, v2, ..., vn) ∈ Π(P arametres(M ethodes(G, m)))}
//Puis, en fonction de la valeur des instances de d´epart et d’arriv´ee
//on d´efinit les ensembles concern´es.
si iArr = *
alors iArrEns = I //Si l’instance d’arriv´ee n’est pas pr´ecis´ee,
//on prend toutes les instances d´efinies au niveau
//du d´eploiement.
sinon si iDes ∈ I
alors iArrEns = {iDes} //Sinon on cr´ee un ensemble contenant
//pour seul ´el´ement, l’instance pass´ee en param`etre.
sinon retourner erreur
si iDep = *//On proc`ede de la mˆeme fa¸con pour l’instance de d´epart.
alors iDepEns = I
sinon si iDes ∈ I
alors iDepEns = {iDep}
sinon retourner erreur
/**
* On d´efinit maintenant tous les couples d’instances d´epart!arriv´ee
* `a partir des ensembles pr´ec´edemment construits.
* Ces couples ne sont construits que pour les instances dont
* les classes sont en relation: (Classe(dep), Classe(des)) ∈ R C
*/
dep arr = {dep!des | ∀ dep ∈ iDepEns,
∀ des ∈ iArrEns,
(Classe(dep), Classe(des)) ∈ R C }
/**
* On concat`ene tous les appels de m´ethodes, cr´e´es `a partir du groupe
* pass´e en param`etre aux couples d’instances d´epart!arriv´ee
* `a partir de l’ensemble dep arr et tel que:
*/
appelsInst = {id!ia.app | ∀ app ∈ appels,
∀ id!ia ∈ dep arr,
appartient(app, Classe(ia))}
retourner appelsInst
fin
TestAbstrait : := S´equence k TestAbstrait
| S´equence
S´equence : := Structure;S´equence
| (TestAbstrait);S´equence
| Structure
Structure : := Cor´egion
| Appel
Cor´egion : := <Appel>Cor´egion
| <Appel><Appel>
Appel : := inst !inst.m´ethode(Param`etres)
| inst !inst.m´ethode()
Param`etre : := valeur
| Param`etres,valeur
Tab.4.2 – Grammaire des tests abstraits.
Nous pr´esentons table 4.2 la grammaire des tests abstraits. Cette grammaire est tr`es
proche de la grammaire des sch´emas de tests. Nous pouvons constater que les boucles ont
disparu ainsi que les groupes. Tous les appels de m´ethode sont instanci´es. En revanche,
la cor´egion et l’alternative restent pr´esentes. Comme nous allons le voir juste apr`es, ces
constructions peuvent ˆetre traduites de diff´erentes mani`eres. Il est important de noter que ces
deux ´el´ements doivent ˆetre traduits avant la g´en´eration des tests concrets. Seules les s´equences
constitu´ees uniquement d’appels instanci´es sont ensuite traduites en tests ex´ecutables.
Dans le document
Outils pour la synthèse de tests et la maîtrise de l'explosion combinatoire.
(Page 65-71)