Documente Academic
Documente Profesional
Documente Cultură
2. Testarea funcţională
2.1. Testarea bazată pe tabele de decizie
Această formă de testare prezintă interes atunci când cerinţele produsului software sunt
formulate cu ajutorul regulilor de decizie de tipul „if-then”.
Un tabel de decizie este compus dintr-un număr de coloane ce conţin toate situaţiile de
test. Partea superioară a coloanei conţine condiţiile ce trebuie satisfăcute. Partea de jos a tabelului
specifică acţiunile care au loc dacă sunt satisfăcute condiţiile din regulă. Un exemplu de tabel de
decizie este prezentat în figura 1.
Condiţii
... 1
Condiţia i 1
... 0
Acţiuni
... 0
Acţiunea j 1
... 0
Figura 1. Exemplu de tabel de decizie
Exemplu: Controlul nivelului de lichid. Să considerăm o problemă simplă de control
care are specificaţiile exprimate sub forma unor tabele de decizie. Se consideră un rezervor de
lichid cu doi senzori şi două valve (figura 2). Senzorul 1 detectează un nivel maxim acceptabil al
lichidului iar senzorul 2 detectează un nivel minim acceptabil al lichidului. Fiecare senzor
generează valoarea 1 logic dacă lichidul depăşeşte nivelul corespunzător. Altfel, senzorii
generează 0 logic. Valva de intrare se deschide doar dacă nivelul scade sub limita minimă
(senzorul 2 devine activ) iar valva de ieşire se deschide dacă senzorul 1 se activează.
S1 0 0 1 1 Condiţii
S2 0 1 0 1
Deschide valvă ieşire 0 0 1 1
Deschide valvă intrare 0 1 0 1 Acţiuni
Trimite mesaj „OK” 1 0 0 0
S1 0 1 1 Condiţii
S2 1 0 1
Deschide valvă ieşire 0 1 1
Deschide valvă intrare 1 0 1 Acţiuni
Se observă că C2, C3 şi C4 determină E3, în timp ce cauza C1 nu influenţează E3. Cauza
C1 poate fi privită drept o condiţie de tip „nu contează”, ce va fi notată cu „x”. Această
observaţie reduce dimensiunea tabelului de decizie corespunzător. Coloana din tabelul de decizie
care va fi folosită la generarea cazurilor de test este:
C1 C2 C3 C4
x 1 1 0
Dacă nu se iau în considerare condiţiile de tip „nu contează”, porţiunea rezultată din
tabelul de decizie va conţine 21 2 coloane ce implică o enumerare a valorilor cauzei C1.
Tabelul de decizie corespunzător grafului cauză-efect al unui ATM constă în cinci
coloane cu un număr substanţial de condiţii de tip „nu contează” (figura 6). Dacă nu ignorăm
aceste condiţii, va rezulta un tabel cu 24 16 coloane.
C1 0 1 x x 1
C2 0 x 1 1 x
C3 x 0 1 1 1
C4 x x 0 1 1
E1 1 0 0 0 0
E2 0 1 0 0 0
E3 0 0 1 0 0
E4 0 0 0 1 0
E5 0 0 0 0 1
Figura 6. Tabel de decizie ATM
În general, dacă se doreşte generarea unui tabel de decizie redus, se va adopta un
mecanism de tip „backtracking” pentru traversarea unui graf de la efecte spre cauze:
La parcurgerea inversă a unui nod „or” a cărui ieşire este „true” se vor utiliza doar
combinaţii de intrări care au valoarea de adevăr „true”. Dacă, spre exemplu, avem trei cauze (a,
b, c) ce afectează un nod de tip „or” a cărui ieşire este „true”, se vor considera doar combinaţiile
<a=true, b=false, c=false>,
<a=false, b=true, c=false>,
<a=false, b=false, c=true>.
La parcurgerea inversă a unui nod „and” a cărui ieşire este „false” se vor utiliza doar
combinaţii de intrări care au doar o singură valoare „false”. Pentru exemplul precedent, se vor
considera combinaţiile
<a=false, b=true, c=true>,
<a=true, b=false, c=true>,
<a=true, b=true, c=false>.
Cazul de test y 0 este suficient pentru a testa toate instrucţiunile din porţiunea de cod
prezentată. Este evident faptul că această formă de testare nu detectează o eroare evidentă a
codului şi anume aceea că nu se calculează de fapt modulul numărului y.
Testarea la nivel de ramură. Cazurile de test sunt alese astfel încât fiecare ramificaţie a
codului să fie executată cel puţin o dată.
Exemplu. Dacă ne referim la instrucţiunea anterioară, cazurile de test y 0 şi y 4
sunt suficiente pentru a executa ambele variante ale blocului de decizie. Pentru y 0 abs 0 .
Pentru y 4 abs 4 , ceea ce indică o eroare. Indiscutabil, această metodă de testare
conduce la detectarea erorilor.
Testarea la nivel de ramură/condiţie. Fiecare ramură trebuie parcursă cel puţin o dată şi
toate combinaţiile posibile ale condiţiilor de decizie trebuie executate.
Exemplu. Se consideră instrucţiunea:
if ((x<val_1) && (y>val_2)){z=calculeaza_1(x,y);
else z= calculeaza_2(x,y);}
Să considerăm cazurile de test x 6, y 12 , x 8, y 14 . Să presupunem că în
primul caz, blocul de decizie returnează „false” şi atunci se execută o ramură a codului, iar în cel
de-al doilea caz, blocul de decizie returnează „true” şi atunci se execută cealaltă ramură a
codului. Se observă faptul că, dacă o eroare este asociată cu o condiţie compusă dintr-un bloc de
decizie, ea rămâne nedetectată. Din acest motiv, testarea trebuie completată cu verificarea tuturor
subcondiţiilor ce apar în blocul de decizie. Deoarece în exemplul prezentat avem două
subcondiţii în blocul de decizie, trebuie adăugate două perechi suplimentare de teste şi anume
(„true”, „false”) respectiv („false”, „true”).
Observaţie. Dacă fiecare subcondiţie este privită ca o intrare singulară, atunci acest tip de
testare este analogă testării exhaustive, „n” condiţii necesitând 2n cazuri de test. În cazul în care
„n” creşte, testarea poate deveni nefezabilă.
Testarea la nivel de cale. Criteriul de acoperire a căilor consideră toate căile logice
dintr-un program şi duce la cazuri de test care verifică programul de-a lungul fiecărei astfel de
căi. Acest criteriu poate deveni impracticabil, mai ales în situaţiile în care programul are un
număr mare de căi. Cu toate acestea, este o metodă de testare folosită, mai ales pentru că permite
detectarea defectelor nedescoperite prin testarea la nivel de ramură.
Exemplu. Se consideră schema logică din figura 7.
Dacă se urmăreşte o testare la nivel de ramură se pot alege următoarele cazuri de test:
x 1, y 5 , x 0, y 15 .
Figura 7. Exemplu de schemă logică
Aceste două cazuri de test acoperă toate ramurile schemei logice (vezi figura 8), dar
execuţia lor corectă nu garantează lipsa erorilor.
Să considerăm situaţia în care la un anumit moment x 0 . În acest moment raportul
y / x eşuează. Acest scenariu nu a fost luat în considerare prin cazurile de test anterioare.
Testarea la nivel de cale (figura 9) evită situaţia prezentată anterior. Se pot considera
următoarele cazuri de test:
x 1, y 5 ; x 2, y 6 ; x 0, y 3 ; x 0, y 14 .
Se observă că şi în cazul unui exemplu relativ simplu, numărul de căi ce trebuie parcurse
este mai mare decât numărul ramurilor.
Din cauza complexităţii principiului acoperirii căilor este esenţială numărarea căilor
dintr-un program.
(a) (b)
Figura 10. Cazuri de acoperire a căilor
Este de remarcat faptul că şi în cazul valorilor mici pentru „n”, între cele două limite
există o diferenţă semnificativă. Pentru a micşora această diferenţă se poate face o descompunere
a grafului original în părţi mai mici şi se determină extremele separat. Să considerăm spre
exemplu un graf cu 6 noduri de decizie. În acest caz limitele ar fi 7 şi 64. Dacă se împarte graful
original în trei părţi, fiecare conţinând 2 noduri, limitele pentru fiecare parte ar fi 3 şi 4. Numărul
de căi de testat în graful original este cuprins între 27( 3*3*3) şi 64( 4* 4* 4) .
În cazul grafurilor ce conţin bucle, acoperirea căilor va fi restricţionată la bucle ce sunt
traversate doar o singură dată. Utilizând această abordare, se poate transforma orice graf cu o buclă
la unul fără nici o buclă. Ideea este de a împărţi orice nod, să zicem A, care este nod terminal al
unei căi cu reacţie în A şi A’. Noul nod este conectat cu nodul final sau cu orice alt nod de mai jos.
Construcţiile de bază ale programării structurate pot fi transformate în grafuri fără bucle.
Enumerarea căilor va fi dată de sumele produselor limitelor grafului fără bucle.
Criteriul de testare a căilor nu poate detecta toate defectele, deoarece se bazează pe faptul
că specificaţiile software sunt transformate cu exactitate în cod. Lipsa unor elemente îngreunează
semnificativ testarea.
4. Testarea la integrare
Componentele majore rezultate din scrierea codului se integrează formând sistemul final.
Plecând de la strategiile de proiectare se pot defini următoarele strategii de testare la
integrare:
Testarea top-down - porneşte de la modulul de pe cel mai înalt nivel şi necesită substitute.
Testarea bottom-up – pleacă de la module detaliate şi se extinde spre niveluri mai
înalte ale ierarhiei; această testare necesită drivere.
Testarea big-bang - modulele se integrează într-un singur pas iar testarea se face
asupra întregului sistem.
Testarea în straturi suprapuse - combină testarea bottom-up şi top-down definind un
anumit strat ţintă în ierarhia modulelor; modulele inferioare stratului ţintă se testează printr-o
abordare bottom-up iar cele superioare printr-o metodă top-down.
Exemplu. Pentru a ilustra aceste idei de testare, să considerăm o ierarhie simplă de
module ca în figura 11.
În figura 12 sunt prezentate clasele de testare la integrare pentru exemplul anterior.
Probleme
1. a) Care este numărul de teste necesar în cazul testării la nivel de ramură / condiţie
pentru n=5,10,20. b) Pentru aceleaşi valori ale lui n din cazul a) calculaţi limitele numărului de
cazuri de test în cazul testării la nivel de cale, în absenţa buclelor.
2. Se consideră schema logică din figura 13. Câte cazuri de test sunt necesare pentru
aplicarea testării la nivel de ramură, respectiv de cale.
Figura 13
3. Construiţi un tabel de decizie şi propuneţi o colecţie de cazuri de test pentru
următoarea problemă de control: sistemul ce trebuie controlat este echipat cu doi senzori, unul
măsoară temperatura T a mediului de lucru, iar celălalt măsoară presiunea P. În funcţie de
anumite condiţii, se consideră anumite comenzi : ZERO, NEGATIV, POZITIV (vezi figura 14).
P
mică OK mare
T
mare ZERO ZERO NEG
OK POZ ZERO NEG
mică POZ ZERO ZERO
Figura 14
Figura 15