15
1 TESTAREA TESTAREA TESTAREA TESTAREA SISTEMELOR SOFTWARE SISTEMELOR SOFTWARE SISTEMELOR SOFTWARE SISTEMELOR SOFTWARE Testarea software determină dacă un sistem software este gata de livrare şi estimează nivelul de performanŃă al acestuia. Testarea furnizează o bază pentru interacŃiunea cu persoanele implicate în proiect. Creşterea complexităŃii sistemelor software a dus la o creştere a bugetului alocat acestei faze din procesul de dezvoltare al unui proiect (între 30 şi 50%). O mare parte a efortului necesar realizării sistemelor software este alocată dezvoltării modelelor de testare şi a aplicaŃiilor de testare automată. Testarea este procesul execuŃiei programului cu scopul de a pune în evidenŃă erorile. Detectarea erorilor este scopul principal al testării. În acelaşi timp, prezintă interes atât dezvoltarea unor seturi de date de test adecvate care să conducă la activarea erorilor precum şi modalităŃile de alocare a timpului necesar testării, în special în sistemele de mare complexitate. În mod obişnuit, spunem că un sistem software eşuează atunci când nu îndeplineşte cerinŃele impuse. FuncŃionarea defectuoasă poate fi rezultatul unuia dintre următoarele motivele: SpecificaŃiile sunt greşite sau unele cerinŃe ale clienŃilor nu sunt specificate; SpecificaŃiile pot conŃine cerinŃe care nu pot fi implementate cu softul disponibil; Proiectarea sistemului poate fi greşită. Implementarea codului are defecte; unii algoritmi sunt greşit sau incomplet implementaŃi. ExperienŃa acumulată de-a lungul timpului în domeniul testării software a dus la elaborarea unor politici de testare. Spre exemplu, Myers (1976) a propus următoarele reguli de bază pentru realizarea testării sistemelor software: Se determină momentul în care se opreşte testarea; Responsabilitatea testării programului revine unui tester, nu celui ce realizat programul; Se descriu rezultatele aşteptate pentru fiecare caz de test; Se scriu cazuri de test pentru condiŃii de intrare valide şi nevalide; Se verifică rezultatele fiecărui test. Testarea se atribuie celor mai creative persoane din echipă Pentru proiectele complexe, specificaŃiile de test pentru sistem şi pentru acceptarea acestuia nu trebuie scrise de către analişti, proiectanŃi şi programatori care au lucrat la proiectul respectiv (pentru sistemele mici şi medii e acceptabil ca aceste specificaŃii să fie scrise de către cei ce dezvoltă sistemul) ci de către utilizatorii sistemului. Testarea software cuprinde o multitudine de strategii de testare. În general, metodele de testare sunt specializate, în sensul că cele mai multe proiecte creează propriile metode de testare depinzând de produsul respectiv. Metodele de testare dinamică presupun executarea programului folosind aşa numitele date de test. Datele de test se construiesc conform cerinŃelor funcŃionale specificate iar rezultatele furnizate de program se compară cu cele prezentate în specificaŃii. Metodele de testare statică cuprind verificarea programului, analiza anomaliilor, inspecŃia codului. Verificarea programului necesită specificarea precondiŃiilor la intrare şi a postcondiŃiilor la ieşire. Analiza anomaliilor caută eventuale comportări anormale ale programului (spre exemplu, porŃiuni de cod care nu sunt executate niciodată). Scopul testării statice este de a analiza sistemul software şi de a deduce operaŃiile sale curente ca o consecinŃă logică a deciziilor de proiectare. Această modalitate de testare nu necesită execuŃia programului. 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.

C12 Testarea sSistemelor Software

Embed Size (px)

Citation preview

Page 1: C12 Testarea sSistemelor Software

1

TESTAREA TESTAREA TESTAREA TESTAREA SISTEMELOR SOFTWARESISTEMELOR SOFTWARESISTEMELOR SOFTWARESISTEMELOR SOFTWARE

