Inginerie Software Implementare, testare, verificare şi validare de programe



Yüklə 214,14 Kb.
səhifə3/3
tarix26.07.2018
ölçüsü214,14 Kb.
#58571
1   2   3

2.3) Testarea de performanță


Odată ce un sistem a fost complet integrat, este posibil să se testeze sistemul după proprietăți emergente precum performanța și fiabilitatea. Testele de performanță trebuie proiectate astfel încât să asigure faptul că sistemul poate procesa sarcina intenționată. De obicei, acest lucru implică planificarea unei serii de teste în care încărcarea este crescută treptat, până când performanța sistemului devine inacceptabilă. [2.4]

La fel ca și alte tipuri de testare, cea de performanță implică atât demonstrarea faptului că sistemul întrunește cerințele, cât și descoperirea problemelor și defectelor din sistem. Pentru a testa dacă sunt atinse cerințele de performanță, trebuie construit un profil operațional. Acesta constă într-o serie de teste care reflectă combinația reală de sarcini care vor fi tratate de sistem. Astfel, dacă 90% din tranzacțiile din sistem sunt de tip A, 5% de tip B și restul de tip C, D și E, profilul operațional trebuie construit astfel încât majoritatea testelor să fie de tip A. În caz contrar, nu se poate obține un test precis al performanței operaționale a sistemului. [2.3]

Această abordare nu este neapărat și cea mai bună pentru testarea de defecte. O abordare mai eficientă este proiectarea de teste în jurul limitelor sistemului, efectiv punând presiune pe sistem, de unde și denumirea de testare de stres, deoarece testele au cerințe dincolo de limitele de proiectare ale software-ului.

De exemplu, un sistem de procesare de tranzacții poate fi proiectat să proceseze până la 300 tranzacții / secundă. Un sistem de operare poate fi proiectat să susțină până la 1000 terminale separate. Testarea de stres continuă aceste teste dincolo de sarcina proiectată maximă a sistemului, până când acesta cedează. Acest tip de testare are două funcții:



  1. Testează comportamentul la cedare al sistemului. Pot apărea circumstanțe printr-o combinație neașteptată de evenimente, în care sarcina plasată pe sistem depășește încărcarea maximă anticipată. În aceste cazuri, este important ca prin cedarea sistemului să nu apară coruperea datelor sau pierderea neașteptată a serviciilor utilizatorilor. Testarea de stres verifică faptul că un sistem nu se va prăbuși sub sarcina sa, ci va eșua cu grație.

  2. Pune presiune pe sistem și poate cauza apariția unor defecte ce nu ar fi descoperite în mod normal. Deși este improbabil ca defectele descoperite în acest mod să cauzeze cedarea sistemului în condiții normale, pot fi reproduse combinații neobișnuite ale unor circumstanțe normale.

Testarea de stres este în mod special relevantă pentru sistemele distribuite bazate pe o rețea de procesoare. Aceste sisteme prezintă adeseori o degradare semnificativă atunci când sunt încărcate puternic. Rețeaua este blocată cu date de coordonare pe care diferitele procese trebuie să le interschimbe, ducând la încetinirea progresivă a acestora pe măsură ce așteaptă datele necesare de la alte procese. [2.1]

3) Testarea pe componente

Testarea pe componente ( uneori numită testare unitară ) este procesul de testare al componentelor individuale dintr-un sistem. Acest proces are obiectivul de a expune defecte prezente în cadrul acestor comoonente și este, în general, responsabilitatea dezvoltatorilor. [2.2]

Există diferite tipuri de componente ce pot fi testate:



  1. Funcții individuale sau metode dintr-un obiect

  2. Clase de obiecte care au multiple atribute și metode

  3. Componente compuse, formate din multiple funcții și obiecte diferite. Aceste componente compuse au o interfață definită, care este utilizată pentru a le accesa funcționalitatea

Funcțiile individuale sau metodele sunt cel mai simplu tip de componentă și testele vor fi un set de apeluri către aceste rutine cu diferiți parametri de intrare. Atunci când se testează clase de obiecte, testele trebuie sa acopere toată funcționalitatea obiectului și includ:

  1. Testarea în izolare a tuturor operațiilor asociate obiectului

  2. Setarea și interogarea tuturor atributelor asociate obiectului

  3. Trecerea obiectului în toate stările posibile ( toate evenimentele care cauzează o schimbare de stare în obiect trebuie simulate )

Dacă se folosește moștenire, este mai dificil să se proiecteze teste pentru clase de obiecte. Atunci când o superclasă oferă operații ce sunt moștenite de un număr de subclase, toate aceste subclase trebuie testate cu toate operațiile moștenite. Motivul este că operația moștenită poate face presupuneri cu privire la alte operații și atribute, care ar fi putut fi schimbate după ce au fost moștenite. De asemenea, când o operație a unei superclase este suprascrisă, operația cu care s-a suprascris trebuie să fie testată. [2.5]


3.1) Testarea de interfață


Multe componente dintr-un sistem nu sunt doar funcții simple sau obiecte, ci obiecte compuse din multiple obiecte care interacționează. Funcționalitatea acestora este accesată printr-o interfață. Testarea componentelor compuse se axează pe testarea faptului că interfața lor se comportă conform specificațiilor.

Fig 5 ilustrează procesul de testare al interfețelor. Se presupune că A, B și C au fost integrate pentru a crea o componentă mai complexă sau un subsistem. Cazurile de test nu sunt aplicate componentelor individuale, ci interfeței componentei compuse create prin combinarea acestor componente. [2.4]

Testarea de interfață este în mod particular importantă pentru dezvoltarea obiect-orientată. Obiectele și componentele sunt definite prin interfețele lor și pot fi reutilizate în combinație cu alte componente din sisteme diferite. Erorile de interfață din componenta compusă nu pot fi detectate prin testarea obiectelor sau componentelor individuale. Erorile din componenta compusă pot apărea din cauza interacțiunilor dintre părțile sale.

Sunt diferite tipuri de interfețe între componentele programului și în consecință, diferite tipuri de erori de interfață ce pot apărea [2.1] :



  1. Interfețe de parametri. Acestea sunt interfețe în care date si uneori referințe la funcții sunt pasate de la o componentă la alta

  2. Interfețe de memorie partajată. Acestea sunt interfețe în care un bloc de memorie este partajat între componente. Datele sunt plasate în memorie de un subsistem și preluate de acolo de alte subsisteme.

  3. Interfețe procedurale. Acestea sunt interfețe în care o componentă încapsulează un set de proceduri care pot fi apelate de către alte componente. Obiectele și componentele reutilizabile au acest tip de interfață.

  4. Interfețe pentru pasarea de mesaje. Aceste sunt interfețe în care o componentă cere un serviciu de la altă componentă prin pasarea unui mesaj către aceasta. Un mesaj este returnat, care include rezultatul execuției serviciului. Unele sisteme obiect-orientate au aceasta formă de interfață, la fel și sistemele client-server.

Erorile de interfață sunt unele dintre cele mai comune forme de eroare în sisteme complexe. Aceste erori se încadrează în trei clase:



  1. Utilizarea greșită a interfeței. O componentă apelează o altă componentă și utilizează greșit interfața. Acest tip de eroare este comun la interfețele de parametri, unde parametrii pot fi de un tip greșit, pot fi pasați într-o ordine greșită sau într-un număr greșit.

  2. Neînțelegerea interfeței. O componentă apelantă interpretează greșit specificațiile interfeței componentei apelate și face presupuneri cu privire la comportamentul componentei apelate. Când componenta apelată nu se comportă conform așteptărilor, apar comportamente eronate. De exemplu, o rutină de căutare binară poate fi apelată cu o matrice neordonată. Căutarea va da greș.

  3. Erori de sincronizare. Acestea au loc în sisteme în timp real care utilizează o interfață de memorie partajată sau de pasare de mesaje. Producătorul de date și consumatorul de date pot opera la viteze diferite. În absența unei proiectări atente a interfeței, consumatorul poate accesa date vechi deoarece producătorul nu și-a updatat informațiile.

