Sunteți pe pagina 1din 31

Testarea software-ului

1. Introducere

Testarea software-ului se face rulând software-ul cu date de test. Se


mai numeşte testare dinamică a software-ului (dynamic software
testing), pentru a se deosebi de analiza statică (static analysis), numită
uneori şi testare statică, care presupune analizarea codului sursă
pentru identificarea problemelor.

Deşi există diverse tehnici pentru validarea software-ului, executarea


datelor cu date de test reprezintă un pas necesar.
2. Noţiuni fundamentale
Testarea exhaustivă este executarea fiecărui caz de test posibil, dar se
face rar, pentru că şi la sistemele simple există foarte multe cazuri de
testare posibile (Exemplu: un program cu 2 intrări de tip întreg pe 32
biţi conduc la un număr de 264cazuri de testare posibile).

Există două criterii de bază privind testarea software:


1. ce cazuri de testare să folosim (test case selection)
2. câte cazuri de testare sunt necesare (stopping criterion)

Test case selection se poate baza pe:


• specificaţii (functional);
• structura codului (structural);
• fluxul datelor (data flow);
• o selecţie aleatoare a cazurilor de testare (random).

Obs. Test case selection poate fi văzută ca o încercare de dimensionare


a cazurilor de testare prin intermediul intrărilor.
Stopping criterion se poate baza pe:
• criteriu de acoperire (coverage criterion), cum ar fi executarea a n
cazuri de testare în fiecare subdomeniu;
• criterii comportamentale (behavior criteria), cum ar fi testarea până o
rată a erorilor e mai mică decât un prag impus.

Un program poate fi gândit ca o mapare a spaţiului domeniu la un


spaţiu al răspunsurilor. Dându-se o intrare (input), care e un punct în
spaţiul domeniu, programul produce o ieşire (output), care e un punct
în spaţiul răspunsurilor.

Un caz de testare trebuie să includă totdeauna ieşirea aşteptată


(expected output).
3. Test coverage criterion
Test coverage criterion e o regulă despre cum să selectăm cazuri de
testare şi când să ne oprim. Abordarea standard o constituie folosirea
relaţiei subsumes.

3.1 Subsumes (includeri)


Un criteriu de testare A subsumează criteriul de acoperire a testării B
dacă orice test care satisface criteriul A satisface de asemenea criteriul
B. Asta înseamnă că criteriul de acoperire a testării A include într-un fel
criteriul B.
Exemplu. Dacă un criteriu de acoperire a testării necesită ca fiecare
instrucţiune să fie executată şi alt criteriu de acoperire a testării
necesită ca fiecare instrucţiune să fie executată plus alte teste
adiţionale, atunci al doilea criteriu subsumează primul criteriu.
Obs. O mulţime bine aleasă de cazuri de testare ce satisfac un criteriu
“mai slab” poate fi mult mai bun decât o mulţime aleasă mai rău care să
satisfacă un criteriu “mai puternic”.
3.2 Testare funcţională (functional testing)

Unul din primii paşi este generarea unui caz de testare pentru fiecare
tip distinct de ieşire a programului. De exemplu, fiecare mesaj de
eroare trebuie generat. Apoi fiecare caz special ar trebui să aibă un caz
de test. Situaţiile ce ne pot induce în eroare (tricky situations) ar trebuie
testate. Greşelile comune ar trebui testate.

Exemplu. Unul dintre exemplele clasice este următorul: pentru trei


numere date la intrare, verificaţi dacă aceste numere pot reprezenta
laturile unui triunghi şi în caz afirmativ precizaţi natura triunghiului.

Soluţie. Împărţim spaţiul domeniu în 3 subdomenii, unul pentru fiecare


tip de triunghi: oarecare (scalen), isoscel (2 laturi egale) şi echilateral
(toate laturile egale). Identificăm două situaţii de eroare: un
subdomeniu cu intrări greşite şi un subdomeniu în care laturile nu pot
forma un triunghi. Fiecare caz de testare trebuie să specifice valoarea
output-ului.
Subdomeniu Caz de test

Oarecare:
Mărimi crescătoare (3,4,5 – oarecare)

Mărimi descrescătoare (5,4,3 – oarecare)