Testarea software determină dacă un sistem software este gata de livrare şi estimează nivelul de performanŃă al acestuia. Testarea furnizează o bază pentru interacŃiunea cu persoanele implicate în proiect. Creşterea complexităŃii sistemelor software a dus la o creştere a bugetului alocat acestei faze din procesul de dezvoltare al unui proiect (între 30 şi 50%). O mare parte a efortului necesar realizării sistemelor software este alocată dezvoltării modelelor de testare şi a aplicaŃiilor de testare automată. Testarea este procesul execuŃiei programului cu scopul de a pune în evidenŃă erorile. Detectarea erorilor este scopul principal al testării. În acelaşi timp, prezintă interes atât dezvoltarea unor seturi de date de test adecvate care să conducă la activarea erorilor precum şi modalităŃile de alocare a timpului necesar testării, în special în sistemele de mare complexitate. În mod obişnuit, spunem că un sistem software eşuează atunci când nu îndeplineşte cerinŃele impuse. FuncŃionarea defectuoasă poate fi rezultatul unuia dintre următoarele motivele:

• SpecificaŃiile sunt greşite sau unele cerinŃe ale clienŃilor nu sunt specificate; • SpecificaŃiile pot conŃine cerinŃe care nu pot fi implementate cu softul disponibil; • Proiectarea sistemului poate fi greşită. • Implementarea codului are defecte; unii algoritmi sunt greşit sau incomplet implementaŃi.

ExperienŃa acumulată de-a lungul timpului în domeniul testării software a dus la elaborarea unor politici de testare. Spre exemplu, Myers (1976) a propus următoarele reguli de bază pentru realizarea testării sistemelor software:

• Se determină momentul în care se opreşte testarea; • Responsabilitatea testării programului revine unui tester, nu celui ce realizat programul; • Se descriu rezultatele aşteptate pentru fiecare caz de test; • Se scriu cazuri de test pentru condiŃii de intrare valide şi nevalide; • Se verifică rezultatele fiecărui test. • Testarea se atribuie celor mai creative persoane din echipă

Pentru proiectele complexe, specificaŃiile de test pentru sistem şi pentru acceptarea acestuia nu trebuie scrise de către analişti, proiectanŃi şi programatori care au lucrat la proiectul respectiv (pentru sistemele mici şi medii e acceptabil ca aceste specificaŃii să fie scrise de către cei ce dezvoltă sistemul) ci de către utilizatorii sistemului.

Testarea software cuprinde o multitudine de strategii de testare. În general, metodele de testare sunt specializate, în sensul că cele mai multe proiecte creează propriile metode de testare depinzând de produsul respectiv.

Metodele de testare dinamică presupun executarea programului folosind aşa numitele date de test. Datele de test se construiesc conform cerinŃelor funcŃionale specificate iar rezultatele furnizate de program se compară cu cele prezentate în specificaŃii.

Metodele de testare statică cuprind verificarea programului, analiza anomaliilor, inspecŃia codului. Verificarea programului necesită specificarea precondiŃiilor la intrare şi a postcondiŃiilor la ieşire. Analiza anomaliilor caută eventuale comportări anormale ale programului (spre exemplu, porŃiuni de cod care nu sunt executate niciodată). Scopul testării statice este de a analiza sistemul software şi de a deduce operaŃiile sale curente ca o consecinŃă logică a deciziilor de proiectare. Această modalitate de testare nu necesită execuŃia programului.

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.

Page 2: C12 Testarea sSistemelor Software

2

• 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. În tabelul 1 se prezintă câteva metode de testare ce fac parte din cele două mari categorii prezentate mai sus, metode ce vor fi prezentate pe larg în secŃiunile ulterioare.

Tabelul 1 Clasificarea formelor de testare Testare funcŃională Testare structurală Dinamică Testare aleatoare

Testare pe domenii Graf cauză-efect

Testare computaŃională Testare pe domenii Testare căi Generare date Analiza schimbărilor

Statică Verificare specificaŃii Inspectare cod Verificare program ExecuŃie simbolică Analiză anomalii

