4.2 Principes du langage de synth`ese de tests
4.2.5 Alternative et cor´egion pour la g´en´eration de tests
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.
4.2.5 Alternative et cor´egion pour la g´en´eration de tests
Nous avons vu que les constructions alternative et cor´egion n’´etaient pas traduites lors
de la g´en´eration des tests abstraits 6
. Lorsque nous allons produire des tests concrets, ces
6
Ces deux constructions ont ´et´e initialement d´efinies pour produire des objectifs de tests pour l’outil
TGV. Leur s´emantique ´etant d´efinie au moment de la g´en´eration de l’objectif de test TGV, nous pouvons
envisager une autre s´emantique lorsque nous souhaitons g´en´erer des tests ex´ecutables.
constructions devront ˆetre traduites en code ex´ecutable. Nous proposons dans cette section
plusieurs traductions pour ces op´erations. Cependant, nous n’avons pas eu l’occasion de
v´erifier par l’exp´erience la pertinence de ces deux op´erateurs pour la g´en´eration de tests.
La traduction la plus intuitive que l’on a de la cor´egion est d’encapsuler chaque appel de la
cor´egion dans un thread s´epar´e. Chaque thread s’ex´ecute alors de mani`ere parall`ele.
L’alter-native pourrait elle se traduire par un test comportant plusieurs chemins, le choix de prendre
un chemin plutˆot qu’un autre se faisant de mani`ere non-d´eterministe lors de l’ex´ecution.
N´eanmoins, il n’est pas raisonnable de produire des tests qui sont non-d´eterministes. En
effet, il est important, pour l’ing´enieur en charge du test, de pouvoir d´egager des s´equences
d’appels qui conduisent syst´ematiquement `a une erreur. Si le cas de test est non-d´eterministe,
plusieurs ex´ecutions du mˆeme cas de test peuvent conduire `a des r´esultats diff´erents. Bien
entendu, ce cas peut arriver lorsque l’application est elle-mˆeme non-d´eterministe, mais, dans
la mesure du possible nous pensons qu’il est toujours pr´ef´erable d’obtenir des comportements
reproductibles afin de permettre l’identification et la correction de l’erreur.
Les sch´emas S2etS3ont ´et´e d´efinis afin d’illustrer ces deux m´ecanismes. Nous proposons
ici une interpr´etation pour ces deux constructions. La traduction de ces constructions peut se
faire `a plusieurs niveaux. Nous pouvons partir des tests abstraits contenant les constructions
non interpr´et´ees et les interpr´eter lors d’une seconde passe. Nous pouvons aussi inclure
l’interpr´etation de ces constructions directement dans la fonction de traduction. Pour finir,
nous pouvons traduire ces constructions au moment de produire les tests concrets.
Nous avons choisi de faire cette traduction lors d’une seconde passe produisant des tests
abstraits. En faisant ce choix nous gardons la possibilit´e d’implanter d’autres mani`eres de
traduire ces constructions. Comme nous produisons des tests abstraits, ils pourront ˆetre
tra-duits vers diverses plates-formes d’ex´ecution. Nous gardons de cette mani`ere une certaine
flexibilit´e quant `a l’utilisation de ces constructions et aux s´emantiques que nous pouvons
leur donner.
Utilisation de la cor´egion : S2
S2 = MTC!sch1.newRdyP12 ; <MTC!sch1.newRdyP12><MTC!sch1.rdySwapP13> ;
MTC!sch1.rdySwapP13^2..2
newRdyP12 ={new(x), rdy(x)} avec x={p1, p2}
RdySwapP13 ={rdy(y), swap()}avec y ={p1, p2, p3}
Comme chaque groupe se d´eplie en 4 appels, nous avons 4 appels pour le premier groupe
du sch´ema, puis 4∗4 appels pour la cor´egion, puis 4∗4 appels pour la boucle de deux appels
au groupe rdySwapP13. Comme tous ces ´el´ements sont en s´equence, nous g´en´erons toutes
les combinaisons. Le nombre de tests g´en´er´es par S2, est donc de 4∗(4∗4)∗(4∗4) = 1024.
Voici quelques exemples de tests abstraits g´en´er´es :
MTC!Sch1.rdy(p1) ; MTC!Sch1.rdy(p1)
seq 22 = MTC!Sch1.new(p1) ; <MTC!Sch1.new(p1)><MTC!Sch1.rdy(p1)> ;
MTC!Sch1.rdy(p1) ; MTC!Sch1.rdy(p2)
...
seq 2i = MTC!Sch1.new(p1) ; <MTC!Sch1.rdy(p1)><MTC!Sch1.rdy(p2)>;
MTC!Sch1.swap() ; MTC!Sch1.rdy(p1)
...
seq 2k = MTC!Sch1.new(p1) ; <MTC!Sch1.rdy(p2)><MTC!Sch1.rdy(p1)> ;
MTC!Sch1.swap() ; MTC!Sch1.rdy(p1)
...
seq 2n = MTC!Sch1.rdy(p1) ; <MTC!Sch1.new(p1)><MTC!Sch1.rdy(p1)> ;
MTC!Sch1.rdy(p3) ; MTC!Sch1.rdy(p1)
...
Si l’utilisateur d´ecide de mettre plusieurs appels dans une cor´egion, nous comprenons
qu’il n’attache pas d’importance `a l’ordre dans lequel les appels sont effectu´es. Nous pouvons
donc ordonner de mani`ere al´eatoire les appels d’op´erations et produire ainsi une s´equence
originale. Si la s´equence est produite al´eatoirement, son ex´ecution est d´eterministe (sauf si
l’application n’est pas d´eterministe).
Par exemple, lors de la production du test concret de seq 2i, nous pouvons g´en´erer l’une
des deux s´equences abstraites suivantes :
seq 2ia = MTC!Sch1.new(p1) ; MTC!Sch1.rdy(p1) ; MTC!Sch1.rdy(p2) ;
MTC!Sch1.swap() ; MTC!Sch1.rdy(p1)
seq 2ib = MTC!Sch1.new(p1) ; MTC!Sch1.rdy(p2) ; MTC!Sch1.rdy(p1) ;
MTC!Sch1.swap() ; MTC!Sch1.rdy(p1)
En effectuant certains choix, nous pouvons ˆetre amen´e `a g´en´erer plusieurs fois les mˆemes
tests (ie des tests syntaxiquement identiques). La mani`ere de traiter ce genre de cas n’est
pas ´evidente. Par exemple, si nous g´en´erons la s´equence seq 2ib, lorsque nous allons traiter
la s´equence seq 2k, nous pouvons g´en´erer l’une des s´equences suivantes :
seq 2ka = MTC!Sch1.new(p1) ; MTC!Sch1.rdy(p2) ; MTC!Sch1.rdy(p1) ;
MTC!Sch1.swap() ; MTC!Sch1.rdy(p1)
seq 2kb = MTC!Sch1.new(p1) ; MTC!Sch1.rdy(p1) ; MTC!Sch1.rdy(p2) ;
MTC!Sch1.swap() ; MTC!Sch1.rdy(p1)
Si la s´equence g´en´er´ee est seq 2ka, nous aurons g´en´er´e deux fois la mˆeme s´equence. Nous
pouvons envisager alors un autre tirage ou d´ecider de ne g´en´erer qu’une seule s´equence au
lieu de deux.
Utilisation de l’alternative : S3
S3 = MTC!sch1.newRdyP12 ; (MTC!sch1.newRdyP12 || MTC!sch1.rdySwapP13) ;
MTC!sch1.rdySwapP13^2..2
Le sch´ema S3 est tr`es semblable au sch´ema S2 pour ce qui est de sa structure et donc
du nombre de tests g´en´er´es. En effet, `a la place de la cor´egion nous avons une alternative.
Or, ces deux constructeurs se d´eplient de la mˆeme mani`ere, l’outil produira donc aussi 1024
s´equences de test abstraites `a partir de S3.
Voici quelques exemples de tests abstraits g´en´er´es :
seq 31 = MTC!Sch1.new(p1) ; (MTC!Sch1.new(p1)|MTC!Sch1.rdy(p1)) ;
MTC!Sch1.rdy(p1) ; MTC!Sch1.rdy(p1)
seq 32 = MTC!Sch1.new(p1) ; (MTC!Sch1.new(p1)|MTC!Sch1.rdy(p1)) ;
MTC!Sch1.rdy(p1) ; MTC!Sch1.rdy(p2)
...
seq 3i = MTC!Sch1.new(p2) ; (MTC!Sch1.rdy(p2)|MTC!Sch1.swap()) ;
MTC!Sch1.rdy(p1)
...
seq 3k = MTC!Sch1.rdy(p1) ; (MTC!Sch1.new(p1)|MTC!Sch1.rdy(p1)) ;
MTC!Sch1.rdy(p3) ; MTC!Sch1.rdy(p1)
...
L’alternative est une construction exprimant un choix non-d´eterministe. L`a encore, nous
ne pouvons pas nous permettre de g´en´erer un test qui exprimerait ce non-d´eterminisme.
N´eanmoins, si l’utilisateur utilise cette construction pour g´en´erer des tests, nous pouvons
l’interpr´eter comme le fait qu’il pr´ef`ere laisser l’outil faire le choix `a sa place. En cons´equence,
lorsque nous avons une alternative, au moment de g´en´erer les tests concrets, nous pouvons
tirer al´eatoirement l’appel ou la s´equence d’appel qui sera effectu´e.
Par exemple, lors de la production du test concret de seq 31, nous pouvons g´en´erer, au
choix, l’une des deux s´equences suivantes :
seq 31a = MTC!Sch1.new(p1) ; MTC!Sch1.rdy(p1) ; MTC!Sch1.rdy(p1) ;
MTC!Sch1.rdy(p1)
seq 31b = MTC!Sch1.new(p1) ; MTC!Sch1.new(p1) ; MTC!Sch1.rdy(p1) ;
MTC!Sch1.rdy(p1)
Tout comme pour la cor´egion, nous pouvons nous retrouver `a g´en´erer deux fois la mˆeme
s´equence. Le mˆeme choix s’offre alors `a nous, `a savoir, reg´en´erer une nouvelle s´equence ou
supprimer la s´equence redondante. Dans certains cas, le choix s’imposera de lui-mˆeme
puis-qu’il peut arriver que toutes les possibilit´es existent d´ej`a.
Une fois que les s´equences de test abstraites sont g´en´er´ees, il reste `a g´en´erer les tests
concrets qui seront effectivement ex´ecut´es sur l’application.
Dans le document
Outils pour la synthèse de tests et la maîtrise de l'explosion combinatoire.
(Page 71-74)