Cea mai mare a doua (4,5,3 – oarecare)

Isoscel:
a=b şi c mai mare (5,5,8 – isoscel)
a=c şi b mai mare (5,8,5 – isoscel)
b=c şi a mai mare (8,5,5 – isoscel)
a=b şi c mai mică (8,8,5 – isoscel)
a=c şi b mai mică (8,5,8 – isoscel)
b=c şi a mai mică (5,8,8 – isoscel)
Echilateral:
a=b=c (5,5,5 – echilateral)

Nu e triunghi:
a cea mai mare (6,4,2 – nu e triunghi)
b cea mai mare (4,6,2 – nu e triunghi)
c cea mai mare (1,2,3 – nu e triunghi)

Intrări greşite:
1 greşită (-1,2,4 – date greşite)
2 greşite (3,-2,-5 – date greşite)
3 greşite (0,0,0 – date greşite)

Obs. Lista subdomeniilor poate fi extinsă. Un caz de testare în fiecare


subdomeniu e soluţia minimală, dar acceptabilă.
3.3 Matrici de testare
O metodă de formalizare a identificării subdomeniilor este construirea
unei matrici folosind condiţiile pe care le identificăm din specificaţie şi
apoi să identificăm toate combinaţiile acestor condiţii ca fiind adevărate
sau false. Se vor folosi toate combinaţiile valide de T şi F. Dacă sunt 3
condiţii, vor fi 23=8 subdomenii (coloane). Liniile vor fi folosite pentru
valorile lui a, b şi c şi pentru ieşirile prognozate (expected output)
pentru fiecare subdomeniu.

Exemplu. Condiţiile din problema triunghiului pot fi : (1) a=b sau a=c
sau b=c, (2) a=b şi b=c, (3) a<b+c şi b<a+c şi c<a+b, (4) a>0 şi b>0 şi
c>0. Coloanele matricii vor reprezenta un subdomeniu. Pentru fiecare
subdomeniu, vom plasa un T în fiecare rând în care condiţia e
adevărată şi F când condiţia e falsă.
3.4 Testare structurală
Testarea structurală se bazează pe structura codului. Cel mai simplu
criteriu este every statement coverage, cunoscut drept C0 coverage.

3.4.1 C0 coverage
Acest criteriu presuppune că fiecare instrucţiune a codului ar trebui
executată se un caz de testare. Abordarea normală pentru obţinerea
C0 coverage este selectarea cazurilor de testare până când un
instrument de acoperire (coverage tool) indică faptul că toate
instrucţiunile din cod au fost executate.

Exemplu. Următorul pseudocod implementează problema triunghiului.


Matricea arată ce linii sunt executate în fiecare caz de test. Primele trei
instrucţiuni (A, B şi C) pot fi considerate părţi ale aceluiaşi nod.
3.4.2 Testarea C1-Every-Branch
Pentru modelarea programului cu triunghiul folosind un control flow
graph, acest criteriu necesită acoperirea fiecărui arc din digramă.
3.4.3 Testarea Every-Path

O cale (path) e o secvenţă unică a nodurilor programului care sunt


executate de un caz de testare. În matricea de testare (exemplul de
mai sus), erau 8 subdomenii. Fiecare dintre ele se întâmplă să fie o
cale. În acel exemplu, există 16 combinaţii diferite de T şi F. Totuşi, 8
dintre aceste combinaţii sunt căi nerealizabile (infeasible paths), adică
nu există combinaţii de T şi F pentru deciziile din program. Poate fi
extrem de dificil să determinăm dacă calea e nerealizabilă, precum şi
să găsim un caz de testare care execută acea cale.
Multe programe cu bucle vor avea un număr infinit de căi. În general,
testarea every-path nu e rezonabilă.
3.4.4 Multiple-Condition Coverage

Acest criteriu de testare necesită ca fiecare condiţie de relaţie primitivă


(primitive relation condition) să fie evaluată true şi false. În plus, trebuie
încercate toate combinaţiile de T/F pentru relaţiile primitive într-o
condiţie. E de notat că evaluarea lazy a unei expresii (un compilator e
lazy dacă, de exemplu, într-o expresie cu or prima relaţie e true, a doua
nu mai e testată) va elimina anumite combinaţii. De exemplu, într-un
and dintre două relaţii primitive, a doua nu va mai fi evaluată dacă
prima e falsă.

