Documente Academic
Documente Profesional
Documente Cultură
Testare empirică
Lansare
aplicatie
DA executie cu NU
Se alege alt succes
caz
Analiza
Rezultate NU lipsuri
complete
DA Stabilire secvente
DA neadecvate
NU
Se fac
Incheiere corectiile
proces
Pentru a uşura detectarea cauzelor care genereazǎ diferenţe între rezulatele
programului şi rezultatele existente în specificaţii, programatorii dezvoltǎ secvenţe care oferǎ
informaţii suplimentare prin:
- afişarea de rezultate intermediare
- afişarea urmei programului prin specificarea cu mesaje a secvenţelor executate
(etichete ale instrucţiunilor)
În procedura urmǎtoare, se contorizeazǎ elementele pozitive, elementele negative şi
elementele nule dintr-o matrice, evidenţierea urmei programului presupune:
void contorizare(int a[][NCOL], int n, int m, int s[])
{
int i, j;
s[0] = s[1] = s[2] = 0;
printf(”s[0] = s[1] = s[2] = 0\n”);
//s[0] numerǎ elementele pozitive din matrice;
//s[1] numǎrǎ elementele negative şi
//s[2] numǎrǎ elementele nule
for(i = 0; i < n; i++){
printf(”for (i = %d; %d < %d”, i, i, n);
for( j = 0; j < m; j++){
printf(”for (j = %d; %d < %d)\n”, j, j, m);
if (a[i][j] > 0){
printf(”a[%d][%d]>0\n”, i, j);
s[0] ++;
}
if (a[i][j] < 0){
printf(”a[%d][%d]<0\n”, i, j);
s[1] ++;
}
if (a[i][j] == 0){
printf(”a[%d][%d]=0\n”, i, j);
s[2] ++;
}
}
}
}
Pentru matricea a cu 3 linii si 3 coloane data de:
a[0][0] = 1; a[0][1] = 2; a[0][2] = -3;
a[1][0] = -4; a[1][1] = 0; a[1][2] = 6;
a[2][0] = 0; a[2][1] = 8; a[2][2] = -9;
se afişeazǎ:
s[0] = s[1] = s[2] = 0
for (i = 0; 0 < 3)
for (j = 0; 0 < 3)
a[0][0]>0
for (j = 1; 1 < 3)
a[0][1]>0
for (j = 2; 2 < 3)
a[0][2]<0
for (i = 1; 1 < 3)
for (j = 0; 0 < 3)
a[1][0]<0
for (j = 1; 1 < 3)
a[1][1]=0
for (j = 2; 2 < 3)
a[1][2]>0
for (i = 2; 2 < 3)
for (j = 0; 0 < 3)
a[2][0]=0
for (j = 1; 1 < 3)
a[2][1]>0
for (j = 2; 2 < 3)
a[2][2]<0
Afişarea de rezultate intermediare pentru procedura de mai sus presupune:
void contorizare(int a[][NCOL], int n, int m, int s[])
{
int i, j;
s[0] = s[1] = s[2] = 0;
printf(”s[0] = s[1] = s[2] = 0\n”);
//s[0] numerǎ elementele pozitive din matrice;
//s[1] numǎrǎ elementele negative şi
//s[2] numǎrǎ elementele nule
for(i = 0; i < n; i++){
printf(”i = %d; n = %d\n”, i, n);
for( j = 0; j < m; j++){
printf(”j = %d; m = %d\n”, j, m);
if (a[i][j] > 0){
s[0] ++;
}
if (a[i][j] < 0){
s[1] ++;
}
if (a[i][j] == 0){
s[2] ++;
}
printf(”a[%d][%d]=%d \n”, i, j, a[i][j]);
printf(”s[0]=%d;s[1]=%d;s[2]=%d;\n”,
s[0], s[1], s[2]);
}
}
printf(”i=%d; j=%d; n=%d; m=%d\n”, i, j, n, m);
printf(”s[0]=%d;s[1]=%d;s[2]=%d;\n”, s[0], s[1], s[2]);
}
Pentru matricea a cu 3 linii si 3 coloane data de:
a[0][0] = 1; a[0][1] = 2; a[0][2] = -3;
a[1][0] = -4; a[1][1] = 0; a[1][2] = 6;
a[2][0] = 0; a[2][1] = 8; a[2][2] = -9;
se afişeazǎ:
s[0] = s[1] = s[2] = 0
i = 0; n = 3
j = 0; m = 3
a[0][0]=1
s[0]=1;s[1]=0;s[2]=0
j = 1; m = 3
a[0][1]=2
s[0]=2;s[1]=0;s[2]=0
j = 2; m = 3
a[0][2]=-3
s[0]=2;s[1]=1;s[2]=0
i = 1; n = 3
j = 0; m = 3
a[1][0]=-4
s[0]=2;s[1]=2;s[2]=0
j = 1; m = 3
a[1][1]=0
s[0]=2;s[1]=2;s[2]=1
j = 2; m = 3
a[1][2]=6
s[0]=3;s[1]=2;s[2]=1
i = 2; n = 3
j = 0; m = 3
a[2][0]=0
s[0]=3;s[1]=2;s[2]=2
j = 1; m = 3
a[2][1]=8
s[0]=4;s[1]=2;s[2]=2
j = 2; m = 3
a[2][2]=-9
s[0]=4;s[1]=3;s[2]=2
i = 3; j = 3; n = 3; m = 3
s[0]=4;s[1]=3;s[2]=2
Analizând aceste secvenţe rezultǎ cǎ execuţia este corectǎ şi completǎ.
Dacǎ şirul de valori ale indicelui de control i este întrerupt atunci se cautǎ cauzele ce
genereazǎ discontinuitatea.
Testare sistematică
max = x1
max < x2
max = x2
max < x3
max = x3
max < x4
max = x4
scrie (max)
Figura 1. Structura graf asociatǎ programului de aflare a maximului
- structura arborescentǎ asociatǎ programului de aflare a maximului este datǎ în
figura 2.
A. citeşte (x1,x2,x3,x4)
max = x1
max < x2
max = x2
max = x3 max = x3
Valori
Traseul Max
x1 x2 x3 x4
(A, B1) 9 8 7 0 9
(A, B2) 5 4 3 8 8
(A, B3) 9 1 10 -7 10
(A, B4) 7 6 9 12 12
(A, B5) 1 7 6 -3 7
(A, B6) 8 10 7 15 15
(A, B7) -1 0 6 4 6
(A, B8) 7 10 11 12 12
Seturile de date de test din tabelul 1 s-au ales astfel încât sǎ fie respectate situaţiile
urmǎtoare de stabilire a elementului maxim, tabelul 2:
Tabelul 2. Intrǎrile şi ieşirile programului de aflare a elemntului maxim
Cu cât programul este mai complex cu atât creşte numǎrul de variante în expresia
relaţionalǎ.
Existǎ programe care optimizeazǎ secvenţele relaţionale astfel încât tabelele de decizie
sǎ conducǎ la un numǎr minim de expresii ortogonale.
Testarea funcţionalǎ şi testarea structuralǎ
Down
Bottom
Nu toţi dintre testerii aplicaţiilor software citesc codul sursă, dar conceptul studierii
codului programului ca parte a acţiunii de testare este cu siguranţă acceptat în mare măsură.
Inspectarea codului şi examinarea superficială a programului (walkthrough) sunt două
metode principale ale testării umane şi fac parte din aşa numita testare staticǎ a aplicaţiilor.
Tehnicile testării umane sunt destul de eficace în găsirea erorilor – aşa că fiecare
proiect de programare trebuie să utilizeze una sau mai multe dintre aceste tehnici. Aceste
metode trebuie aplicate între timpul codării programului şi timpul începerii testelor bazate pe
computer. Ele contribuie substanţial la productivitatea şi fiabilitatea programului.
Inspecţie şi examinările superficiale sunt mult mai eficace, decât procesul citirii
programului înainte de testare de către programator, deoarece în aceste procese sunt implicate
şi alte persoane în afara autorului programului.
În general, aceste metode sunt eficiente în găsirea unui procent de 30% până la 70%
din erorile logice de proiectare şi de codificare din programe. Ele nu sunt eficiente în
detectarea erorilor de proiectare la nivel înalt cum sunt erorile descoperite în procesul de
analiză a cerinţelor.
Inspectarea codului sursă este o tehnică utilă pentru localizarea erorilor de proiectare
şi implementare. Multe erori sunt uşor descoperite dacă autorul va citi programul cu suficientă
atenţie.
Ideea din spatele inspecţiei codului este ca autorul sǎ discute pas cu pas programul cu
alţi ingineri software.
O echipă de inspectare a codului în mod normal este alcătuită din patru persoane
[FAGA76]:
P1. moderatorul - un programator competent care nu este implicat în proiect şi nu este
familiarizat cu detaliile programului; este asemănător unui inginer de control a
calităţii; responsabilităţile moderatorului includ:
- planificarea şi distribuirea materialelor pentru inspecţie;
- conducerea inspectării;
- înregistrarea tuturor erorilor găsite;
- să urmărească ca erorile să fie corectate ulterior;
P2. programatorul obiectului de test;
P3. programatorul responsabil cu proiectarea - dacă e diferit de programator;
P4. persoana responsabilă cu testarea.
Sarcina echipei de inspecţie este de a detecta şi nu de a corecta erorile. În timpul
sesiunii de inspecţie a codului, se petrec două activităţi:
A1. programatorul citeşte, declaraţie după declaraţie, logica programului; în timpul
expunerii, ceilalţi participanţi ridică întrebări şi urmăresc dacă există erori;
probabil că programatorul, mai mult decât ceilalţi membri ai echipei, găseşte cele
mai multe erori în timpul acestei relatări; cu alte cuvinte, simplul act de citire a
unui program în faţa unui public pare să fie o tehnică de detectare a erorilor
remarcabil de eficace;
A2. programul este analizat luând în considerare lista de erori comune în programare.
După inspectare, programatorul este deprins cu lista de erori găsite. Dacă au fost găsite
mai multe erori sau dacă oricare dintre erori cere o corecţie substanţială, moderatorul face
aranjamentele pentru o reinspectare a programului după ce erorile au fost corectate. Erorile
găsite sunt analizate, clasificate şi utilizate pentru perfecţionarea listei de erori ce va fi folosită
pentru a îmbunătăţii eficienţa inspecţiilor viitoare.
Acest proces de inspectare, de obicei, se concentrează pe descoperirea erorilor nu pe
corectarea lor.
Programatorul va începe munca de corectare a erorilor descoperite numai după
terminarea procesului de inspectare.
Marile programe trebuie examinate prin mai multe inspectări, fiecare inspecţie fiind
făcută pe una sau mai multe subrutine sau module.
Pentru ca procesul de inspectare să fie eficient, trebuie stabilită o atitudine
corespunzătoare. Dacă programatorul vede inspectarea ca pe un atac asupra sa şi adoptă o
atitudine defensivă, procesul va fi ineficient. Mai degrabă, programatorul trebuie să abordeze
procesul cu o atitudine pozitivă şi constructivă: obiectivul inspecţiei este de a găsi erorile în
program, îmbunătăţindu-se astfel calitatea muncii.
Procesul de inspectare a codului reprezintă o cale de a identifica mai devreme cât mai
multe dintre secţiunile predispuse la erori ale unui program, ajutând la concentrarea cât mai
mare a atenţiei pe aceste secţiuni în timpul procesului de testare bazat pe calculator.
Lista de erori urmărite în inspectare este în mare măsură independentă de limbaj. Se
completeazǎ această listă cu erori specifice limbajului şi cu erori detectate după procesul de
inspectare.
Erori de referire a datelor se referǎ dacǎ:
- o variabilă referinţă are o valoare care este nesetată sau neiniţializată; probabil
aceasta este cea mai frecventă eroare de programare; ea apare într-o mare varietate
de circumstanţe; pentru fiecare referire la un articol de date variabilă, element al
unui vector sau câmp într-o structură se încearcă să se "dovedeascǎ" neprotocolar
că articolul are o valoare la acel punct;
- pentru toate referiţele unui vector, este fiecare valoare a indicilor în interiorul
limitei definite;
- pentru toate referinţele unui vector, fiecare indice are o valoare întreagă; aceasta nu
este neapărat o eroare în toate limbajele, dar este o practică periculoasă;
- pentru toate referirile prin pointer sau variabile referinţă, este memoria referită
alocată; aceasta este cunoscută ca problema “referirii izolate”; apare în situaţiile în
care timpul de viaţă al pointerilor este mai mare decât timpul de viaţă a memoriei
referite;
- atunci când o suprafaţă de memorie are nume alias cu atribute diferite, valoarea
dată în această suprafaţă are atributele corecte când este referită prin unul din aceste
nume; un program FORTRAN conţine o variabilă reală A şi o variabilă întreagă B;
ambele variabile au construite aliasuri pentru aceeaşi zonă de memorie prin
utilizarea instrucţiunii EQUIVALENCE; dacă programul memorează o valoare în
A şi apoi referă variabila B, o eroare este probabil să apară deoarece calculatorul va
utiliza o reprezentare „floating - point” în zona de memorie ca un întreg;
- valoarea unei variabile are un tip sau atribut diferit de ceea ce aşteaptă
compilatorul; această situaţie apare când un program citeşte o înregistrare în
memorie şi o referă prin utilizarea unei structuri, dar reprezentarea fizică a
înregistrării este diferită de definiţia structurii;
- există probleme de adresare explicită sau implicită dacă, pe maşina utilizată,
unităţile de memorie alocate sunt mai mici decât unităţile de memorie adresate;
- sunt utilizate variabile pointer sau referinţă, locaţia de memorie referită are
atributele aşteptate de compilator; un pointer C++ stabilit pe o structură de date este
asignat cu adresa unei structuri de date diferite;
- o structură de date este referită în mai multe proceduri sau subrutine, este structura
definită identic în fiecare procedură;
- pentru limbajele orientate-obiect, sunt toate cerinţele de moştenire întâlnite în clasa
implementată.
Erori de declarare a datelor se referǎ dacǎ:
- au fost toate variabilele declarate explicit; o astfel de absenţă nu este neapărat o
eroare, dar este o sursă comună de necazur; dacă o subrutină de program primeşte
ca parametru un vector, şi nu reuşeşte să definească parametru ca un vector, o
referinţă către vector este interpretată ca un apel de funcţie, conducând la încercarea
maşinii să execute vectorul ca pe un program;
- toate atributele variabilelor nu sunt stabilite explicit în declaraţie, sunt valorile
default ale acestora bine înţelese;
- atunci când o variabilă este iniţializată într-o instrucţiune declarativă, este ea
iniţializată corect; în multe limbaje, iniţializarea vectorilor şi şirurilor este oarecum
complicată şi, deci, predispusă erorilor;
- are fiecare variabilă asignată lungimea şi tipul de dată corect;
- este iniţializarea unei variabile compatibilă cu tipul său de memorie; dacă o
variabilă într-o subrutină din FORTRAN trebuie să fie reiniţializată de fiecare dată
când subrutina este apelată, ea trebuie iniţializată cu o declaraţie de asignare mai
degrabă decât cu o declaraţie DATA;
- există variabile cu nume similare, volt sau volts; aceasta nu este neapărat o eroare,
dar trebuie văzut ca o avertizare pentru că numele sunt confundate undeva în
interiorul programului.
Erori de calcul se referǎ dacǎ:
- există calcule cu variabile ce au tipuri de date nepotrivite;
- există operaţii de calcul mixte; este adunată o variabilă reală cu o variabilă de tip
întreg; astfel de operaţii nu sunt neapărat erori dar ele trebuie cercetate cu atenţie
pentru a ne asigura că regulile de conversie ale limbajului sunt bine înţelese;
- există operaţii de calcul ce utilizează variabile cu acelaşi tip de date dar lungimi
diferite;
- este tipul de date a unei variabile într-o atribuire mai mic decât tipul de dată sau
rezultatul expresiei din partea dreaptă;
- este posibilă o depăşire de limită superioară sau inferioară în timpul calculării unei
expresii; aceasta înseamnă că rezultatul final pare a avea o valoare validă, dar un
rezultat intermediar este prea mare sau prea mic pentru tipurile de date ale
limbajului;
- este posibil ca divizorul unei operaţii de împărţire să fie zero;
- este posibil ca valoarea unei variabile să depăşească sensul domeniului; declaraţia
de atribuire a unei variabile numită “probabilitate” s-ar putea verifica pentru a se
asigura că valoarea asignată va fi întotdeauna pozitivă şi mai mare ca 1.0;
- pentru expresiile ce conţin mai mult de un operator, este corectă presupunerea
ordinii de evaluare şi precedenţă a operatorilor.
Erori de comparaţie se referǎ dacǎ:
- există comparaţii între variabile ce au tipuri de date diferite, cum sunt comparaţiile
dintre un caracter dintr-un şir cu o adresă, dată sau număr;
- există comparaţii între variabile de lungimi diferite; dacă există, trebuie să ne
asigurăm că regulile de conversie sunt foarte bine înţelese;
- sunt folosiţi corect operatorii de comparare; programatorii în mod frecvent
confundă astfel de relaţii ca: cel mai mare, cel mai mic, mai mare decât, nu este
mai mic decât, mai mic decât sau egal;
- starea fiecărei expresii logice este cea presupusă; programatorii fac adesea greşeli
când scriu expresii logice ce conţin: şi, sau sau not;
- pentru expresiile ce conţin mai mult de un operator boolean, este corectă
presupunerea despre ordinea de evaluare şi precedenţă a operatorilor;
- calea în care compilatorul evaluează expresiile logice afectează programul;
declaraţia if((x==0 && (x/y)>z) este acceptabilă pentru compilatoarele care
termină testul de îndată ce o parte a operatorului şi este falsă, dar cauzeazǎ o eroare
de împărţire la zero cu alte compilatoare.
Erori de control a fluxului se referǎ dacǎ:
- fiecare buclă se va termina în cele din urmă;
- programul, modulul sau subrutina se va termina;
- este posibil ca, datorită unei condiţii pe intrare, o buclă să nu se execute niciodată;
- pentru o buclă controlată prin iteraţie cât şi printr-o condiţie - o buclă de căutare,
care sunt consecinţele ieşirii din buclă prin epuizare (fall-through); adică ce se va
întâmpla în următorul pseudo-cod dacă NOTFOUND nu devine niciodată fals:
DO i = 1 to TABLESIZE WHILE (NOTFOUND)
- limbajul conţine un concept de declaraţii de grupuri sau blocuri de cod (do-while
sau {…}), există un while explicit pentru fiecare grup şi există un do
corespunzător; sau există acolada închisă pentru fiecare acoladă deschisă; marea
majoritate a compilatoarelor din ziua de azi depistează astfel de erori automat;
- există decizii incomplete; adică, dacă valorile unui parametru de intrare sunt 1, 2 şi
3, presupunerea logică că trebuie să fie 3 dacă nu e 1 sau 2 este validă.
Erori de interfaţă se referǎ dacǎ:
- numărul de parametrii recepţionaţi de un modul este egal cu numărul de argumente
trimise la apelarea modulului; parametrii sunt în ordinea corectă;
- atributele - tipul de dată sau dimensiunea fiecărui parametru corespund atributelor
argumentului corespunzător;
- unităţile de sistem pentru fiecare parametru corespund unităţilor de sistem ale
argumentului corespunzător; parametru este exprimat în grade dar argumentul este
exprimat în radiani;
- numărul de argumente transmise de un modul către un alt modul este egal cu
numărul de parametrii aşteptaţi;
- atributele fiecărui argument transmis către alt modul se potrivesc cu atributele
corespunzătoare parametrului din acel modul;
- unităţile de sistem ale fiecărui argument transmise unui alt modul se potrivesc cu
unităţile de sistem ale parametrului corespunzător din acel modul;
- există subrutine care modifică parametru de intrare deşi se doreşte a fi numai o
valoare de intrare;
- sunt prezente variabile globale, ele au aceeaşi definiţie şi atribute în toate modulele
care le referă;
- sunt constantele trecute ca argumente.
Erori de intrare/ieşire se referǎ dacǎ:
- fişierele sunt declarate explicit, sunt atributele lor corecte;
- atributele unei declaraţii OPEN a unui fişier sunt corecte;
- specificaţiile de format sunt în armonie cu informaţiile din declaraţiile de I/O;
- există suficientă memorie disponibilă pentru a păstra fişierul pe care programul îl
va citii;
- au fost toate fişierele deschise înainte de a fi utilizate;
- au fost toate fişierele închise după utilizare;
- sunt condiţiile de sfârşit de fişier detectate şi tratate corect;
- sunt erorile de I/O tratate corect.