În cazul testării sistemelor software există şi probleme ce nu Ńin de tehnică. Spre exemplu, se pot pune următoarele întrebări: Cine face testarea? Testarea poate fi realizată de un programator care a fost implicat în scrierea codului? Se apelează la un tester independent, se schimbă porŃiuni de cod între membrii aceleiaşi echipe sau se lasă testarea în seama utilizatorului final? Fiecare dintre alternativele propuse are argumente pro şi contra.

O altă problemă fundamentală este legată de durata activităŃilor de testare, când apar două puncte de vedere cel puŃin contradictorii care trebuie luate în considerare. Primul este al proiectanŃilor care fac tot posibilul pentru a realiza un produs fără defecte. Cel de-al doilea este al managerilor de proiect care iau în considerare constrângerile de timp impuse proiectului.

Înainte de a intra într-o prezentare mai detaliată a diferitelor variante de testare, este importantă precizarea paşilor principali care intervin în orice schemă de testare.

Etapele principale ale unei scheme de testare • SelectaŃi ce trebuie măsurat (cuantificat) de testul respectiv. Înainte de realizarea testului, trebuie identificate scopurile acestuia. Scopurile pot fi diferite (spre exemplu, testarea fiabilităŃii, testarea completitudinii cerinŃelor). • DecideŃi cum faceŃi testarea a ceea ce trebuie testat. După ce aŃi stabilit ce este de testat, trebuie să decideŃi cum realizaŃi testele relevante. • DezvoltaŃi cazurile de test. Pentru tipurile de testare deja acceptate, trebuie creată o colecŃie de cazuri de test (situaŃii de test) pentru antrenarea sistemului supus testării. • DeterminaŃi rezultatele aşteptate ale testului respectiv. • ExecutaŃi cazurile de test.

• ComparaŃi rezultatele obŃinute cu cele aşteptate.

2. Niveluri ale testării software

Testarea software se realizează la diferite nivele de-a lungul întregului ciclu de viaŃă al produsului. Testarea începe la nivel de componente software individuale. Se verifică funcŃionalitatea şi structura fiecărei componente, după care se face testarea la integrare a componentelor. Standardul IEEE de verificare şi validare software (IEEE Std. 1059-1993) identifică patru nivele de testare, după cum se poate observa în tabelul 2. CorespondenŃa între nivelele de testare şi etapele ciclului de viaŃă a sistemului este prezentată în figura 1.

Page 3: C12 Testarea sSistemelor Software

3

Tabel 2 Testare DefiniŃie Scop Componentă Se verifică implementarea elementelor

software (ex. FuncŃii, module). Logica programului este completă şi corectă. Componentele funcŃionează conform proiectării.

Integrare Componentele software şi hardware sunt combinate şi testate până la integrarea întregului sistem

Obiectivele proiectării sunt satisfăcute

Sistem Se testează sistemul integrat Proiectul software este o entitate completă în concordanŃă cu cerinŃele operaŃionale.

Acceptare Se verifică dacă rezultatele testelor satisfac criteriile de acceptare ale clienŃilor

Obiectivele clienŃilor sunt satisfăcute

Figura 1. Nivele de observabilitate a testării

3. ActivităŃi de test

În cadrul testării software se pot delimita următoarele activităŃi cheie: • Elaborarea planului de testare • Proiectarea testului • Stabilirea cazurilor de test • Determinarea procedurii de testare • Executarea testului • Realizarea raportului de testare Planul de testare trebuie să precizeze scopul, tipul abordării, resursele necesare şi un orar al

activităŃii de testare. Este necesară de asemenea identificarea surselor şi nivelelor de risc şi stabilirea persoanele ce realizează testarea. Planificarea testării poate începe din momentul în care cerinŃele sistemului sunt complete. Este dificilă determinarea momentului în care se opreşte testarea. Din acest motiv trebuie introduse criterii pentru a stabili dacă un test este complet sau nu.

Proiectarea testului rafinează abordarea propusă în planul de testare. În această etapă se identifică principalele caracteristici ce trebuie testate şi se definesc cazurile de test asociate. Este recomandat ca proiectarea testelor să se facă pentru o testare de regresiune (testele executate anterior să poată fi repetate la un punct ulterior în procesul de dezvoltare şi întreŃinere).