Testarea de defecte ale interfețelor este dificilă, deoarece unele defecte de interfață se manifestă numai în condiții neobișnuite. De exemplu, fie un obiect care implementează o coadă pe post de structură de date de lungime fixă. Un obiect apelant poate presupune că această coadă este implementată ca o structură de date infinită și nu va verifica depășirea cozii când un element este introdus. Această condiție poate fi detectată în timpul testării numai prin proiectarea de teste care forțează depășirea cozii, iar această depășire trebuie să corupă comportamentul obiectului într-un mod detectabil. [2.2]

O altă problemă poate să apară din pricina interacțiunilor între defecte din diferite module sau obiecte. Defectele dintr-un obiect pot fi detectate numai când un alt obiect se comportă într-un mod neașteptat. De exemplu, un obiect poate apela alt obiect pentru a primi un serviciu și poate presupune că răspunsul este corect. Dacă a existat o neînțelegere cu privire la valoarea calculată, valoarea returnată poate fi validă, dar incorectă. Acest lucru se va manifesta numai când un calcul ulterior va da un rezultat eronat. [2.3]

Un set de reguli generale pentru testarea de interfețe este următorul:


  1. Se va examina codul ce trebuie testat și se va lista în mod explicit fiecare apel către o componenta externă. Se va proiecta un set de teste în care valorile parametrilor către componentele externe sunt la limitele extreme ale intervalelor lor. Aceste valori extreme au cea mai mare probabilitate să dezvăluie inconsistențe în interfață

  2. Când sunt pasați pointeri printr-o interfață, se va testa întotdeauna interfața cu parametri de tip pointer null.

  3. Când o componentă este apelată printr-o interfață procedurală, se vor proiecta teste care duc la defectarea componentei. Presupunerile de defectare eronate sunt unele dintre cele mai comune neîntelegeri de specificații.

  4. Se va utiliza testarea de stres în sisteme de pasare de mesaje. Se vor proiecta teste care generează mult mai multe mesaje decât este probabil să existe în practică. Se pot dezălui astfel probleme de sincronizare.

  5. Când mai multe componente interacționează printr-o memorie partajată, se vor proiecta teste care variază ordinea în care aceste componente sunt activate. Aceste teste pot dezvăli presupuneri implicite făcute de programator cu privire la ordinea în care aceste date partajate sunt produse și consumate.

Tehnicile de validare statice sunt adesea mai eficiente din punct de vedere al costului decât testarea, pentru a descoperi erori de interfață. Un limbaj strongly-typed precum Java permite ca multe erori de interfață să fie prinse de compilator, pe când la un limbaj precum C, un analizor static ( de exemplu, LINT ) poate detecta erori de interfață. [2.1]

4) Proiectarea cazurilor de test

Obiectivul procesului de proiectare a cazurilor de test este crearea unui set de cazuri de test care sunt eficiente în descoperirea defectelor de program și în indicarea faptului că sistemul întrunește cerințele.

Pentru a proiecta un caz de test, se selectează o caracteristică a sistemului sau o componentă care se testează. Apoi se selectează un set de intrări care execută acea funcționalitate, se documentează ieșirile dorite și, când este posibil, se proiectează o verificare automată, care testează ca ieșirile dorite și cele rezultate să fie identice.

Există diferite abordări pentru a proiecta cazuri de test [2.2]:


  1. Testarea bazată pe cerințe în care cazurile de test sunt proiectate pentru a testa cerințele sistemului. Aceasta este utilizată mai ales în etapa de testare a sistemului, deoarece, în general, cerințele de sistem sunt implementate de mai multe componente. Pentru fiecare cerință, se identifică cazurile de test care pot demonstra că sistemul întrunește acea cerință.

  2. Testarea pe partiții în care se identifică partițiile de intrare și de ieșire și se proiectează teste astfel încât sistemul execută întrările din toate partițiile și generează ieșirile în toate partițiile. Partițiile sunt grupuri de date care au caracteristici comune, precum un grup numai cu numere negative, toate numele cu mai puțin de 30 de caractere, etc.

  3. Testarea structurală în care se utilizează cunoștințele cu privire la structura programului pentru a proiecta teste care solicită toate părțile unui program. În esență, atunci când se testează un program, trebuie executat totul cel puțin o dată. Testarea structurală ajută la identificarea cazurilor de test care pot face acest lucru posibil.

În general, atunci când se proiectează cazuri de test, trebuie început cu testele de nivel cel mai înalt din cerințe și apoi adăugat progresiv teste detaliate folosind testarea structurală și pe partiții.

4.1) Testarea bazată pe cerințe


Un principiu general al ingineriei cerințelor este acela că aceste cerințe trebuie să fie testabile. Astfel, testarea bazată pe cerințe este o abordare sistematică de proiectare a cazurilor de test în care se ia în considerare fiecare cerință și se derivă un set de teste pentru aceasta. Testarea bazată pe cerințe este mai degraba validare decât testare de defecte, se încearcă demonstrarea faptului ca sistemul a implementat corect cerințele sale. [2.1]

Testarea unei cerințe nu implica scrierea unui singur test. În mod normal, sunt necesare mai multe teste pentru a asigura acoperirea completă a cerinței.


4.2) Testarea pe partiții


Datele de intrare și rezultatele de ieșire se încadrează adeseori într-un număr de clase diferite, care au caracteristici comune precum numere pozitive, negative, etc. Programele se comportă în mod normal într-un mod similar pentru toți membrii unei clase. Asta înseamnă că, atunci când se testează un program care execută calcule și necesită două numere pozitive, este de așteptat ca programul să se comporte la fel pentru toate numerele pozitive. [2.3]

Datorită acestui comportament echivalent, aceste clase sunt denumite uneori partiții de echivalență sau domenii ( Bezier, 1990 ). O abordare sistematică a proiectării de cazuri de test se bazează pe identificarea tuturor partițiilor unui sistem sau a unei componente. Cazurile de test sunt proiectate în așa fel încât intrările sau ieșirile să se încadreze în aceste partiții. Testarea pe partiții poate fi utilizată pentru a proiecta cazuri de test atât pentru sisteme, cât și pentru componente. [

În Fig. 6, fiecare partiție de echivalență este reprezentată ca o elipsă. Partițiile de echivalență ale intrărilor sunt seturi de date în care toți membrii setului trebuie procesați într-un mod echivalent. Partițiile de echivalență ale ieșirilor sunt ieșiri de program care au caracteristici comune și astfel pot fi considerate ca fiind o clasă distinctă. Se indentifică de asemenea partiții în care intrările sunt în afara celorlalte partiții care au fost alese. Acestea testează dacă programul tratează intrările invalide în mod corect. Intrările valide și invalide formează de asemenea partiții de echivalență.

Odată ce s-a identificat un set de partiții, se pot alege cazuri de test pentru fiecare dintre aceste partiții. O regulă generală pentru alegerea cazurilor de test este să se aleagă la limitele partițiilor și la jumătatea partițiilor, deoarece proiectanții și programatorii au tendința să considere valori tipice de intrare atunci când dezvoltă un sistem. Se testează prin alegerea mijlocului partiției. Valorile de la limită sunt adesea atipice și de aceea sunt omise de către dezvoltatori. Erorile programelor apar adesea la procesarea acestor valori atipice. [2.4]

Partițiile se identifică prin utilizarea specificațiilor programului sau a documentației de utilizator și din experiență.

Atunci când se testează programe ce folosesc secvențe, liste sau matrici, există un set de reguli proiectarea cazurilor de test:



  1. Se testează software cu generale pentru secvențe care au o singură valoare. Programatorii se gândesc în mod natural că secvențele sunt compuse din mai multe valori și trec uneori această presupunere și în programele lor. În consecință, programele pot să funcționeze incorect când secvența e compusă dintr-o singură valoare.

  2. Se utilizează secvențe diferite de lungimi diferite în teste diferite. Acest lucru scade șansele ca un program cu defecte să producă accidental o ieșire corectă.

  3. Se derivă testele astfel încât primul, ultimul și elementul de la mijloc să fie accesate. Această abordare identifică problemele de la limitele partiției.

4.3) Testarea structurală