Exemplu. În pseudocodul din exemplul de la C0, sunt mai multe


condiţii multiple. Primitivele care nu se execută din cauza evaluării lazy
sunt marcate mai jos cu un “X”.
3.4.5 Subdomain testing (testarea de subdomeniu)
Se bazează pe idee partiţionării domeniul de intrare (input domain) în
subdomenii ce sunt mutual excluse şi impunerea unui număr de cazuri
de testare egal din fiecare subdomeniu. O idee similară se întâlnea în
cazul matricii de testare. În acest caz însă nu se restricţionează modul
în care sunt selectate domeniile.

Every-statement coverage şi every-branch coverage nu sunt


subdomain tests. Nu sunt subdomenii mutual excluse în ceea ce
priveşte executarea diferitelor instrucţiuni sau ramuri. Every-path
coverage este un subdomain coverage.

Exemplu. Pentru problema triunghiului, putem începe cu un


subdomeniu pentru fiecare ieşire. Acestea se pot subdiviza ulterior în
noi subdomenii, în funcţie de faptul dacă cel mai mare sau elementul
greşit introdus este în prima poziţie, a doua poziţie sau a treia poziţie.
3.4.6 C1 subsumează C0
Exemplu. Pentru problema triunghiului, am selectat cazurile de testtare
bune pentru a obţine C0 coverage. Cazurile erau:
(3,4,5 – oarecare),
(3,5,3 – isoscel),
(0,1,0 – intrări greşite),
(4,4,4 – echilateral)
Aceste teste acopereau 4 din 5 ieşiri.

Putem obţine C1 coverage cu două cazuri de testare:


(3,4,5 – oarecare) şi
(0,0,0 – intrări greşite).

Testul nu este probabil la fel de bun ca primul. Dar obţinem astfel atât
C1 coverage, cât şi C0 coverage.
4. Data flow testing
Este testarea bazată pe fluxul datelor (data flow) într-un program.
Datele curg din locul unde sunt definite până în locul unde sunt folosite.

O definiţie de date (sau def.) este atunci când o valoare e asignată


unei variabile.

Computation use (sau c-use) este atunci când o variabilă apare în


membrul drept al unei instrucţiuni de atribuire. c-use se spune că apare
într-o instrucţiune de atribuire.

Predicate use (sau p-use) este atunci variabila este utilizată în


condiţia unei instrucţiuni de decizie. p-use e asignată ambelor ramuri
ale instrucţiunii de decizie.

Definition free path (sau def-free) e o cale de la definiţia unei


variabile la folosirea acelei variabile care nu include altă definiţie a
variabilei.
Exemplu. Pentru problema triunghiului, reprezentăm control flow
graph.
Sunt multe criterii de testare a fluxului datelor.
Criteriile de bază includ dcu, care necesită o def-free de la fiecare
definiţie până la c-use; dpu, care necesită o def-free de la fiecare
definiţie până la p-use; du, care necesită o def-free de la fiecare
definiţie la orice folosire posibilă. Cele mai extinse criterii sunt all-du-
paths, care necesită toate def-free paths de la fiecare definiţie la
fiecare folosire posibilă.
Exemplu. Data flow testing pentru problema triunghiului.
dcu – singura c-use este pentru variabila din nodul k (instrucţiunea de
ieşire)
de la def type în nodul abc la nodul k calea abc,e,g,i,k
de la def type în nodul d la nodul k calea d,e,g,i,k
de la def type în nodul f la nodul k calea f,g,i,k
de la def type în nodul h la nodul k calea h,i,k
de la def type în nodul j la nodul k calea j,k
Exemplu (continuare)
dpu – singura p-use este pentru variabilele a,b,c şi singura def este
nodul abc
de la nodul abc la arcul abc-d
de la nodul abc la arcul abc-e
de la nodul abc la arcul e-f
de la nodul abc la arcul e-g
de la nodul abc la arcul g-h
de la nodul abc la arcul g-i
de la nodul abc la arcul i-j
de la nodul abc la arcul i-k

du – toate defs la toate folosirile


