• Aucun résultat trouvé

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.