Cazurile şi procedurile de test se construiesc în faza de implementare. Se urmăreşte realizarea unei colecŃii de cazuri de test cât mai redusă care să poată duce la îndeplinirea scopurilor propuse. Cazurile de test bine realizate au o mare probabilitate de a detecta erorile. Procedura de testare identifică toŃi paşii necesari operării sistemului şi rulării cazurilor de test ce implementează proiectul de test obŃinut în etapa anterioară.

Executarea testului începe la nivel de componente şi continuă cu testarea la integrare, testarea sistemului şi testarea de acceptare.

Raportul de testare rezumă toate ieşirile testului şi subliniază discrepanŃele detectate. ActivităŃile de testare se distribuie de-a lungul întregului ciclu de viaŃă al produsului.

4. Tipuri de teste software

łinând cont de multitudinea metodelor de testare existente este avantajoasă luarea în

Page 4: C12 Testarea sSistemelor Software

4

considerare a testelor în funcŃie de modalitatea în care acestea devin accesibile proiectantului. Testele funcŃionale sunt utilizate pentru a rula codul cu intrări nominale pentru care valorile

aşteptate sunt disponibile. Pentru aceste intrări sunt cunoscute de asemenea condiŃiile la limită. Spre exemplu, pentru a testa funcŃional înmulŃirea matricelor se vor lua în considerare matrice al căror produs este dinainte cunoscut.

Testele de performanŃă ajută la determinarea unor performanŃe ale sistemului cum ar fi timpul de execuŃie al unor părŃi de cod şi timpul de răspuns (în cazul sistemelor încorporate). Scopul acestui tip de testare constă în identificarea punctelor slabe ale sistemului software, cuantificarea neajunsurilor în scopul unei viitoare îmbunătăŃiri.

Testele la stres sunt proiectate pentru a urmări comportarea sistemului atunci când acesta cedează. Acest tip de testare evaluează limitările sistemului software.

Testele structurale sunt folosite pentru a verifica logica internă a sistemului. Testele pe componente se efectuează asupra modulelor individuale, proceduri şi funcŃii. Testele la integrare sunt proiectate pentru a testa comportarea sistemului pe măsură ce se

adaugă modulele componente. Testarea interfeŃelor are ca obiectiv detectarea erorilor cauzate de interfeŃele dintre obiecte.

Pot apărea următoarele tipuri de erori: utilizare greşită a interfeŃei (parametri cu un alt tip sau într-o altă ordine decât sunt specificaŃi în interfaŃă), înŃelegerea greşită a interfeŃei (presupuneri greşite legate de ce ar trebui să facă o componentă), erori de timing (au loc în sistemele în timp real care folosesc memorie partajată sau transmitere de mesaje).

5. Testarea funcŃionala (black box)

După cum am precizat anterior, testarea de tip black box nu necesită cunoaşterea codului pentru realizarea unor teste semnificative. În continuare vom discuta despre câteva categorii reprezentative ale acestei metode de testare cum ar fi testarea derivată din sintaxă, testarea bazată pe tabele de decizie şi abordarea bazată pe grafuri cauză efect.

T5.1 Testarea derivată din sintaxă

Această clasă de teste funcŃionale se aplică sistemelor ale căror specificaŃii sunt descrise de o anumită gramatică. Această constă, spre exemplu, în compilatoare şi clasificatori sintactici. Deoarece specificarea formală a unor astfel de sisteme se exprimă prin reguli de producŃie, generarea cazurilor de test urmăreşte un ca fiecare regulă de producŃie să fie aplicată (testată) cel puŃin o dată.

Exemplu. Să considerăm o clasă de expresii aritmetice descrisă de următoarele reguli de producŃie:

<expresie>::=<expresie>+<termen>|<expresie>-<termen>|<termen> <termen>::=<termen>+<factor>|<termen>-<factor>|<factor> <factor>::=<identificator>|(<expresie>) <identificator>::=a|b|c|d|e|...|z

