Sunteți pe pagina 1din 10

L12.

Testarea sistemelor software


Obiective
Scopul acestei lucrări de laborator este studiul unor metode de testare la nivel de
componente software cum ar fi testarea funcţională şi testarea structurală precum şi testarea la
integrare a sistemului software.
După parcurgerea acestui referat, studenţii vor avea cunoştinţele necesare:
 testării bazate pe tabele de decizie;
 testării bazate pe grafuri cauză-efect;
 testării exhaustive;
 testării la nivel de instrucţiune şi de ramură;
 testării la nivel de cale;
 testării la integrare.

1. Clasificarea metodelor de testare


Metodele de testare pot fi clasificate în două mari categorii:
 Testarea black box (cutie neagră). Această abordare se concentrează asupra intrărilor,
ieşirilor şi funcţionalităţii modulelor software.
 Testarea white box (cutie albă). Această abordare presupune inspectarea structurii
codului modulelor software.
Testarea black box se mai numeşte testare funcţională. Punctul de plecare este fie o
specificaţie, fie codul. În cazul codului, datele de test trebuie să permită verificarea
funcţionalităţii programului. Testerul nu este interesat de modul în care este implementat
programul respectiv, ci de modul în care acesta furnizează răspunsul dorit.
Testarea white box, cunoscută şi sub numele de testare structurală, presupune analizarea
implementării programului (modulului). Se verifică executarea corectă a tuturor căilor şi
ramurilor codului programului testat.

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ă.

Figura 2. Rezervor de lichid


Regulile de producţie sunt următoarele::
 Dacă senzorul 1 este activ (prea mult lichid în rezervor), atunci se deschide valva de
ieşire.
 Dacă senzorul 2 este activ ( prea puţin nivel în rezervor) atunci se deschide valva de
intrare.
În plus, se adaugă o acţiune de avertizare în momentul în care senzorii furnizează „0” logic.
Tabelul de decizie complet are 22  4 coloane (fig. 3a). Dacă nu interesează mesajele de avertizare în
caz de eroare, se poate reduce dimensiunea tabelului de decizie aşa cum se poate observa în figura 3b.
În general, pentru „n” condiţii se va ajunge la 2n combinaţii, deoarece fiecare coloană a
tabelului trebuie folosită cel puţin o dată. Prin urmare vor exista 2n cazuri de test. Se observă că
şi pentru valori mici ale lui „n”, tabelul de decizie ajunge la dimensiuni mari. Această creştere
exponenţială se explică prin faptul că nu au fost luate în considerare constrângerile între
variabilele din condiţii, constrângeri ce presupun limitări fizice şi conceptuale între variabile. A
treia coloană din tabelul de decizie din figura 3b poate fi astfel eliminată.

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

Figura 3a. Tabel de decizie complet

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

Figura 3b. Tabel de decizie redus

2.2. Testarea funcţională bazată pe grafuri cauză-efect


Principalul dezavantaj al metodei bazate pe tabele de decizie este că intrările sunt luate în
considerare separat chiar dacă problema necesită o altă abordare. Garfurile cauză-efect iau în
considerare relaţiile dintre combinaţii specifice de intrări (cauze) şi ieşiri (efecte). Se evită în
acest mod creşterea exponenţială a dimensiunii tabelelor de decizie. Cauzele şi efectele sunt
reprezentate ca noduri ale grafului. Un astfel de graf include un număr de noduri intermediare
care leagă cauzele şi efectele prin expresii logice.
Exemplu. Se consideră un bancomat (ATM) simplu. Lista cauzelor şi efectelor este
următoarea:
Cauze Efecte
C1: comanda este „creditare” E1: tipăreşte „comandă nevalidă”
C2: comanda este „debitare” E2: tipăreşte „număr cont nevalid”
C3: numărul de cont este valid E3: tipăreşte „sumă debit nevalidă”
C4: tranzacţia este validă E4: cont debit
E5: cont credit
Graful cauză-efect este prezentat în figura 4. Nodurile intermediare realizează operatorii
logici „and” şi „or”. Simbolul de negare „” stabileşte faptul că efectul are valoarea de adevăr
„true” doar dacă nodul asociat este „false”.
Graful cauză-efect ajută la determinarea cazurilor de test corespunzătoare. Aceste cazuri
de test se obţin parcurgând în sens invers (de la efect la cauză) porţiuni din graful prezentat în
figura 4. Dacă spre exemplu suntem interesaţi în determinarea cauzelor efectului E 3 se urmăreşte
porţiunea de graf prezentată în figura 5.