Testarea structurală reprezintă o abordare a proiectării cazurilor de test prin care testele sunt derivate din cunoașterea structurii și implementării programului. Această abordare este uneori denumită “white-box”, “glass-box” sau “clear-box” pentru a o deosebi de testarea “black-box”.

Întelegerea algoritmului utilizat într-o componentă poate ajuta în identificarea altor partiții și cazuri de test. Pentru ilustrarea acestui concept, se va implementa o specificație de rutină de căutare sub forma rutinei de căutare binară. Secvența este implementată ca un vector ordonat. Prin examinarea codului rutinei de căutare, se observă că implică împărțirea spațiului de căutare în trei părți. Fiecare din aceste părți compun o partiție de echivalență ( Figura 8 ) . Se proiectează apoi cazuri de test în care cheia se află la limitele fiecărei partiții. [2.3]


4.4) Testarea de cale


Testarea de cale este o strategie de testare structurală al cărei obiectiv este solicitarea fiecărei căi de execuție independentă printr-o componentă sau printr-un program. Dacă fiecare cale independentă este executată, atunci toate instrucțiunile din componentă au fost executate cel puțin o dată. Mai mult, toate instrucțiunile condiționale sunt testate atât pentru cazurile adevărate, cât și cele false. Într-un proces de dezvoltare obiect-orientat, testarea de cale poate fi folosită la testarea metodelor asociate obiectelor. [2.5]

Numărul de căi printr-un program este de obicei proporțional cu dimensiunea acestuia. Pe măsură ce modulele sunt integrate în sistem, devine infezabil să fie folosite tehnicile de testare structurală. Tehnicile de testare de cale sunt, de aceea, utilizate preponderent pentru testarea de componente. Testarea de cale nu verifică toate combinațiile posibile alte tuturor căilor prin program. Pentru orice altă componentă, în afara celor triviale, fără bucle, acesta este un obiectiv imposibil. Există un număr infinit de combinații de căi posibile într-un program cu bucle. Chiar și atunci când toate instrucțiunile programului au fost executate cel puțin o dată, defecte de program încă pot apărea atunci când anumite căi sunt combinate. Punctul de start pentru testarea de cale este un graf al fluxului de program. [2.4] Acesta este un schelet al tuturor căilor prin program și constă din noduri ce reprezintă decizii și arce ce indică fluxul de control. Graful fluxului este construit prin înlocuirea instrucțiunilor de control ale programului cu diagrame echivalente. Dacă nu există instrucțiuni de tip “goto” într-un program, derivarea grafului este un proces simplu. Fiecare ramură a unei instrucțiuni condiționale ( if-then-else sau case ) este ilustrată ca o cale separată. O săgeată înapoi către nodul condițional indică o buclă. În Fig. 10 este ilustrat graful pentru căutarea binară. Fiecare instrucțiune este un nod separat și numărul nodului corespunde cu numărul liniei din program. [2.1]

Obiectivul testării de cale este asigurarea faptului că fiecare cale independentă prin program este executată cel puțin o dată. O cale independentă prin program este aceea care traversează cel puțin un arc nou in graful fluxului. În termeni de program, acest lucru implică solicitarea uneia sau mai multora condiții noi. Atât ramurile adevărate cât și cele false ale tuturor condițiilor trebuie executate.



În graful fluxului pentru căutarea binară din Fig. 10, fiecare nod reprezintă o linie din program cu o instrucțiune executabilă. Urmărind fluxul, se pot determina căile prin graf:

1, 2, 3 ,4, 5, 6 ,7 ,8 ,9 ,10, 14

1, 2, 3 ,4, 5, 14

1, 2, 3 ,4, 5, 6 ,7, 11, 12, 5, …

1, 2, 3 ,4, 6, 7, 2, 11, 13, 5, …

Dacă toate aceste căi sunt executate, se poate cunoaște cu certitudine că fiecare instrucțiune din metodă a fost executată cel puțin o data și fiecare ramură a fost verificată pe cazurile adevărat și fals.

Se poate găsi numărul de căi independente într-un program prin calculul complexității ciclomatice ( McCabe, 1976 ) al grafului de flux corespunzător programului. Pentru programele fără instrucțiuni de tip “goto”, valoarea complexității ciclomatice este numărul de condiții din program + 1. O condiție simplă este expresia logică fără conectori de tip “și” și “sau”. Dacă programul include condiții compuse, care sunt expresii logice ce au conectori “și” și “sau” în componență, atunci se numără condițiile simple din condițiile compuse atunci când se calculează complexitatea. [2.1]

De aceea, dacă sunt șase instrucțiuni de tip if și o buclă while și toate expresiile condiționale sunt simple, complexitatea ciclomatică este 8. Dacă o expresie condițională este compusă, ca de exemplu “if A atunci B sau C”, atunci se numără aceste trei condiții simple. Complexitatea ciclomatică este astfel 10. Pentru căutarea binară, complexitatea ciclomatică este 4, deoarece sunt trei expresii condiționale simple la liniile 5, 7 și 11.

După ce se determină numărul de căi independente prin cod calculând complexitatea ciclomatică, se proiectează cazurile de test astfel încât să execute toate aceste căi. Numărul minim de cazuri de test necesar pentru a testa toate căile programului este egal cu complexitatea ciclomatică.

Proiectarea cazurilor de test este simplă în cazul căutării binare, însă, atunci când programele au o structură ramificată complexă, poate fi dificil să se determine cum va fi procesat un caz de test particular. În aceste cazuri, un analizor dinamic de program poate fi folosit pentru a determina profilul de execuție al programului. [2.1]

Analizoarele dinamice de program sunt instrumente de testare care funcționează în conjuncție cu compilatoarele. În timpul compilării, aceste analizoare adaugă instrucțiuni suplimentare la codul generat. Acestea numără de câte ori fiecare instrucțiune de program a fost executată. Dupa ce programul a fost rulat, un profil de execuție poate fi listat. Acesta indică părțile din program care au fost sau nu executate folosind cazuri de test particulare. Profilul de execuție dezvăluie astfel secțiuni de program care au rămas netestate. [2.3]

5) Automatizarea testării

Testarea reprezintă un proces costisitor și laborios al dezvoltării software. Astfel, instrumentele de testare au fost printre primele instrumente software dezvoltate. Acestea oferă acum o gamă diversă de facilități și pot reduce semnificativ costurile de testare.

Un astfel de framework de testare este JUnit, folosit pentru testare de regresie. Acesta este un set de clase Java pe care utilizatorul le extinde pentru a crea un mediu de testare automatizat. Fiecare test individual este implementat ca un obiect și un executor de teste le rulează pe toate. Testele în sine trebuie scrise în așa fel încât să indice dacă sistemul s-a comportat conform așteptărilor. [2.4]

Un workbench de testare reprezintă un set de instrumente integrate pentru a susține procesul de testare. În plus față de framework-urile care suportă execuția automată a testelor, un workbench poate include instrumente pentru a simula alte părți ale sistemului și pentru a genera date de test. Printre instrumentele care pot fi incluse, sunt menționate [2.1]:



  1. Manager de teste. Administrează rularea testelor programului. Acesta ține evidența datelor de test, a rezultatelor dorite și a facilităților programului ce sunt supuse testelor. Un exemplu de manager de teste este JUnit.

  2. Generator de date de test. Generează datele de test pentru programul ce urmează a fi testat. Acest lucru poate fi realizat prin selectarea datelor dintr-o bază de date sau prin utilizarea de tipare pentru a genera date aleatore de forma dorită.

  3. Oracle. Generează predicții ale rezultatelor de test dorite. Oracolele pot fi fie versiuni precedente de program sau prototipuri de sistem. Testarea back-to-back implică rularea oracolului și a programului ce trebuie testat în paralel. Diferențele rezultatelor sunt evidențiate.

  4. Comparator de fișiere. Compară rezultatele testelor programului cu rezultate testelor anterioare și raportează diferențele între ele. Comparatoarele sunt utilizate în testarea de regresie, unde rezultatele diferitelor versiuni executate sunt comparate. Când sunt utilizate teste automate, acestea pot fi apelate chiar din cadrul testelor.

  5. Generatoare de rapoarte. Oferă facilități de definire și generare a rapoartelor pentru rezultatele testelor.

  6. Analizor dinamic. Adaugă cod la un program pentru a număra de câte ori a fost executată fiecare instrucțiune. După testare, un profil de execuție este generat, indicând cât de des a fost executată fiecare instrucțiune.

  7. Simulator. Diferite tipuri de simulatoare pot fi oferite. Simulatoarele de target simulează mașina pe care programul trebuie să execute. Simulatoarele de interfață utilizator sunt programe scriptate care simulează interacțiuni simultane ale utilizatorului.