Un set de cazuri de test pentru testarea derivată din sintaxă conŃine expresii ce verifică regulile de mai sus. Un exemplu de expresie împreună cu regula corespunzătoare este dată în figura următoare.

<expresie>::=<expresie>+<termen>|

<expresie>-<termen>| <termen>

<termen>::=<termen>+<factor>| <termen>/<factor>| <factor>

<factor>::=<identificator>| (<expresie>) <identificator>::=a|b\c|d|e|...|z

Figura 2. Caz de test şi regulă de producŃie (subliniată)

Page 5: C12 Testarea sSistemelor Software

5

5.2 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”. Exemplele care se pretează la acest tip de testare sunt sistemele bazate pe reguli. O regulă este de forma:

If cond1 and cond2 and cond3 and ... condn then actiune

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

CondiŃii ... 1

CondiŃia i 1 ... 0

AcŃiuni ... 0

AcŃiunea j 1 ... 0

Figura 3. 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 4). 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ă. sunt următoarele:

Figura 4. Rezervor de lichid

Reguli:

• 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 senzorul 2 furnizează rezultate

eronate. Tabelul de decizie complet are 22 4= coloane (figura 5A). 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 5B.

Î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 5B poate fi astfel eliminată.

Page 6: C12 Testarea sSistemelor Software

6

În secŃiunea următoare vom prezenta metoda de testare bazată pe grafuri cauză efect care elimină neajunsul major al metodei bazate pe tabele de decizie, şi anume creşterea exponenŃială a dimensiunii tabelelor odată cu creşterea numărului de reguli.

S 1 0 0 1 1 CondiŃii S 1 0 1 1 CondiŃii S 2 0 1 0 1 S 2 0 0 1

Deschide valvă ieşire

0 0 0 1 Deschide valvă ieşire

0 0 1

Deschide valvă intrare

1 0 0 0 AcŃiuni Deschide valvă intrare

1 0 0 AcŃiuni

Trimite mesaj eroare

0 1 0 0 Trimite mesaj eroare

Figura 5A. Tabel de decizie complet Figura 5B. Tabel de decizie redus

5.3 Testarea funcŃională bazată pe grafuri cauză-efect

Principalul dezavantaj al metodei bazate pe tabele de decizii 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 C1: comanda este „creditare” C2: comanda este „debitare” C3: numărul de cont este valid C4: tranzacŃia este validă

Efecte E1: tipăreşte „comandă nevalidă” E2: tipăreşte „număr cont nevalid” E3: tipăreşte „sumă debit nevalidă” E4: cont debit E5: cont credit

Graful cauză-efect este prezentat în figura 6. 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 6. dacă spre exemplu suntem interesaŃi în determinarea cauzelor efectului E3 se urmăreşte porŃiunea de graf prezentată în figura 7.

Figura 6. Graf cauză-efect

Figura 7. Determinarea cauzelor efectului E3

Page 7: C12 Testarea sSistemelor Software

7

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 12 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 8). Dacă nu ignorăm aceste condiŃii, va rezulta un

tabel cu 42 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 8. 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 (Ghezzi et al., 1991):

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

6. CondiŃii de testare la limită

Testarea de tip white box, care necesită cunoaşterea codului, nu se poate face pentru cazurile care nu sunt vizibile în mod explicit, sau care nu sunt suficient reliefate. Să considerăm spre exemplu o instrucŃiune de tipul if (x>y) then S1 else S2. Această formă a unei instrucŃiuni condiŃionale este generică şi se întâlneşte în multe tipuri de probleme. Să considerăm spre exemplu doi senzori ale căror citiri (x şi y) sunt folosite pentru luarea unor decizii, notate S1 şi S2. CondiŃia x>y determină două clase de echivalenŃă: • E1 – clasa de echivalenŃă a valorilor lui x şi y pentru care x y>

• E2 – clasa de echivalenŃă a valorilor lui x şi y pentru care x y≤ Cele două clase de echivalenŃă sunt formate din perechi de valori citite (x,y) care determină