Figura 4. Graf cauză-efect

Figura 5. Determinarea cauzelor efectului E3

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>.

În grafurile cauză-efect pot fi introduse constrângeri suplimentare între intrări, cum ar fi


cele de tipul „a implică b”. Acestea reduc numărul cazurilor de test deoarece unele combinaţii de
intrări nu vor mai fi luate în considerare în procedura de testare.

2.3. Testarea exhaustivă


Testarea exhaustivă face parte din metoda de testare black box. Această metodă este
impracticabilă dar furnizează o imagine asupra complexităţii procesului de testare. Un test
exhaustiv trebuie să arate că programul funcţionează corect pentru toate intrările posibile.
Exemplu. Se consideră ecuaţia de gradul doi de forma ax 2  bx  c  0 , unde a, b, c sunt
parametrii ecuaţiei. Din punct de vedere funcţional, programul transformă spaţiul tridimensional
al parametrilor (a, b, c) într-un spaţiu bidimensional al rădăcinilor ecuaţiei (r1, r2). Testarea
exhaustivă pleacă de la reprezentarea internă a parametrilor. Dacă presupunem că reprezentarea
internă este pe 16 biţi, pentru fiecare intrare vom avea 216 cazuri de test. Considerând toate cele
trei intrări, vom avea în final 248 cazuri de test ce trebuie executate, ceea ce este, evident,
nefezabil.
3. Testarea structurală

Testarea structurală presupune dezvoltarea de cazuri de test ce iau în considerare


structura codului (logica internă). Există mai multe categorii de testare structurală, funcţie de cât
de complet trebuie să fie procesul de testare şi de restricţiile de timp.
Testarea la nivel de instrucţiune este o formă de testare primară, care necesită
executarea fiecărei instrucţiuni cel puţin o dată.
Exemplu. Se consideră următoarea porţiune de cod care se presupune că determină
modulul lui y.
begin
if (y ≥ 0) then y = 0-y; abs = y;
end;

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.

Figura 8. Testarea la nivel de ramură


Figura 9. Testarea la nivel de cale
În cazul lipsei buclelor, numărul căilor este determinat de numărul de noduri de decizie şi
de distribuţia lor. Cele două extreme ale numărului de căi dintr-un graf se pot observa în
exemplul din figura 10. În cazul în care se unesc ramurile, blocurile de decizie sunt „stivuite”
unele peste altele (figura 10a). Unirea ramurilor poate duce la 2n căi posibile. Numărul maxim
de căi dintr-un graf este deci 2n . În cazul în care nu se face unirea ramurilor există n  1 căi
posibile (vezi figura 10b), deci n  1 ≤ număr de căi ≤ 2n .

(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.

Figura 11. Ierarhie de module software

Testare bottom-up Testare top-down


Testare în straturi
Testare big-bang
Stratul de test este situat între
A şi (B, C, D)
Figura 12. Exemple de testări la integrare

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

4. Se consideră următoarele specificaţii software pentru un sistem de transmitere a


datelor:
 Caracterul din coloana 1 trebuie să fie A, B sau C.
 Caracterul din coloana 2 trebuie să fie o cifră.
 Caracterul din coloana 3 trebuie să fie o cifră mai mare de 5.
În această situaţie, modificarea fişierului este completă (este emis un mesaj de
modificare. Dacă primul caracter este incorect, se trimite mesajul M1. Dacă al doilea caracter
este incorect se trimite mesajul M2. Mesajul M3 este emis dacă al treilea caracter este incorect.
Desenaţi un graf cauză-efect şi propuneţi un tabel de decizie redus pentru testare.
5. Se consideră o problemă de calcul a valorii unei funcţii polinomiale de ordinul trei:
a 0  a1 x  a 2 x 2  a 3 x 3 .
Care este numărul de cazuri de test dacă se foloseşte testarea exhaustivă, presupunând că se
utilizează reprezentarea pe 32 biţi pentru reprezentarea unui număr real. Presupunând că fiecare
caz de test durează 7sec, care este timpul necesar aplicării acestei metode de testare.
6. Se consideră următorul fragment de cod, în care există o eroare evidentă:
dx=0.1;
N=50;
for (i=0; i<=N; i++)
{
z[i]=sin(x)/(x-2.5);
x=x+dx;
}
Care tip de testare structurală pune în evidenţă eroarea?
7. Pentru ierarhia de module din figura 15, realizaţi testarea la integrare prin metodele
bottom-up, top-down şi în straturi.

Figura 15

S-ar putea să vă placă și