Când sunt utilizate pentru sisteme de dimensiuni mari, instrumentele trebuie configurate și adaptate pentru sistemul particular care este testat. De exemplu: [2.2]



  1. Noi instrumente pot fi necesare pentru a testa caracteristici specifice ale aplicației și pot exista instrumente care nu sunt necesare.

  2. Scripturi pot fi necesare pentru simulatoarele de interfață utilizator și tipare definite pentru generatoarele de date de test. Poate fi necesară definirea formatelor rapoartelor.

  3. Poate fi necesară pregătirea manuală a seturilor de rezultate de test dorite, în cazul în care nu exista versiuni anterioare de program pentru a servi drept oracol.

  4. Poate fi necesară crearea de comparatoare de fișiere specializate, care includ cunoștințe cu privire la structura rezultatelor de test din fișiere.

O cantitate semnficiativă de efort și timp este necesară pentru a crea un workbench de testare exhaustiv. De aceea, astfel de workbench-uri sunt folosite numai în dezvoltarea sistemelor de dimensiuni mari. Pentru aceste sisteme, costurile de testare pot reprezenta până la 50% din costurile de dezvoltare totale, de aceea este important să se investească în sisteme de testare de foarte bună calitate. [2.2]

6) Concluzii [2.2]


  1. Testarea poate doar indica prezența defectelor într-un program, însă nu poate demonstra ca au fost eliminate toate defectele.

  2. Testarea de componente este responsabilitatea dezvoltatorului sistemului. O echipă separată de testare realizează în general testarea sistemului.

  3. Testarea de integrare reprezintă activitatea în care se testează componentele integrate și are rolul de a identifica defecte. Testarea funcțională are rolul de a testa versiunile produsului software și de a valida faptul că acestea întrunesc specificațiile.

  4. Atunci când se testează sisteme, trebuie încercat să se “strice” sistemul prin alegerea tipurilor de cazuri de test care au fost eficiente în descoperirea de defecte în alte sisteme.

  5. Testarea interfețelor are rolul de a descoperi defecte în interfețele componentelor compuse. Defectele de interfață pot apărea din cauza erorilor făcute în analiza specificațiilor, neînțelegerea specificațiilor, erori în cadrul specificațiilor în sine sau presupuneri de sincronizare greșite.

  6. Partiționarea de echivalență reprezintă un mod de a deriva cazuri de test. Aceasta depinde de găsirea de partiții ale intrărilor și ieșirilor și solicitarea programului cu valori din cadrul acestor partiții. Adeseori, valoarea care are cea mai mare probabilitate de a duce la un test de succes este cea de la limitele unei partiții.

  7. Testarea structurală se bazează pe analizarea unui program pentru a determina căile prin acesta și utilizarea acestei analize pentru selecția cazurilor de test.

  8. Automatizarea testării reduce costurile testării prin augmentarea procesului de testare cu o gamă variată de instrumente software.


Capitolul 3: Verificare şi validare de programe

Testarea unui program este cel mai comun mod de a verifica dacă sunt îndeplinite specificațiile și face ce vrea clientul. Cu toate acestea, testarea este doar una dintr-o serie de tehnici de verificare și validare. Unele dintre aceste tehnici, cum ar inspecțiile de program, au fost folosite de aproape treizeci de ani, dar încă nu au devenit parte din ingineria software.[3.1]



Obiective:

-diferenta dintre verificare software si validare software

- introducere in inspectiile de program ca metoda de a descoperi defecte de program

- intelegerea modului de analiza statica automata si modul in care este folosit in verificare si validare

- cum este folosita verificarea statica in procesul de dezvoltare

În timpul și după procesul de implementare, programul în curs de dezvoltare trebuie să fie verificat pentru a se asigura că acesta îndeplinește caietul de sarcini aferent și oferă funcționalitatea așteptata de oamenii care platesc software-ul. Verificarea și validarea reprezinta numele dat la aceste procese de control și analiză. [3.1]

Verificarea are loc în fiecare etapă a procesului software.Verificarea și validarea nu sunt același lucru, deși sunt adesea confundate.

Boehm (Boehm, 1979) și-a exprimat succint diferența dintre ele:

• "Validarea: Am construit potrivit produsul?"

• "Verificare: Am construit produsul potrivit?"

Aceste definiții ne spun că rolul de verificare presupune controlul că software-ul este conform cu specificația sa. Trebuie verificat că îndeplinește specificatiile sale funcționale și non-funcționale. Validarea, totuși, este un proces mai general. Scopul validarii este de a se asigura că sistemul software îndeplinește așteptările clientului. [3.1]

Scopul final al procesului de verificare și de validare este de a stabili încrederea că sistemul software-ul este "potrivit pentru scopul care a fost proiectat". Nivelul de încredere necesar depinde de scopul sistemului, așteptările utilizatorilor sistemului și mediul de comercializare al acestuia:



  1. Funcția Software-ului. Nivelul de încredere necesar depinde de scopul software-ului. De exemplu, nivelul de încredere necesar pentru software-ul care este utilizat pentru a controla un sistem critic pentru siguranță este mult mai mare decât cea necesară pentru un sistem software prototip care a fost dezvoltat pentru a demonstra unele idei noi.

2. Așteptările utilizatorilor. Este o reflecție tristă asupra industriei software in care mulți utilizatori au așteptări scăzute asupra software-ului lor și nu sunt surprinsi când acesta da erori în timpul utilizarii. Ei sunt dispuși să accepte aceste erori de sistem atunci când beneficiile utilizarii sunt mai mari decât dezavantajele. Cu toate acestea, toleranța de erori de sistem a scăzut începând cu anii 1990. Aceasta este acum mai puțin acceptabila pentru a furniza sisteme fiabile, astfel încât companiile de software trebuie să depună eforturi suplimentare pentru verificarea și validare.

3. Mediul de marketing . Atunci când un sistem este comercializat, vânzătorii de sistem trebuie să ia în considerare programele concurente, prețul pe care acești clienți sunt dispuși să il plateasca pentru un sistem. In cazul in care o firma are puțini concurenți, aceasta poate decide să lanseze un program inainte de a fi pe deplin testat și depanat pentru că vor să fie primul si sa apara cat mai repede pe piață. În cazul în care clienții nu sunt dispuși să plătească prețuri ridicate pentru software-ul respectiv, ei pot fi dispusi să tolereze mai multe defecte ale acestuia. Toți acești factori trebuie să fie luati în considerare atunci când se decide cât de mult efort ar trebui să fie depus pe procesul de verificare si validare. [3.1]

În cadrul procesului de validare si verificare, există două abordări complementare pentru controlul și analiza sistemului:


  1. Inspecții software : analizeaza și verifica reprezentările sistemului cum ar fi documentul cu cerințele, diagramele de design și codul sursa al programului. Se pot folosi inspecții în toate etapele procesului. Inspecțiile pot fi completate de unele analize automate ale textului sursă al unui sistem. Inspecțiile și analizele automate de software sunt tehnici statice de validare si verificare.

  2. Testarea Software-ului : implică executia implementarii software-ului de test cu date. Se examineaza rezultatele software-ului și comportamentul său operațional la verificari dacă funcționează conform necesităților. Testarea este o tehnică dinamica de verificare și validare.



Figura 1. Validarea si verificarea statica si dinamica [3.1]
Aceasta figura arată că inspecțiile de software și de testare joacă roluri complementare în procesul software. Săgețile indică etapele procesului în care tehnicile pot fi utilizate. Prin urmare, se pot utiliza inspecțiile software la toate etapele procesului software. Așa cum am discutat, cerințele și comentariile de proiectare sunt principalele tehnici utilizate pentru detectarea erorilor din caietul de sarcini și design. Se poate testa doar un sistem atunci când un prototip sau o versiune executabila a