toate cazurile de testare ale dcu şi dpu combinate.

all-du-paths – toate def-free paths de la toate defs la toate folosirile.


toate cazurile de testare ale dcu şi dpu combinate.
5. Testarea aleatoare (random testing)
Se realizează prin selectarea aleatoare a cazurilor de testare. Are
avantajul că este rapidă. În plus, inferenţa statistică e mai uşoară când
testele sunt selectate aleator.

Exemplu. Pentru problema triunghiului, putem folosi un generator de


numere aleatoare şi să grupăm fiecare mulţime de trei numere ca o
mulţime de testare. Va trebui să determinăm în plus expected output. O
problemă ar putea fi faptul că probabilitatea să generăm un caz de
testare a echilateralităţii e foarte mică.

5.1 Profilul operaţional (operational profile)


Testarea în mediul de dezvoltare (development environment) e adesea
diferită de executarea în mediul operaţional (operational environment).
O cale de a le face pe acestea similare ar fi să avem o specificare a
tipurilor şi probabilităţile ca aceste tipuri să se întâlnească în operaţiile
normale. Această specificare se numeşte operational profile.
Prin desenarea cazurilor de testare ale profilului operaţional, cel care
face testul va avea mai multă încredere că acea comportare a
programului în timpul testării e mai predictivă despre cum se va
comporta în timpul funcţionării.

Exemplu. Un posibil profil operaţional pentru problema triunghiului:


Pentru aplicarea testării aleatoare, se poate genera un număr pentru
selectarea categoriei după probabilităţi şi apoi generarea unor numere
suficiente pentru a crea cazul de testare. Dacă cumva categoria
selectată a fost cazul echilateral, se va folosi acelaşi număr pentru
toate cele trei intrări. Un isoscel drept va necesita un număr aleator
pentru lungimea a două laturi şi apoi se poate calcula cealaltă latură.

5.2 Inferenţă statistică la testare


Dacă testarea aleatoare a fost făcută prin selectarea aleatorie a
cazurilor de testare dintr-un profil operaţional, atunci comportarea
software-ului în timpul testării ar trebui să fie aceeaşi cu comportarea
sa în mediul operaţional.

Exemplu. Dacă selectăm 1000 cazuri de testare aleator, folosind


profilul operaţional şi găsind 3 erori, putem prezice că software-ul va
avea o rată a erorilor mai mică de 3 defecţiuni (failures) la 1000 de
execuţii în mediul operaţional.
5. Boundary testing (testarea de frontieră)

De multe ori erorile apar la frontierele dintre domenii. În cod,


instrucţiunile condiţionale determină frontierele domeniilor. Dacă avem
o condiţie x<=1, atunci frontiera x=1 este în domeniul true. În termeni
de boundary testing, spunem că on tests sunt în domeniul true şi off
tests sunt valori ale lui x mai mari decât 1 şi sunt în domeniul fals. Dacă
o condiţie e scrisă x<1 în loc de x<=1, aunci frontiera x=1 este acum în
domeniul fals.

Boundary testing e făcută cu scopul de a ne asigura că frontiera


adevărată, reală (actual) dintre domenii e apropiată pe cât se poate de
frontiera specificată. De aceea, cazurile de testare sunt selectate pe
frontieră şi în afara frontierei, cât mai apropiat cu putinţă de frontieră.
Testul de frontiera standard constă în efectuarea a două on tests cât
mai departe posibil pe frontieră şi un off test aproape de mijlocul
frontierei.
Figura de mai jos arată o frontieră simplă. Săgeata indică faptul că on
tests ale frontierei sunt în subdomeniul de sub frontieră. Cele două on
tests sunt la capătul frontierei şi off test-ul chiar deasupra jumătăţii.
Exemplu. În exemplul cu triunghiul, condiţiile primitive, a>=b+c or
b>=a+c or c>=a+b, determină o frontieră. Deoarece depinde de trei
variabile, frontiera e un plan în spaţiul 3D. On testele ar trebui să fie 2
(sau mai multe) teste separate care au egalitate (de exemplu 8,1,7 şi
8,7,1). Acestea sunt amândouă adevărate. Off testul va fi în domeniul
false şi va fi aproape de mijloc (de exemplu 7.9,4,4).

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