valoarea de adevăr a condiŃiei relaŃionale asociate. Criteriul de acoperire a ramurilor (care presupune testarea tuturor ramurilor din program) duce la selectarea a două combinaŃii de intrări: una

Page 8: C12 Testarea sSistemelor Software

8

provenind din E1 şi cealaltă din E2 (vezi figura 9). Se testează căile x y> şi x y< . Cazul x y= , care este parte a clasei de echivalenŃă E2, are o probabilitate nulă de a fi testat, deci nu va fi selectat niciodată pentru testare. Cu toate acestea, cazul la limită x y= prezintă interes şi din acest motiv, se poate prevedea o cale de realizare.

Figura 9. CondiŃia de testare la limită x = y

7. Testarea exhaustivă

Testarea exhaustivă face parte din metoda de testare black box. Cu toate că este impracticabilă, ea 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. Când ne referim la intrări trebuie să avem în vedere şi aspectele hardware ale realizării codului.

Exemplu. Se consideră ecuaŃia de gradul doi de forma 2ax 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 162 cazuri de test. Considerând toate cele trei intrări, vom avea în final 482 cazuri de test ce trebuie executate, ceea ce este nefezabil.

8. Testarea structurală

Testarea structurală presupune dezvoltarea de cazuri de test ce iau în considerare structura codului (logica internă). Există mai multe categorii de testarea 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

Page 9: C12 Testarea sSistemelor Software

9

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 4, y 10= − = , x 6, y 12= − = . Î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 n2 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 10.

Figura 10. Exemplu de schemă logică

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 12= =

Aceste două cazuri de test acoperă toate ramurile schemei logice (vezi figura 11), 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.

Figura 11. Testarea la nivel de ramură

Page 10: C12 Testarea sSistemelor Software

10

Testarea la nivel de cale evită situaŃia prezentată anterior. Se pot considera următoarele cazuri de test:

x 1, y 5= = ; x 2, y 15= = ; x 0, y 7= = ; x 0, y 13= = .

Figura 11. Testarea la nivel de cale

ObservaŃie. 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.

Î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 12. În cazul în care se unesc ramurile, blocurile de decizie sunt „stivuite” unele peste

altele (figura 12a). Unirea ramurilor poate duce la n2 căi posibile. Numărul maxim de căi dintr-un

graf este deci n2 . În cazul în care nu se face unirea ramurilor există n 1+ căi posibile (vezi figura 12b), deci:

n 1+ ≤ număr de căi ≤ n2 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)= .

Page 11: C12 Testarea sSistemelor Software

11

(a) ramuri unite

(b) ramuri neunite

Figura 12. Cazuri de acoperire a căilor

Î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 (figura 13). Enumerarea căilor va fi dată de sumele produselor limitelor grafului fără bucle.

Exemplu. Să considerăm graful din figura 14. Se porneşte cu frontierele care fac parte din toate căile posibile. Acestea sunt, evident, a şi h. Atunci:

FGC aFGC hα= ,

unde FGC este funcŃia de generare a căii iar α este funcŃia de generare a căii pentru sub-graful dintre B şi E. În continuare se construieşte funcŃia de generare a căii pentru α, FGCα:

Figura 13. Transformarea schemei logice în grafuri fără bucle

FGC de bFGCα β= + ,

unde semnul „+” se foloseşte pentru operaŃia „sau”. Pentru sub-graful cu nodurile C, B’, E’ şi E se obŃine:

FGC f cbfβ = + .

Revenind la expresia originală se obŃine:

Page 12: C12 Testarea sSistemelor Software

12

FGC aFGC h a(de bFGC )h a(de b(f cbf ))h adeh abfh abcbfhα β= = + = + + = + +

Figura 14. Conversia unui graf într-un graf echivalent fără bucle

Se poate observa că numărul de căi poate creşte foarte mult, mai ales pentru porŃiunile de

cod cu fluxuri de control semnificative. Acest fapt limitează aplicabilitatea acestei metode de testare. 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.

9. Testarea regresivă

Scopul acestei metode de testare este de crea posibilitatea repetării testelor în momentul în care apare o modificare a produsului software. Există două activităŃi principale ale testării regresive:

• Stabilirea unui test (sau a unei serii de teste) pentru reluare. Regula este să se meargă pe teste puternice (şi anume acele teste cu nivel mare de acoperire).

• Compararea ieşirilor noi cu cele vechi (de bază) pentru a fi siguri că nu există schimbări nedorite.

Pentru testarea regresivă efectivă, trebuie realizate prelucrări suplimentare ale seriilor de test.

Eficacitatea testării regresive se exprimă în termenii următoarelor condiŃii: (a) cât de grea este construirea şi menŃinerea seriilor de test şi (b) cât de fezabil este sistemul de testare regresivă.

10. Testarea software statică

Testarea statică, spre deosebire de cea dinamică, nu se concentrează asupra execuŃiei codului. Există două variante de tehnici de testare statică:

• tehnici informale care includ trecerile rapide prin cod şi inspectarea propriu zisă a codului;

• tehnici formale ce cuprind demonstraŃii de corectitudine şi execuŃia simbolică.

10.1 Tehnici informale

Tehnicile informale au fost introduse la sfârşitul anilor ’70 şi diferă prin faptul că, dacă inspectările softului sunt orientate pe reacŃie, trecerile prin cod se bazează pe interacŃiunea dintre testeri, membrii echipei proiectului şi alte persoane implicate în proiect.

Inspectările sunt activităŃi realizate de o echipă experŃi care verifică proiectul sau codul cu scopul de a identifica erorile. Au fost propuse în 1976 de Fagan şi au fost dezvoltate de IBM. O inspectare conŃine cinci paşi principali:

• Privirea de ansamblu asupra documentelor ce trebuie inspectate • Pregătirea. ParticipanŃii încearcă să înŃeleagă documentul în detaliu. Tipurile de erori şi

frecvenŃa acestora găsite în inspecŃiile recente sunt utile pentru ca atenŃia să se concentreze asupra ariilor predispuse în măsură mai mare la erori

Page 13: C12 Testarea sSistemelor Software

13

• Inspectarea. Pentru început, un participant parcurge codul împreună cu echipa de inspecŃie, asigurându-se că fiecare problemă este acoperită şi că fiecare ramură e parcursă cel puŃin o dată. Fiecare participant continuă cu propria listă de verificare. Scopul este de a găsi şi documenta erorile, nu de a le înlătura. Liderul echipei de inspecŃie (moderatorul) are ca sarcini pregătirea raportului scris şi asigurarea unei rezolvări potrivite

• Refacerea. Erorile şi problemele din raportul scris sunt rezolvate • Continuarea. Moderatorul se asigură că toate problemele ridicate au fost rezolvate. Toate

rezolvările trebuie verificate pentru a fi siguri că nu au fost introduse noi erori. În cazul în care mai mult de 5% din materialul inspectat a fost refăcut, echipa se reuneşte pentru o nouă inspectare.

Echipa responsabilă cu inspectarea este formată în general din 3-6 persoane. Spre exemplu, dacă se inspectează proiectul, echipa va conŃine un moderator, un proiectant, un dezvoltator şi un tester. Fiecare inspecŃie trebui să utilizeze o listă de verificare a defectelor potenŃiale (cum ar fi corespondenŃa între specificaŃii şi proiectare, între parametrii actuali şi cei formali ai interfeŃelor, compatibilitatea softului cu hardware-ul disponibil etc.). Rezultatele inspecŃiei sunt înregistrate funcŃie de nivelul de severitate şi tip. Pentru ca inspecŃia să aibă succes ea trebuie să aibă un caracter iterativ. În cazul inspectării codului activităŃile au scopul de a descoperi erorile obişnuite sau pe cele provenind din clase specifice cum ar fi:

• Variabile neiniŃializate; • Salturile în interiorul buclelor; • Bucle fără condiŃie de terminare; • Indexarea vectorilor în afara limitelor; • Nepotriviri între parametrii actuali şi cei formali. • Trecerea rapidă prin cod presupune organizarea unor întâlniri de lucru pentru analizarea