programului este disponibila. Un avantaj de dezvoltare este disponibilitatea unei versiuni testabile a sistemului într-un stadiu destul de devreme în procesul de dezvoltare. [3.2]


Tehnicile de control includ inspecții de program, analiză automata de cod sursă și verificarea formală. Cu toate acestea, tehnicile statice pot verifica numai corespondența între un program și specificatiile sale; nu pot demonsta că software-ul este operațional. De asemenea, nu se pot utiliza tehnici statice pentru a verifica proprietățile emergente ale software-ului, cum ar fi performanța și fiabilitate. [3.2]

Testarea presupune exercitarea programul folosind datele, cum ar fi datele reale prelucrate de program. Defectele de program sau inadvertențele se vor descoperi prin examinarea rezultatelor programului și se caută anomalii.

Există două tipuri distincte de testare care pot fi utilizate la diferite etape ale procesului software:

1.Testarea de validare este destinata să demonstreze că software-ul este ceea ce clientul vrea - că îndeplinește cerințele sale. Ca parte a testului de validare, s-ar putea folosi testarea statistică pentru a testa performanțele programului și fiabilitatea, precum și a verifica cum reactioneaza în condiții de funcționare.

2. Testarea defectelor este destinata să dezvăluie defectele din sistem mai repede decât prin simularea utilizarii operaționale. Scopul testării defectelor este de a găsi neconcordanțe între un program și specificatiile sale. [3.2]

Desigur, nu există nicio limită de greutate și rapiditate între aceste abordări de testare. Procesele de validare, verificare și depanare sunt în mod normal intercalate. Pe măsură ce se descopera defecte în programul care se testeaza, va trebui modificat programul pentru a corecta aceste defecte. Cu toate acestea, testarea (sau, mai general, verificarea și validarea) și depanarea au obiective diferite:

1. procesele de verificare și validare sunt destinate pentru a stabili existența defectelor unui sistem software.

2. depanarea este un proces care localizează și corectează aceste defecte.



Figura 2. Procesul de depanare[3.2]


După ce un defect a fost descoperit în program, acesta trebuie corectat și apoi revalidat sistemul. Acest lucru poate implica reinspectarea programului în cazul în care testele existente sunt executate din nou. Testarea de regresie este utilizata pentru a verifica dacă modificările aduse unui program nu au introdus noi defecte. Experiența a arătat că o mare parte din "reparații” sunt fie incomplete , fie introduc noi defecte în cadrul programului. [3.2]

În principiu, ar trebui să se repete toate testele după fiecare reparație a defectelor; în practică, acest lucru este de obicei prea scump.




3.1 Planificarea verificarii si validarii

Verificarea și validarea este un proces costisitor. Pentru unele sisteme, cum ar fi sistemele în timp real cu constrângeri nefuncționale complexe, mai mult de jumătate din bugetul sistemului de dezvoltare poate fi cheltuit pe aceste procese . [3.3]




Figura 3. Planul de testare[3.3]
Planificarea sistemului de validare si verificarea ar trebui să înceapă cat mai devreme în procesul de dezvoltare. Modelul procesului de dezvoltare software este aratat în figura de mai sus si este numit uneori modelul –V . Este o instanțiere a modelului cascada și arată că planurile de testare ar trebui să fie deduse din specificațiile sistemului și proiectare. Acest model, de asemenea, descompune sistemul de validare si verificare într-un număr de etape. Fiecare etapă este determinată prin testele care au fost definite pentru a verifica conformitatea programului cu designul și specificatiile sale. [3.3]

Ca o regulă generală, pentru un sistem mai critic, mai mult efort ar trebui să fie dedicat tehnicilor de verificare statice.


Componentele principale ale unui plan de testare pentru un sistem mare și complex sunt :

  • Procesul de testare

O descriere a fazelor majore ale procesului de testare

  • Cerințe de trasabilitate

Sistemul de îndeplinire a cerințelor de testare ar trebui să fie planificat astfel încât toate cerințele sa fie testate individual.

  • Articole testate

Produsele procesului software care trebuie testate trebuie sa fie specificate.

  • Program de testare

Un program de testare și alocarea resurselor pentru acest program este, în mod evident, legat de programul mai general de dezvoltare a proiectului.

  • Proceduri de testare

Nu este suficient sa se ruleze testele pur și simplu; rezultatele testelor trebuie să fie în mod sistematic înregistrate. Trebuie să fie posibil să se verifice procesul de testare pentru a verifica dacă a fost efectuat corect.


  • Cerințe hardware și software

Această secțiune trebuie să stabilească instrumentele software si hardware necesare și estimate utilizarii.

  • Constrângeri

Constrângerile care afectează procesul de testare, cum ar fi lipsa de personal ar trebui să fie anticipate in aceasta sectiune.
Pentru sistemele mai mici, un plan de testare mai puțin formal poate fi utilizat, dar există încă o necesitate pentru un document oficial pentru a sprijini planificarea procesului de testare. Pentru unele procese agile, cum ar fi programarea extremă de testare este inseparabilă de dezvoltare. [3.3]

Planurile de testare nu sunt documente statice, dar evoluează pe parcursul procesului de dezvoltare. Planurile de testarese pot schimba din cauza întârzierilor în alte stadii în procesul de dezvoltare. În cazul în care o parte dintr-un sistem este incompletă, sistemul în ansamblul său nu poate fi testat. Atunci trebuie să se revizuiască planul de testare pentru a redistribui testerii pentru o altă activitate și aducerea înapoi, atunci când software-ul este din nou disponibil. [3.3]



3.2 Inspecțiile software
Inspecțiile software suntprocese statice , în care un sistem software este revizuit pentru a găsi erori, omisiuni și anomalii. Când se inspecteaza un sistem, se tine cont de cunoașterea sistemului, domeniul său de aplicare, limbajul de programare sau de designul modelului pentru a descoperi erori. [3.1]

Există trei avantaje majore ale inspecției:



  • În timpul testării, erorile pot ascunde alte erori. În consecință, o singură sesiune de inspecție poate descoperi multe erori într-un sistem.

  • Versiuni incomplete ale unui sistem pot fi inspectate fără costuri suplimentare. Dacă un program este incomplet, atunci este nevoie sa se dezvolte teste de specialitate pentru a verifica componentele care sunt disponibile.

  • La fel ca în căutarea pentru defecte de program, o inspecție poate lua în considerare și alte atribute de calitate ale unui program, cum ar fi respectarea standardelor, portabilitatea și întreținerea. De asemenea ne intereseaza ineficiența, existenta unor algoritmi nepotriviti sau stilul de programare sărac ce ar putea face sistemul dificil să se mențină și sa se actualizeze.



Procesul de inspecție al programului
Inspecțiile programului au ca obiectiv detectarea defectelor de program. Noțiune de un proces de control formal a fost dezvoltat pentru prima dată de IBM în anii 1970 (Fagan, 1976). Acum este o metodă de verificare a programului destul de utilizata pe scară largă, în special în ingineria sistemelor critice. Din metodă originală a lui Fagan, au fost dezvoltate o serie de abordări alternative pentru inspecție (Gilb și Graham, 1993). Diferența esențială între inspecțiile de programe și alte tipuri de revizuire a calității este că obiectivul specific al inspecțiilor este de a găsi defecte de program, mai degrabă decât să ia în considerare probleme mai largi de proiectare. Defecte pot fi erori logice, anomalii in cod , care ar putea indica o condiție eronată , nerespectarea organizarii sau standardele proiectului. [3.1]
Activitățile din procesul de inspecție sunt :

Autorul sau proprietarul - Programatorul sau proiectantul responsabil pentru producerea programului sau documentatiei. Responsabil pentru fixarea defectelor descoperite în timpul procesului de inspecție.

Inspectorul - Găsește erori, omisiuni și inconsecvențe în programe și documente. Poate identifica, de asemenea, probleme mai largi, care sunt în afara domeniul de aplicare al echipei de inspecție.

Corectorul - Prezintă codul sau documentul la o reuniune de inspecție.

Scribul - Înregistrează rezultatele reuniunii de inspecție.

Președintele sau moderatorul - Gestionează procesul și facilitează inspecția. Raporteaza rezultatele procesului la moderatorul șef.

Moderatorul general - responsabil cu îmbunătățirea procesului de inspecție, actualizarea listei de verificare, dezvoltarea standardelor, etc

Înainte de inceperea unui proces de inspectie de program, este esențial ca:

1. Sa existe o specificație exactă a codului care urmează să fie inspectat. Este imposibil sa se inspecteze o componentă la nivel de detaliu pentru a detecta defecte fără a avea o specificație completă.

2. Membrii echipei de control sa fie familiarizați cu standardele de organizare.

3. O versiunea compatibila a codului sa fie distribuita la toti membrii echipei. Nu va exista niciun punct în controlul codului, care este "aproape complet", chiar în cazul în care o întârziere provoacă întreruperi de program. [3.1]
Moderatorul echipei de inspecție este responsabil pentru planificarea inspecției. Acesta implică selectarea unei echipe de inspectie si asigurarea că materialul care urmează să fie inspectat și specificațiile sale sunt complete. Programul ce urmeaza sa fie inspectat este prezentat echipei de inspecție în etapa de prezentare generală, cand autorul codului descrie ceea ce programul este destinat să facă. Aceasta este urmată de o perioadă de pregătire individuală. Fiecare membru al echipei de inspectie studiaza specificatiile și programul si se cauta defectele în cod. [3.4]

Inspecția în sine ar trebui să fie destul de scurta (nu mai mult de două ore) și ar trebui sa se concentreze pe detectarea defectelor, standardelor de conformitate și de programarea de proasta calitate. Echipa de inspecție nu trebuie să sugereze modul în care ar trebui să fie corectate aceste defecte si nici să se recomande modificări la alte componente. [3.4]

În urma inspecției, autorul programului ar trebui să facă modificări pentru a corecta problemele identificate. În etapa de urmarire, moderatorul ar trebui să decidă dacă este necesară o reinspectie a codului. De asemenea se poate decide că nu este necesara o reinspectie completa și că defectele au fost stabilite cu succes. Programul este apoi aprobat de către moderator pentru lansare. [3.4]

Figura 4. Procesul de inspectie [3.4]




Verificari ale inspectiei [3.5]:
Defecte de date

Sunt toate variabilele programului inițializate înainte de atribuirea valorile lor care sunt folosite?

Au fost numite toate constantele?

Trebuie ca limita superioară de matrice sa fie egala cu dimensiunea matricei sau dimensiunea -1?

În cazul în care se utilizează șiruri de caractere, este un delimitator atribuit în mod explicit?

Există vreo posibilitate de supraincarcare a bufferului?



Defecte de control

Pentru fiecare afirmație condiționată, este condiția corecta?

Este stabilita pentru fiecare buclă conditia de terminare a acesteia?

Declaratiile compuse sunt corect intre paranteze?

În cazul declarațiilor, sunt toate cazurile posibile reprezentate?

Erori de intrare / ieșire

Sunt utilizate toate variabilele de intrare?

Sunt toate variabilele de ieșire atribuite unor valori înainte de a avea rezultatul programului?

Defecte de interfață

Nu toate apelurile de funcții și metode au numărul corect de parametri?

Sunt parametrii în ordinea corectă?

Dacă accesul componentelor la memoria partajată au același model ca al structurii de memorie partajată?



Erori ale managementului de stocare

Dacă legatura unei structuri este modificată, au fost corect realocate toate celelalte legaturi?

Dacă se utilizează stocarea dinamică, a fost alocat spațiu in mod corect?

Este spațiu în mod explicit dealocat după ce acesta nu mai este necesar?



Defecte de management

Au fost luate în considerare toate condițiile de eroare posibile?



3.3 Analiza statica automata
Inspecțiile sunt o forma de analiza statică –examinarea programul fără executarea aceastuia. Așa cum am discutat, inspecțiile sunt adesea conduse de liste de verificare de erori care identifică erorile comune în diferite limbaje de programare. Pentru cateva erori, este posibil să se automatizeze procesul de control al aceastei liste, care a dus la dezvoltarea de analizoare automate statice pentru diferite limbaje de programare. [3.4]

Analizoarele statice sunt instrumente software care scanează textul sursă al unui program și detecteaza eventualele defecte și anomalii. Acestea analizeaza textul de program și recunoaste astfel tipurile de declarații în program. Poate detecta apoi dacă declarațiile sunt bine formatate, face deducții despre fluxul de control în program și, în multe cazuri, poate calcula un set de valori posibile pentru toate datele de program si pot fi utilizate ca parte a procesul de inspecție sau ca o activitate distinctă a procesului de validare si verificare. [3.4]

Intenția de analiză statica automată este de a atrage atenția unui inspector la anomalii în cadrul programului, cum ar fi variabilele care sunt folosite fără inițializare, variabilele care sunt neutilizate sau date a căror valoare ar putea ieși din raza de acțiune. [3.4]

Unele dintre controalele care pot fi detectate prin analiza statica sunt :



Defecte de date

Variabilele sunt folosite inainte de initializare

Variabilele sunt declarate, dar niciodata folosite

Posibile incalcari ale declararii matricelor

Nedeclararea variabilelor

Defecte de control

Codul inaccesibil

Ramuri necondiționate în bucle

Erori de intrare / ieșire

Variabile de iesire neatribuite



Defecte de interfață

Nepotriviri ale tipului parametrului

Nepotriviri ale numărului de parametrii

Neutilizarea rezultatelor funcțiilor

Functii si proceduri neapelate

Erori ale managementului de stocare

Pointeri neasignati

Aritmetica pointerilor
Anomaliile sunt adesea rezultate ale unor erori de programare, astfel încât acestea să sublinieze lucruri care ar putea merge greșit atunci când programul este executat. Cu toate acestea, ar trebui să se înțeleagă că aceste anomalii nu sunt neapărat defecte de program. [3.1]

Etapele implicate în analiza statica includ [3.1]:



1. Controlul fluxului de analiză -- Această etapă identifică și scoate în evidență buclele cu multiple ieșiri sau punctele de intrare și codul inaccesibil. Codul inaccesibil este codul care este înconjurat prin declarații Goto necondiționate sau, care este într-o declaratie condiționata si condiția nu poate fi adevărata.
2. Analiza de utilizare a datelor -- Această etapă evidențiază modul în care sunt folosite variabile în program. Aceasta detectează variabilele care sunt folosite fără inițializare anterioara, variabilele care sunt scrise de două ori și variabilele care sunt declarate, dar nu au fost folosite niciodată. Analiza de utilizare a datelor descoperă, de asemenea, teste ineficiente în cazul în care condiția testului este redundantă. Condițiile redundante sunt condiții care sunt fie adevărate, fie false întotdeauna.
3, Analiza interfetei -- Această analiză verifică coerența de rutină, declarațiile procedurilor și utilizarea lor. Nu este necesara în cazul limbajelor de programare puternice cum ar fi Java, deoarece compilatorul efectuează aceste verificări. Analiza interfaței poate detecta erori în limbaje slabe cum ar fi FOR-TRAN și C. Analiza interfetei poate detecta, de asemenea, funcții și proceduri care sunt declarate și nu sunt apelate niciodata sau rezultate ale funcțiilor care nu sunt utilizate.
4, Analiza fluxului de informații -- Această fază a analizei identifica dependențele dintre variabilele de intrare și cele de ieșire. În timp ce nu se detectează anomalii, se arată modul în care valoarea fiecărei variabile din program este derivata din alte valori ale variabilelor. Cu aceste informații, o inspecție a codului ar trebui să poată să găsească valori care au fost calculate în mod eronat. Analiza fluxului de informații poate arăta, de asemenea, condiții care afectează valoarea unei variabile.
5, Analiza rutelor -- Această fază de analiză semantică identifică toate rutele posibile prin program și stabilește situațiile executate în această ruta. Ea dezvăluie, în esență, controlul programului și permite fiecarui posibil predicat să fie analizat individual.
Analiza statica este deosebit de valoroasa atunci când este folosit un limbaj de programare, cum ar fi C-ul. Acest lucru este deosebit de important atunci când C (și într-o măsură mai mică, C ++) este utilizat pentru dezvoltarea sistemelor. În acest caz, analiza statică poate descoperi un număr mare de erori potențiale și poate reduce semnificativ costurile de testare. [3.5]