unui produs software, unui modul de cod, unui plan de testare etc. AcŃiunea este condusă de un persoană ce face o prezentare a produsului ce trebuie analizat. Erorile sunt înregistrate de un coordonator. Grupul de lucru se concentrează pe detecŃia erorilor, nu pe corecŃia lor. În general, o astfel de echipă este formată din următorii membri: un prezentator al problemelor ce trebuie revăzute, un coordonator al echipei de lucru, un secretar ce se ocupă cu pregătirea tuturor materialelor necesare, un reprezentant al persoanelor ce se ocupă cu întreŃinerea produsului, o persoană responsabilă cu îndeplinirea standardelor interne şi un reprezentant al clientului.

10.2 Tehnici formale

Tehnicile formale constau în demonstraŃii de corectitudine şi execuŃie simbolică.

DemonstraŃiile de corectitudine se bazează pe observaŃia că orice porŃiune de cod (program) este un obiect formal, în timp ce orice specificaŃie poate fi realizată printr-o metodă formală. Aceasta înseamnă că se pune accentul pe echivalenŃa dintre program şi specificaŃii. EchivalenŃa poate fi pusă în evidenŃă printr-o demonstraŃie matematică.

ExecuŃia simbolică utilizează simboluri în locul valorilor numerice, adică se bazează pe clase de date. Pentru a ilustra esenŃa acestei idei să considerăm următorul exemplu:

x = 7*y; if (x>a) then a = a+x-3 else y = sin(x/2); b = x+a*y;

În figura 15 literele mari cum ar fi X sau Y semnifică valori simbolice, acestea corespunzând variabilelor originale utilizate în cod). Să presupunem că la începutul execuŃiei simbolice, x X= şi a A= . Prima instrucŃiune duce la X 7*Y= . Celelalte variabile rămân neschimbate. Blocul de decizie poate fi activat pe oricare din cele două direcŃii (comparaŃia 7*Y A> poate fi adevărată sau falsă). Vom selecta unul din cele două fire de execuŃie ca un triplu de forma:

<valori variabile simbolice, cale de execuŃie, condiŃie>

Page 14: C12 Testarea sSistemelor Software

14

Cele două căi de execuŃie sunt asociate grafului de control al fluxului.

Figura 15 Exemplu de execuŃie simbolică

11. Testarea la integrare

Componentele majore rezultate din scrierea codului se integrează formând sistemul final. Stilul de testare ales depinde de strategia aleasă pentru proiectarea sistemului software. În

cazul strategiei de proiectare top-down (care presupune o serie de rafinări succesive) se utilizează module înlocuitoare sau substitute (stubs) care au rolul de a emula modulele ce nu au fost dezvoltate încă (vezi figura 16). În cazul strategiei de proiectare bottom-up sistemul se dezvoltă plecând de la module detaliate, implementând funcŃii din ce în ce mai complexe. Se utilizează modulele driver pentru reprezentarea modulelor de nivel mai înalt ale căror nume le poartă (vezi figura 17).

Figura 16. Strategia top-down de testare a sistemului

Figura 17. Strategia bottom-up de testare a sistemului

Plecând de la strategiile de proiectare se pot defini următoarele strategii de testare la integrare:

• Testarea bottom-up – pleacă de la module detaliate şi se extinde spre nivele mai înalte ale ierahiei; această testarea necesită drivere.

• Testarea top-down - porneşte de la modulul de pe cel mai înalt nivel şi necesită substitute.

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

ObservaŃie. Există situaŃii în care unele module nu sunt testate separat la testările bottom-up şi top-down.

Page 15: C12 Testarea sSistemelor Software

15

Figura 18. Ierarhie de module software

Exemplu. Pentru a ilustra aceste idei de testare, să considerăm o ierarhie simplă de module ca în figura 18.

În figura 19 sunt prezentate clasele de testare la integrare pentru exemplul anterior.

Testare bottom-up

Testare top-down

Testare big-bang

Testare în straturi Stratul de test este situat între

A şi (B, C, D) Figura 19. Exemple de testări la integrare