Nu există nicio îndoială că, pentru limbaje, cum ar fi C, analiza statica este o tehnica eficienta pentru a descoperi erori de program. Cu toate acestea, designerii de limbaje de programare moderne, cum ar fi Java, au eliminat unele erori caracteristice lingvistice predispuse. Toate variabilele trebuie să fie inițializate, nu există declarații Goto, astfel codul inaccesibil este mai puțin probabil să fie creat accidental, și managementul de stocare este automat. Această abordare de evitare a erorilor este mai eficienta în îmbunătățirea fiabilității programului decât detecția erorilor. Cu toate ca analiza statica pentru Java este disponibila, aceasta nu este utilizata pe scară largă. Nu este clar dacă numărul de erori detectate justifică timpul necesar pentru a analiza rezultatelor programului. [3.5]

Prin urmare, pentru a ilustra analiza statică se foloseste un program C mic, mai degrabă decât un program Java. Sistemele UNIX si Linux includ un analizor static numit LINT pentru programele C. LINT prevede verificarea statica, care este echivalentă cu cea prevăzută de compilator într-un limbaj puternic cum ar fi Java. Un exemplu de producție realizată de LINT este prezentată în figura. [3.5]

Figura 5. Analiza statica LINT (Software engineering 8th ed) [3.5]

În aceasta transcriere a unei sesiuni de terminale Unix, comenzile sunt prezentate cu caractere cursive. Prima comandă (linia 138) enumeră ( fără sens) programul. Definește o funcție cu un parametru, numita printarray, și apoi solicită această funcție cu trei parametri. Variabile i și C sunt declarate, dar nu le sunt atribuite valori. Valoarea returnată de funcție nu este utilizata. [3.5]

Linia 139 prezinta compilarea C a acestui program cu nicio eroare raportata de către compilatorul C. Aceasta este urmată de un apel al analizorului static LINT, care detectează și raporteaza erori de program. [3.5]

Analizorul static arată că variabilele c și i au fost folosite, dar neinitializate, și că printarray a fost apelata cu un număr diferit de argumente decât a fost declarata. Identifică, de asemenea, utilizarea inconsecventă a primului argument în printarray și faptul că valoarea funcției nu a fost folosita niciodată. [3.5]

Analiza pe bază de instrument nu poate înlocui inspecții, așa cum există unele tipuri de erori pe care analizoarele statice nu le pot detecta. De exemplu, acestea pot detecta variabilele neinitializate, dar nu pot detecta initializarile care sunt incorecte. În limbaje slabe, cum ar fi C, analiza statica poate detecta funcții care au greșite numarul și tipurile de argumente, dar ei nu pot detecta situațiile în care un argument incorect de tip corect a fost trecut la o funcție. [3.5]

Pentru a aborda unele dintre aceste probleme, analizoare statice cum ar fi LCLint (Orcero, 2000;Evans și Larochelle, 2002) susțin utilizarea de adnotări în cazul în care utilizatorii definiesc constrângeri în program. Aceste constrângeri permit unui programator să precizeze că variabilele dintr-o funcție, nu ar trebui să fie schimbate, variabilele globale utilizate, și așa mai departe. Analizorul static poate verifica apoi programul împotriva acestor constrângeri și evidentierea secțiunilor de cod care par a fi incorecte. [3.5]

3.4 Metode formale si de verificare
Metodele formale de dezvoltare software se bazează pe reprezentări matematice ale software-ului, de obicei, ca o specificație formală. Ne putem gândi la utilizarea metodelor formale ca la verificarea tehnică statica finala. Pentru asta este nevoie de analize foarte detaliate ale specificatiilor sistemului și programului, iar utilizarea lor este de multe ori consumatoare de timp și costisitoare. În consecință, utilizarea metodelor formale este în mare parte limitată la securitatea critica a proceselor de dezvoltare software. [3.1]
Metodele formale pot fi folosite în diferite etape in procesului de verificare si validare[3.1]:

1. O specificație formală a sistemului poate fi dezvoltata și analizata matematic pentru inconsecvențe. Această tehnică este eficientă în descoperirea erorilor și omisiunilor din documentatie.

2. Puteți verifica în mod formal, folosind argumente matematice, că codul unui sistem sofware este în conformitate cu specificatiile sale. Acest lucru necesită o specificație formală și este eficienta în descoperirea unor erori de proiectare.
Argumentul pentru utilizarea specificației formale și verificarea programului asociat este ca specificația formală forțează o analiză detaliată a caietului de sarcini. Aceasta poate dezvălui potențiale inconsecvențe sau omisiuni care nu ar putea fi altfel descoperite până când sistemul este operațional. Verificarea formala demonstrează că programul dezvoltat respectă specificațiile sale, astfel erorile implementate să nu compromită fiabilitatea. [3.1]

Argumentul împotriva utilizării specificațiilor formale este că necesită notații de specialitate.

Inginerii software nu pot recunoaște potențialele dificultăți ale cerințelor pentru că nu înțeleg domeniul. Cu toate ca specificatiile pot fi substantiale din punct de vedere matematic, acestea nu pot specifica sistemului proprietățile care sunt într-adevăr necesare. [3.1]

Verificarea unui sistem software nontrivial necesita mult timp și instrumente specializate, cum ar fi expertiza teoremelor matematice. Prin urmare, este un proces extrem de costisitor și, care crește dimensiunea sistemului, costurile de verificare formală crascand în mod disproporționat. Prin urmare, mulți oameni cred că verificarile formale nu sunt costisitoare si eficiente. Același nivel de încredere în sistem poate fi realizat mai ieftin prin folosirea altor tehnici de validare, precum inspecții și testarea sistemului. [3.1]

Acesta este, uneori, susținut de faptul ca utilizarea metodelor formale pentru dezvoltarea sistemului conduce la sisteme mai fiabile și mai sigure. Nu există nicio îndoială că specificatiile unui sistem formal este mai puțin probabil să conțină anomalii care trebuie rezolvate de către designerul sistemului. Cu toate acestea, specificatiile formale nu garantează că software-ul va fi de încredere în utilizarea practică. Motivele pentru aceasta sunt:

1. Specificațiile pot să nu reflecteze cerințele reale ale utilizatorilor sistemului. Lutz (Lutz, 1993) a descoperit că multe eșecuri experimentate ale utilizatorilor au fost o consecință de erori și omisiuni ale specificatiilor care nu au putut fi detectate de sistemul formal. În plus, utilizatorii sistemului rareori înțeleg notațiile formale astfel încât acestia nu pot citi caietul de sarcini oficial pentru a găsi direct erori și omisiuni.

2. Verificarea poate contine erori. Verificarea programului este mare si complexa, așa, ca programele mari și complexe, conțin si ele, de obicei, erori.

3. Verificarea poate presupune un model de utilizare care este incorect. Dacă sistemul nu este folosit anticipat, verificarea poate fi invalida.

În ciuda dezavantajelor lor, metodele formale au un rol important în dezvoltarea de sisteme software critice. Specificațiile formale sunt foarte eficiente în a descoperi problemele de specificație care sunt cele mai frecvente cauze ale eșecului sistemului. Verificarea formala creste încrederea în cele mai critice componente ale acestor sisteme. Utilizarea acestor abordări formale este în creștere și ca tot mai multi ingineri se familiarizeaza cu aceste tehnici. [3.1]



Dezvoltare de software de curatare, Cleanroom
Un model al procesului de curatare este prezentat în figura .

Figura 6. Procesul de curatare [3.1]


Obiectivul aceastei abordari a dezvoltării software este un software cu zero defecte. Numele "Cleanroom" a fost derivat prin analogie cu unitățile de fabricație în cazul în care defectele semiconductoarelor sunt evitate prin fabricarea într-o atmosferă extrem de curata. Dezvoltarea „cleanroom” este deosebit de relevanta pentru acest capitol, deoarece a fost înlocuita testarea unității componentelor sistemului de inspecții pentru a verifica coerența acestor componente cu specificațiile lor. [3.1]

Abordarea Cleanroom pentru dezvoltarea software se bazează pe cinci strategii cheie:



  1. Specificație formală

Software-ul care urmează să fie dezvoltat este specificat în mod formal. Un model de tranzitie al starilor care arată răspunsurile sistemului la stimuli este folosit pentru a exprima specificatiile softului.

  1. Dezvoltarea incrementală

Software-ul este împărțit în trepte, care sunt dezvoltate și validate separat folosind procedeul Cleanroom. Aceste etape sunt specificate, cu clientul, într-un stadiu incipient în proces.

  1. Programarea structurata

Doar un număr limitat de control și abstractizare a datelor sunt utilizate. Procesul de dezvoltare al programului este un proces de rafinare treptată a specificatiilor. Un număr limitat de construcții sunt utilizate și scopul este de a transforma în mod sistematic specificația pentru a crea codul programului.

  1. Verificarea statică

Dezvoltarea software este static verificata cu ajutorul inspecțiilor software riguroase. Nu există nicio unitate sau modul de testate pentru codul componentelor.

  1. Testarea statistică a sistemului

Creșterea software-ului integrat este testat statistic pentru a determina fiabilitatea. Aceste teste statistice sunt bazate pe un profil operațional, care este dezvoltat în paralel cu specificațiile sistemului aratat în figura precedenta.
Există trei echipe implicate atunci când procesul Cleanroom este utilizat pentru sistemele de dezvoltare mari[3.1]:

1. Echipa de specificatii -- Acest grup este responsabil pentru dezvoltarea și menținerea specificațiilor sistemului. Aceasta echipa produce specificatii orientate spre client (definiția cerințelor utilizatorilor) și specificațiile matematice pentru verificare. În unele cazuri, atunci când specificațiile sunt complete, echipa de specificatii este, de asemenea, responsabila pentru dezvoltare.

2. Echipa de dezvoltare -- Această echipă are responsabilitatea de a dezvolta și verifica software-ul. Software-ul nu este executat în timpul procesului de dezvoltare.

3. Echipa de certificare -- Aceasta echipa este responsabila pentru dezvoltarea unui set de teste statistice pentru a exercita software-ul după ce a fost dezvoltat. Aceste teste sunt bazate pe specificația formală. Dezvoltarea testelor se efectuează în paralel cu dezvoltarea de software. Cazurile de test sunt utilizate pentru a certifica fiabilitatea software-ului. Modelele de creștere a fiabilitatii pot fi utilizate pentru a decide când se poate opri testarea.


Utilizarea abordării Cleanroom a dus, în general, la un software cu foarte puține erori. Abordarea de dezvoltare incrementală în procesul Cleanroom este de a oferi funcționalitate clientui în trepte, din timp. Funcții mai puțin importante de sistem sunt incluse în pași mai târzii. Prin urmare, clientul are posibilitatea de a încerca aceste creșteri critice înainte de livrarea întregului sistem. Dacă probleme ale cerințelor sunt descoperite, clientul isi spune parearea echipei de dezvoltare despre aceste informații și solicită o nouă versiune. [3.1]

Inspecția riguroasa a programului este o parte fundamentală a procesului Cleanroom. [3.1]

Argumentele matematice utilizate în procesul Cleanroom nu sunt, cu toate acestea, dovezi formale ale corectitudinii. Dovezi matematice formale prin care un program este corect în ceea ce privește specificația sa sunt prea scumpe pentru a fi dezvoltate. Acestea depind de cunoașterea semanticii formale ale limbajului de programare pentru a construi teorii care reprezinta programul și caracteristicile formale ale acestuia. Aceste teorii trebuie să fie dovedite apoi matematic. Din cauza costului ridicat și competențelor de specialitate care sunt necesare, acestea sunt de obicei elaborate numai pentru aplicațiile critice de securitate. [3.1]

Inspecția și analiza formală a fost dovedit a fi foarte eficiente în procesul cleanroom. Marea majoritate a defectelor sunt descoperite înainte de executare și nu sunt introduse în software-ul dezvoltat. Linger (Linger, 1994) a raportat că, în medie, au fost descoperite doar 2.3 defecte la mia de linii de cod sursă în timpul testarii pentru proiectele Cleanroom. Costurile totale de dezvoltare nu sunt crescute deoarece este nevoie de mai puțin efort pentru a testa și repara software-ul dezvoltat. S-a descoperit ca cele mai multe echipe ar putea folosi cu succes metoda Cleanroom. Programele produse au fost de o calitate mai buna decât cele dezvoltate folosind tehnici tradiționale - codul sursă a avut mai multe comentarii și o structură simplista. Dezvoltarea cleanroom funcționează atunci când este practicata de ingineri calificați și dedicați. [3.1]



3.5 Puncte cheie
Verificarea și validarea nu sunt același lucru. Verificarea este destinata să demonstreze că un program îndeplinește caietul de sarcini. Validarea este destinata să demonstreze că programul face ceea ce utilizatorul cere. [3.1]

■ Planurile de testare ar trebui să includă o descriere a elementelor care urmează să fie testate, programul de testare, procedurile de gestionare a procesului de testare, cerințele hardware și software, precum și orice problema de testare care poate să apară.

■ Tehnicile de verificare statice implica examinarea și analiza codului sursă al programului pentru a detecta erorile. Acestea ar trebui să fie utilizate cu testarea programului, ca parte a procesului de validare si verificare.

■ Inspecțiile de program sunt eficiente în găsirea erorilor de program. Scopul este de

localizare a defectelor. O listă de verificare a defectelor trebuie să conducă procesul de inspecție.

■ Într-o inspecție de program, o echipă mică verifică sistematic codul. Membrii echipei includ un lider de echipă sau moderator, autorul codului, un cititor care prezintă codul în timpul inspecției și un tester care prezinta codul dintr-o perspectivă de testare.

■ Analizele statice sunt instrumente software care prelucrează un cod sursă de program și atrage atenția asupra anomaliilor, cum ar fi secțiuni de cod neutilizate și variabile neinitializate. Aceste anomalii pot fi rezultatul unor defecte in cod.

■ Dezvoltarea software Cleanroom se bazează pe tehnici statice pentru verificarea programului și testarea statistică pentru certificarea fiabilitatii sistemului. Acesta a fost de succes în producerea de sisteme care au un nivel ridicat de fiabilitate.




Bibliografie:

Capitolul 1:


1.1) "Management Information Systems: Managing the Digital Firm" (ed. 11). Laudon, K., & Laudon, J.

1.2) “Software Engineering” ed. 8 – I. Sommerville

1.3) The Unified Software Development Process” - Ivar Jacobson, Grady Booch, James Rumbaugh

Capitolul 2:


2.1) “Software Engineering” 8th Edition – Ian Sommerville

2.2) “Software Testing  - Jiantao Pan



2.3) ”Introduction to Software Testing” - Paul Ammann, Jeff Offutt

2.4) ”Foundations of Software Testing - Mathur, Aditya P



2.5) ”Part of the Pipeline: Why Continuous Testing Is Essential - Adam Auerbach, 

Capitolul 3:

3.1 ) Software engineering”, ed. VIII, Addison Wesley, 2007 - A. Sommerville

3.2) „Verification, Validation and Testing in Software Engineering 1st Edition” - Aristides Dasso and Ana Funess


3.3) „Software Verification and Validation- An Engineering and Scientific Approach” - Fisher, Marcus S.

3.4) https://users.ece.cmu.edu/~koopman/des_s99/verification/


3.5) http://softwaretestingfundamentals.com/verification-vs-validation/
Yüklə 214,14 Kb.

Dostları ilə paylaş:
1   2   3




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©muhaz.org 2024
rəhbərliyinə müraciət

gir | qeydiyyatdan keç
    Ana səhifə


yükləyin