A IV-a faza a procesului de dezvoltare a sistemelor - FAZA IMPLEMENTĂRII
Aceasta este faza în care este produs codul corespunzator proiectului furnizat de faza anterioara, îndeplinind restrictiile de resurse, acuratete si performanta indicate de specificatii.
Procesul implementarii este cel mai dificil de descris, nefiind riguros definit. Implementarea este procesul transformarii abstractizarii prezentate în proiect într-o realizare fizica utilizând limbajul arhitecturii tinta. Este o faza concretizata într-o stare confuza, deseori haotica si instabila pentru sistemele software complexe, în care coordonarea este dificila.
O problema majora care cauzeaza instabilitatea consta în dificultatea translarii priectului în cod sursa.
În primul rând, un proiect nu va fi niciodata o mapare de 1 la 1 catre implementare. De aceea, oricât de bun ar fi proiectul este necesar un efort oarecare de a scrie codul corespunzator, ori aceasta este o sursa de a introduce erori.
În al doilea rând, procesul de transformare proiect-implementare este si mai dificil când proiectul nu este complet, consistent sau nu comunica exact si inteligibil ceea ce se doreste din partea sistemului. Erorile de proiectare determina pierderea timpului programatorilor în a rezolva probleme gresite puse. Acestea sunt erorile de logica si sunt cele mai frecvente. De aceea este foarte importanta utilizarea unor metode riguroase pentru prezentarea proiectului.
În al treilea rând, unele aspecte sunt în afara domeniului proiectantului. Efectele exacte ale utilizarii unui anumit sistem de operare sau limbaj de programare sunt în afara scopului proiectantului dar reprezinta o importanta decizie 717c29h a programatorului.
În cele din urma, implementarea însasi este predispusa catre erori, fiind un proces creator uman. Limbajul de programare poate fi folosit incorect, aceasta însemnând ca oarecare timp si efort se vor consuma pentru corectarea acestor erori. Din pacate, corectarea erorilor nu este o sarcina usoara. S-a constatat ca un programator are 50 sanse sa descopere eroarea într-un interval de 5-10 linii de cod si numai 20 sanse sa o decsopere într-un domeniu de 40-50 linii.
Documentele de baza produse în aceasta faza sunt:
codul sursa si obiect comentate într-o forma standard sau respectând anumite conventii
pliante (dosare) ale software-ului, prezentând modulele software individuale
manualul de utilizare a produsului software, prezentând conventiile utilizate în programe, o prezentare generala a implementarii, descrierea particularitatilor
planul pentru coordonarea configuratiei
planul pentru testarea produsului
Un aspect important în managementul fazei de implementare este cel al managementului configuratiei sistemului software. Motivul consta în faptul ca produsul se gaseste în diverse faze pe masura ce echipele de programatori implementeaza diferite parti ale sale si nu exista un produs "întreg" pâna la integrarea tuturor modulelor. De aceea, la anumite intervale de timp, toate modulele vor fi reunite formând o anumita versiune a produsului, baza de la care programatorii vor lucra în continuare.
Codul este produs în module. Fiecare modul trebuie sa fie inteligibil pentru cel care îl verifica si pentru programatorul care ulterior îl va întretine.
Fiecare modul :
include un header introductiv (titlu, nume autor, data crearii, istoria modificarilor)
declara toate variabilele si le documenteaza
foloseste nume semnificative si neambigue pentru variabile, functii, etc.
foloseste comentarii (acestea se recomanda pentru zonele dificile ale codului si nu pentru cele evidente. Se recomanda sa se separe comentariile de codul sursa prin linii vide)
evita ascunderea logicii modulului de catre codul de diagnoza (Codul de diagnoza se utilizeaza,de obicei, pentru a afisa continutul unor variabile sau pentru a evidentia starea programului. Exista tendinta de a sterge acest cod din versiunea finala a sistemului, totusi ele este folositor si în faza de întretinere a sistemului. De aceea, se recomanda ca acest cod sa fie comentat sau compilat conditionat (inclus ca linii de depanare)).
utilizeaza regulile programarii structurate
este consistent în folosirea limbajului de programare (pastreaza acelasi stil)
mentine un cod cât mai scurt si mai simplu (Un modul trebuie sa aiba o astfel de dimensiune încât sa fie vizibil dintr-o data. Lungimea maxima recomandata este de 50 linii, fara a considera header-ul si codul de diagnoza. În ceea ce priveste simplitatea codului, numarul de elemente care trebuie cuprinse mental examinând o parte a modulului nu trebuie sa depaseasca aproximativ 7 elemente.)
are o prezentare care sa evidentieze usor logica de control (Tehnica obisnuita este de a separa blocurile între ele prin linii vide si de a alinia blocurile din diversele constructii ale limbajului. Se recomanda a nu se utiliza mai multe instructiuni pe aceeasi linie.)
Standardele codarii trebuie sa fie stabilite pentru fiecare limbaj utilizat si prevazut în documentatia sistemului. Aceste standarde trebuie sa furnizeze reguli pentru:
prezentarea informatiilor (din header) si forma comentariilor
denumirea programelor, subprogramelor, fisierelor, variabilelor si datelor
limitarea dimensiunii modulelor
folosirea rutinelor de biblioteca
definirea constantelor
definirea tipurilor de date
folosirea datelor globale
tratarea erorilor
În faza de implementare se extinde mai întâi proiectul din faza anterioara la componentele primitive ale sistemului. Se vor folosi aceleasi metode din faza de proiectare (proiectarea structurata, proiectarea orientata-obiect, dezvoltarea sistemelor Jackson, metode formale). Urmatorul pas este a defini procesarea fiecarui modul prin metode ca: harti de fluxuri (fowcharts), rafinarea pas cu pas, programarea structurata, limbaje de proiectare a programelor (PDL), pseudo-codul, programarea structurata Jackson.
Producerea codului implica scrierea codului într-un limbaj de programare, verificarea si integrarea sa cu alte coduri pentru obtinerea unui sistem final.
În scopul scrierii codului se vor utiliza limbajele de programare.
Limbaje de programare
Urmatoarele clase de limbaje de programare sunt larg recunoscute:
a) limbaje procedurale (inperative sau algoritmice)
b) limbaje orientate-obiect
c) limbaje functionale
d) limbaje de programare logica
Limbajele functionale si logice sunt numite si declarative deoarece permit programatorului sa declare "ce" trebuie executat si nu "cum".
a) Limbaje procedurale suporta urmatoarele caracteristici:
secventa (permite specificarea ordinii executiei instructiunilor)
selectia (permite evaluarea unei conditii ti luarea unei decizii)
iteratia (permite structurilor repetitive)
diviziunea în module (permite descompunerea functionala)
Limbajele procedurale traditionale sunt COBOL si FORTRAN.
Unele limbaje procedurale suporta:
structurarea în blocuri
-impune ca un modul sa aiba un singur punct de intrare si un singur punct de
iesire. Pascal, Ada si C suporta aceasta caracteristica.
tipizarea puternica
-impune ca tipul fiecarei date sa fie declarat. Acest lucru previne aplicarea
operatorilor asupra obiectelor incompatibile din punct de vedere al tipului.
Aceasta caracteristica ajuta compilatorul în evidentierea erorilor si în
compilarea eficienta. Ada si Pascal sunt limaje puternic tipizate.
recursivitatea
-permite unui modul sa se autoapeleze. Pascal, Ada si C suporta recursivitatea.
b) Limbaje orientate-obiect
Limbajele orientate-obiect suporta toate caracteristicile limbajelor de programare structurata si, în plus:
mostenirea (este tehnica prin care modulele pot prelua capabilitati de la modulele de nivel superior)
polimorfismul (este abilitatea unui proces de a lucra cu diferite tipuri de date sau a unei entitati de a se referi la momentul executiei la instante ale diferitelor clase. Ideal ar fi ca un limbaj sa fie complet polimorf, astfel încât nu ar mai fi necesare portiuni de cod pentru fiecare tip de data. Polimorfismul implica suportul pentru "dynamic binding". "Dynamic binding" înseamna legarea metodelor obiectelor de selectarea mesajului la momentul executiei si nu al compilarii.)
mesajele (Limbajele orientate-obiect utilizeaza mesaje pentru implementarea interfetelor. Un mesaj încapsuleaza detaliile actiunii care trebuie realizata. Un mesaj este trimis de catre un obiect catre un alt obiect-receptor pentru a invoca serviciul celui din urma.)
Exemple de astfel de limbaje sunt: Smalltalk si C
c) Limbaje functionale
Limbajele functionale ca LISP si ML suporta structurarea declarativa, constructiile procedurale fiind inutile. În particular, cosntructia secventa nu mai este utilizata în logica programului. Un model informational de baza (arbore sau lista) este utilizat pentru a defini aceasta logica. Daca o anumita informatie este necesara pentru o operatie, ea este automat obtinuta din modelul informational. În programarea functionala operatorii (functiile) se aplica argumentelor (parametrii). Însisi parametrii pot fi expresii functionale astfel încât un program functional poate fi gândit ca o singura expresie aplicând o functie alteia. De exemplu, daca DOUBLE este functia definita ca DOUBLE(X)=X X, si APPLY este o functie ce executa o alta functie asupra fiecarui membru al listei, atunci expresia:
APPLY(DOUBLE, ) returneaza
Programele scrise în limbaje functionale apar diferite fata de cele scrise în limbaje procedurale deoarece asignarile sunt absente. Programele în limbaj functional sunt scurte, clare si sunt potrivite atât pentru specificatii cât si pentru implementarea rapida.
d) Limbaje de programare logica
Limbajele de programare logica implementeaza o anumita forma a logicii clasice. Ca si limbajele functionale, ele au o structura declarativa. În plus, suporta:
backtracking (este abilitatea de a reveni la un punct anterior în lantul de deductii, utila în momentul traversarii unui arbore de cunostinte)
backward chaining (începe cu o ipoteza si rationeaza înapoi spre factorii care au determinat ca aceasta ipoteza sa fie adevarata. De exemplu, daca factorul A si ipoteza B sunt înlantuite în expresia IF A THEN B, backward chaining permite sa se deduca faptul ca A este adevarat din ipoteza ca B este adevarat.)
forward chaining (este opusul conceptului backward chaining. Începe de la o colectie de factori si rationeaza spre o concluzie. De exemplu, daca factorul A si concluzia B sunt înlantuite în expresia IF A THEN B, backward chaining permite sa se deduca din faptul ca A este adevarat concluzia ca B este adevarat)
Cel mai important limbaj de programare logica este Prolog.
O gama larga de utilitare sunt valabile pentru dezvoltarea programelor, depanarea si testarea acestora:
utilitare de modelare (Modelling Tools) - genereaza nucleul ("scheletul ) modulelor
-genereaza automat declaratii pentru constante, variabile, tipuri pentru includerea în codul sursa al fiecarui modul. Unele utilitare de modelare pot tranforma diagramele reprezentând apelurile modulelor în apeluri de functii sau proceduri complet comentate, desi fara a avea valorile parametrilor actuali. Daca asemenea utilitare sunt folosite, scrierea codului începe prin a completa "scheletul unui astfel de modul: se completeaza toate apelurile; se introduc constructiile iterative (while, repeat, loop, etc); se introduc constructiile alternative (if, case, etc.) si se adauga în final detaliile de baza ca operatii aritmetice, operatii de intrare-iesire si alte apeluri sistem.
generatoare de cod - tranforma relatii formale în cod sursa
-se utilizeaza în domenii ca gestiunea bazelor de date si interactiunea cu factorul uman, domenii caracterizate de un cod repetitiv si de necesitatea de a executa numeroase operatii de rutina dar esentiale. Deoarece generatoarele de cod sunt din ce în ce mai mult integrate în metodele de proiectare, va fi posibil de a genera automat codul sursa pentru portiuni din ce în ce mai mari ale componentelor unui sistem. Chiar daca pentru parti ale sistemului codul va fi scris manual, utilizarea generatoarelor de cod ramâne în continuare avantajoasa. Modificari în cerintele software pot rezulta în schimbari automate în declaratiile datelor si modulelor, pastrând si verificând consistenta de-a lungul ciclului de viata al produsului.
editoare - creaza si modifica codul sursa si documentatia.
editoare senzitive la limbaj - creaza cod sursa corect din punct de vedere sintactic
-aceste editoare contin un interpretor care ajuta în scrierea unui cod sursa corect d.p.d.v. sintactic. Cele mai simple astfel de editoare recunosc parantezele si realizeaza o aliniere automata care fac programul mai usor de înteles si reduc erorile. E posibil, de asemenea, de a furniza scheme (tipare) pentru construirea programelor, continând headere standard, sectiuni obligatorii pentru declararea constantelor si tipurilor de date. Acestea pot fi generate automat de utilitarele de modelare. Editoarele care recunosc aceste scheme pot reduce timpul de dezvoltare si pot preveni erorile.
analizoare statice - examineaza codul sursa
-analiza statica este procesul de scanare a textului unui program pentru detectarea unor erori:
identifica variabile neutilizate sau utilizate înainte de a fi asignate
verifica daca valoarea variabilei este în intervalul admis
furnizeaza o prezentare a structurii aplicatiei
masoara complexitatea codului în termenii unei metrici
tranforma codul sursa într-un limbaj intermediar pentru verificare formala
masoara anumite atribute ale codului cum ar fi numarul de linii de cod si nivelul maxim de imbricare.
Cele mai multe compilatoare furnizeaza unele din caracteristicile analizoarelor statice (cum ar fi caracteristica 1). Analizoarele statice dedicate de obicei furnizeaza functii de analiza statica avansate, cum ar fi analiza structurii codului.
compilatoare - transforma codul sursa în cod obiect
-acestea variaza în viteza, completitudinea verificarilor, usurinta utilizarii, folosirea sintaxei standard, calitatea codului si afisarilor si prezenta caracteristicilor de programare. Alegerea compilatorului este de importanta cruciala. Viteza compilatorului afecteaza costul produsului si usurinta în dezvoltarea, depanarea si întretinerea produsului, în timp ce calitatea codului afecteaza performantele produsului în timpul executiei. Compilatoarele ar trebui comparate tinând cont de viteza lor, de timpul de executie al programului si dimensiunea codului. Dimensiunile stivei si a memoriei heap pot fi, de asemenea, importante. Compilatoarele variaza mult si functie de caracteristicile care suporta programarea:
listare completa
cros-referentierea
dimensiunea datelor si modulelor
diagnosticare
verificare completa
switch-uri (ex: verificarea limitelor vectorilor; limbaj strict sau extensii)
Cele mai avansate compilatoare executa anumite optimizari pentru masini secventiale sau paralele, încercând sa descopere si sa elimine deficientele codului sursa. Aceste optimizari pot fi impuse prin switch-uri, de exemplu prin directive în codul sursa (exemplu: directiva pragma în Ada). Utilizatorii ar trebui sa verifice daca optimizarile pe care le doresc sunt implementate în compilatoarele candidat.
linkeditoare - reunesc modulele obiect în programe executabile
-acestea sunt furnizate de masina, sistemul de operare sau compilator. De aceea, utilizatorul are în foarte mica masura controlul asupra alegerii acestora. Este util ca linkeditorul sa determine automat bibliotecile si directoarele pe care trebuie sa le utilizeze si care sunt modulele sau componentele care trebuie linkeditate. Cele mai multe linkeditoare pot fi controlate de parametri creati de utilitare build sau make.
depanatoarele - localizeaza erori în timpul executiei programului
-utilizarea depanatoarelor simbolice interactive este puternic încurajata, mai ales pentru verificare. Un depanator bun este integrat cu editorul si compilatorul interpretorul si permite o gama de moduri de investigare: pas cu pas, trasare prin breakpoint, vizualizarea valorilor variabilelor, setarea unor conditii.
analizoarele dinamice - examineaza programele în curs de executie
-analiza dinamica este procesul de masurare a resurselor (timp CPU, timp intrare-iesire, memorie) consumate de fiecare modul si linie de cod. În contrast cu analizoarele statice, cele dinamice se folosesc pentru programe în curs de executie. Analizoarele dinamice se mai numesc si profilers. Ele mai pot fi folosite si pentru a determina daca toate instructiunile programului au fost executate în timpul testului (coverage test). Unele analizoare dinamice verifica daca programul utilizeaza corect memoria, de exemplu, verifica daca apelurile pentru alocarea memoriei au corespondent în apeluri pentru dealocare, determinând astfel golurile de memorie (memory leaks).
Analizoarele dinamice pot localiza partile sistemului care cauzeaza slabe performante ale acestuia si pot detecta erori de programare (exemplu: initializari inutile).
utilitare de test - testeaza module si programe
-Acestea suporta una sau mai multe din urmatoarele functii:
generarea si gestiunea datelor de test
verificarea automata a rezultatelor
diagnoza erorilor si depanarea
realizarea testelor driver si stubs
Utilitarele generale de test pot genera mari cantitati de date de intrare
procesoare de text- pentru crearea documentelor
generatoare de documentatie -genereaza documentatie utilizator din codul sursa
-mentin consistenta dintre cod si documentatie si fac procesul de documentare concurent cu cel de codare. Generatoarele de cod pot include utilitare pentru generarea automata a documentatiei.
utilitare pentru managementul configuratiei - înregistreaza versiunile modulelor si fisierelor - sunt organizate în baze de date si controleaza dezvoltarea sistemelor când multe module pot exista în diferite versiuni. Unele utilitare permit specificarea unei configuratii (m module în n versiuni) si autoamata compilare, linkeditare si arhivare a acestora. Este recomandata folosirea utilitarelor pentru managementul configuratiei când numarul de module sau de versiuni devine foarte mare.
În concluzie, procesul de implementare este dificil de caracterizat si de descris. Aici se regasesc aspecte ale analizei cerintelor, ale specificatiilor si proiectarii. Programatorul va trebui sa faca un numar de importante compromisuri între siguranta produsului, costul, eficienta, timpul de executie, posibilitatea lui de întretinere, etc. Sarcina cea mai dificila a programatorului este de a realiza aceasta pluralitate a scopurilor. Este dificil de a spune care va fi rezultatul acestor compromisuri atât timp cât produsul nu este complet si testat. Odata ce produsul a fost finalizat, în sensul ca toate partile sale componente au fost reunite si sistemul poate functiona, începe etapa urmatoare a procesului de dezvoltare si anume faza testarii.
A V-a faza a procesului de dezvoltare a sistemelor
FAZA TESTĂRII
Testarea este procesul executiei sistemului produs cu scopul de a pune în evidenta erorile. Testarea e deseori considerata un aspect al fazei de implementare deoarece programele sunt testate de programatorii care le-au creat. Totusi, acest tip de testare este mai degraba local, la nivel de unitate, de modul, si nu la nivel global, al produsului software final.
Se va face face distinctie între termenul de depanare si cel de testare.
Depanarea consta în corectarea de catre programator a unor erori în componentele program pentru care sunt raspunzatori.
Testarea consta în executarea programului cu intentia de a descoperi erori. Pentru aceasta se utilizeaza abordarea falsificationista propusa ca metoda stiintifica de catre filizoful Karl Popper, abordare care implica aplicarea unor teste în urma carora sistemul esueaza.
Un program testat este cel în care conditiile care îl determina sa esueze nu au fost înca descoperite. Aceasta înseamna ca daca rezultatul testelor este consistent cu rezultatele asteptate, componenta testata se considera corecta în contextul testului.
Pentru proiectele complexe, specificatiile de test pentru sistem si pentru acceptarea acestuia nu trebuie scrise de catre analisti, proiectanti si programatori care au lucrat la proiectul respectiv (pentru sistemele mici si medii e acceptabil ca aceste specificatii sa fie scrise de catre cei ce dezvolta sistemul) ci de catre utilizatorii sistemului.
În scopul testarii se vor scrie în faza de proiectare specificatii pentru:
testele unitatilor
testele de integrare
testele sistemului
testele de acceptare
Aceste specificatii trebuie sa defineasca:
proiectele de test
cazurile de test
procedurile de test
Dupa ce modulele individuale au fost codate si testate, echipa de dezvoltare trebuie sa le integreze în componente mai mari pe care sa le testeze, sa le integreze în componente si mai mari, sa le testeze si pe acestea, s.a.m.d. Integrarea este, de aceea, strâns legata de testare.
Se urmaresc prin testare urmatoarele scopuri:
evidentierea erorilor
demonstrarea îndeplinirii cerintelor de catre sistem
stabilirea faptului ca sistemul se conformeaza necesitatilor utilizatorului
stabilirea performantei sistemului
masurarea sigurantei sistemului
asigurarea ca modificarile realizate în sistem nu au produs efecte secundare (testarea regresiva)
1. Metode de testare
Numarul de metode de testare este considerabil. În general, metodele de testare sunt specializate, în sensul ca cele mai multe proiecte creaza propriile metode de testare depinzând de produsul respectiv.
Strategiile de testare pot fi privite din perspectiva testelor tip black box si white box. Tabelul urmator listeaza diferentele între cele 2 tipuri de testare:
Black Box |
White Box |
testeaza specificatiile externe |
testeaza specificatiile interne |
evidentieaza domeniul Input Output |
evidentieaza domeniul programului |
nu pretinde cunoasterea codului |
pretinde cunoasterea codului |
realizeaza o testare functionala |
realizeaza o testare structurala |
Testarea white box este în primul rând directionata catre ramurile si caile structurii codului programului. În principiu, se doreste prin aceasta de a testa cât mai complet structura codului, indiferent de functiile implementate de structura. Acest tip de testare se utilizeaza mai ales la nivelul modulului.
Testarea black box nu necesita cunoasterea structurii programului ci a specificatiilor acestuia. Acest tip de testare urmareste intrarile si iesirile sistemului si este necesar (considerând testarea dinamica) la toate nivele de dezvoltarea a sistemului, începând cu modulul (unitatea).
Într-o alta clasificare, metodele de testare generice pot fi plasate în doua mari categorii:
metode statice
metode dinamice
Testarea statica reprezinta inspectarea si analiza proiectului si codului program. Aceasta metoda este utilizata de obicei pentru testarea unitatilor. Testarea statica se concentreaza asupra analizei structurii codului, încercând detectarea erorilor logice de programare si a practicilor de programare nerecomandate. O eroare logica poate fi initializarea gresita a unei variabile iar o practica de programare discutabila este, de exemplu, declararea unei variabile niciodata folosita (ceea ce determina consum inutil de memorie).
Metodele utilizate includ:
inspectarea manuala a codului
structured walk-through
analiza statica a cailor
Primele doua sunt utile în determinarea erorilor de calcul si logice, ultima evidentiaza erori de definite a datelor sau de logica a fluxului de control.
Analiza statica a cailor utilizeaza tehnici din teoria compilatoarelor pentru a examina graful fluxurilor de control si graful apelurilor ale programului. Programul este împartit în blocuri de cod (acolo unde fluxul de control se modifica- este întâlnita o constructie conditionala sau o eticheta- blocul se termina). Un arc reprezentând fluxul de control este trasat de la vechiul bloc la începutul noului bloc, ca în figura urmatoare:
![]() |
B1 label1:
..
If x=y goto label2
![]() |
B2 ... B4 label2:
x:=6 ..
. if x!=z goto label3
![]() |
B3 label3: B5 ..
... z:=6
..
Goto label1
Variabilele folosite în blocurile de cod sunt analizate. Tipul de informatii care pot fi evidentiate de-a lungul acestor fluxuri de control sunt:
variabile neinitializate
variabile declarate dar nefolosite
numarul de utilizari ale fiecarui tip de instructiune
imbricare incorecta a buclelor
bucle infinite
cod inaccesibil
nerespectarea codarii standard
Grafurile apelurilor sunt similare grafurilor fluxurilor de control, examinînd însa apelurile unitatilor de program (programul principal, proceduri, subrutine, functii, etc.) de catre alte unitati. Parametrii de apel si variabilele declarate si utilizate în unitatile de program sunt analizate. Pot fi detectate utilizari gresite ale parametrilor si variabilelor locale si globale.
Analiza statica este utila pentru evidentierea anumitor erori, dar e dificil de aplicat în aplicatiile foarte mari si nu ofera nici o informatie despre erori care apar în timpul executiei. Unele studii afirma ca aproximativ 25% din erori nu pot fi detectate daca se foloseste doar testarea statica. Analiza statica are avantajul de a evidentia mai multe erori decât analiza dinamica.Ea poate semnala erori care nu pot fi gasite prin testare dinamica.
De exemplu, se considera urmatoarea secsiune de cod:
total = 0
for (i=1; i<10; i ++)
total += beans[i];
if (i>11)
error_handling();
Instructiunea 5. nu se va executa niciodata. Aceste erori sunt localizate într-un cod care nu se va executa în timpul testarii. La prima vedere, aceste erori par inofensive dar modificari ulterioare ale programului (eventual în timpul descoperirii si corectarii altor erori) ar putea determina posibilitatea executarii acestei instructiuni (sau poate chiar grup de instructiuni) netestata (netestat) anterior.
Analizoarele statice fac parte, de obicei, din colectiile de utilitare pentru proiectarea sistemelor software, sau din mediile CASE.
Testarea dinamica consta în executia partilor de program pentru a verifica daca acestea îsi îndeplinesc specificatiile. Se aplica atât unitatilor cât si produsului.
Exista doua tipuri de testare dinamica:
Testarea dinamica functionala
-se concentreaza asupra comportarii externe a programului, fara a considera structura interna a programului, deci din perspectiva cutiei negre. Datele de test se construiesc conform cerintelor functionale specificate iar rezultatele furnizate de program se compara cu cele prezentate în specificatii.
Testarea dinamica logica.
-acest mod de testare se refera la modul în care se excuta programul, din perspectiva cutiei albe. Fiecare instructiune, fiecare decizie si conditie sunt testate. Aceasta înseamna ca fiecare instructiune este executata cel putin o data si fiecare conditie dintr-o decizie ia toate valorile posibile. Testarea poate merge si mai departe considerând toate combinatiile posibile de decizii conditii, dar acest lucru se aplica foarte rar. Se utilizeaza pentru verificarea interfetelor de date si control între unitati. Datele de interfata sunt cele transmise între programe iar controlul de interfata consta în secventa de apeluri si iesiri din module. De exemplu, nu se va permite acces la anumite variabile sau chiar la un anumit modul (a se vedea conceptul de private) iar acest lucru trebuie verificat.
Tot prin acest tip de testare se obtin urmatoarele informatii:
timpul de raspuns
timpul de executie a rutinelor
timpul de acces al variabilelor
timpii CPU
frecventa de executie a instructiunilor
Aceste teste dinamice pot fi aplicate modulelor individuale sau produsului final.
În proiectarea datelor de test se vor lua în consideratie evidentierea erorilor si verificarea îndeplinirii cerintelor utilizatorului. Astfel, în datele de test se vor include datele pentru toate cazurile speciale dar si date în afara domeniului corect de valori (valori incorecte).
Dupa corectarea erorilor, se vor repeta unele sau chiar toate testele anterioare. O astfel de testare (regresiva) este esentiala daca se doreste a se avea încredere în procesul de testare.
Utilizarea metodelor de testare statica sau dinamica nu garanteaza detectarea tuturor erorilor. În plus, limitarile practice de timp si de ordin financiar favorizeaza aceasta situatie. Totusi, planuri de test si strategii de integrare bine definite contribuie la obtinerea unui produs mai sigur si la reducerea costurilor finale ale produsului software.
2. Testarea fiecarei unitati
Planul pentru testarea unitatilor trebuie sa prezinte scopul, abordarea si resursele necesare pentru teste si sa tina cont de cerintele de verificare din Documentul Cerintelor Software.
Acest plan se realizeaza înca din faza de proiectare.
Testarea fiecarei unitati presupune:
n verificarea proiectarii si implementarii fiecarei componente de baza
n veririficarea faptului ca un modul executa ceea se doreste de la el (îsi îndeplineste specificatiile: testarea tip cutie neagra" - black box) si ca executa acest lucru în maniera în care trebuie sa o faca (testarea tip cutie alba" sau "cutie de sticla - white box
Testul cutie alba se realizeaza de obicei prin inserarea codului de diagnoza. Totusi depanatoarele sunt preferate pentru acest gen de testare.
Modul uzual de a testa un nou modul este de a trece prin câteva cazuri de test cu depanatorul si apoi de a lansa testele tip cutie negra pentru restul cazurilor. Datele de intrare de test trebuie sa fie realiste si sa acopere domeniul de valori posibile.
Înainte ca un modul (unitate) sa fie acceptat trebuie ca fiecare instructiune sa fie executata cel putin o data. Acest lucru se poate verifica utilizând depanatoarele, analizoarele dinamice si codul de diagnoza. Codul de diagnoza pot complica sursele de aceea analizoarele dinamice si depanatoarele sunt preferabile.
Daca unitatea este o o procedura sau un grup de proceduri, acestea trebuie invocate de un alt cod. Un program care apeleaza modulul , îi furnizeaza intrari si primeste rezultate se numeste driver de test. Driverele de test sunt implementate în cadrul aceluiasi proiect de dezvoltare a sistemului software.
În mod normal, testarea fiecarei unitati se face de catre persoane sau echipe raspunzatoare pentru producerea componentelor respective.
3. Integrarea si testarea sistemului
3.1 Integrarea
Componentele majore rezultate din scrierea codului se integreaza formând sistemul final.
Integrarea trebuie sa se realizeze într-o secventa functie-cu-functie, ceea ce permite a se demonstra din timp capabilitatile operationale ale software-ului si de a evidentia evolutia proiectului. În mod normal, primele componente care se integreaza suporta intrarea si iesirea. Odata ce aceste componente au fost integrate si testate, pot fi utilizate pentru a testa alte componente.
În aceasta etapa a integrarii, testarea devine raspunderea unei echipe de testare. De cele mai multe ori aceasta echipa este independenta de persoanele care lucreaza la dezvoltarea proiectului. Ea are responsabilitatea de a planifica, proiecta, executa si analiza toate testele de dezvoltare, dincolo de testele la nivel de unitate.
Metodele de integrare sunt urmatoarele:
integrarea functie cu functie -consta în urmatoarele etape:
selectarea functiilor care trebuie integrate
identificarea componentelor care contin aceste functii
identificarea dependentelor componentelor (fluxul datelor de intrare sau de control)
ordonarea componentelor functie de numarul dependentelor (primele sunt cele cu mai putine dependente)
când o componenta depinde de o alta aflata mai departe în lista anterior generata, se creaza un driver pentru simularea acesteia.
introducerea mai întâi a componentelor cu mai putine dependente
Diagramele fluxurilor de date sunt utile în reprezentarea dependentelor componentelor.
integrarea top-down utilizeaza module înlocuitoare sau substitute (stubs) pentru reprezentarea modulelor nivelelor de baza ale caror nume le poarta. Pe masura ce modulele reale sunt completate si testate, ele înlocuiesc substitutele.
integrarea bottom-up consta în utilizarea modulelor 'driver pentru reprezentarea modulelor de nivel mai înalt ale caror nume le poarta. Pe masura ce modulele reale sunt completate si testate, ele înlocuiesc modulele driver. Modulele driver pot fi utilizate pentru a implementa cazurile de test.
3.2 Testarea integrarii
Testarea integrarii verifica interfatarea corecta a componentelor majore. Trebuie sa se verifice daca toate datele interschimbate prin interfata respecta specificatiile proiectului si daca fluxurile de control definite în proiect au fost implementate.
3.3 Testarea sistemului
Aceste teste pot fi realizate în mediul de dezvoltare sau în mediul tinta sau într-o combinatie a celor doua. Ele trebuie sa verifice îndeplinirea obiectivelor sistemului.
Testarea sistemului trebuie sa includa activitati ca:
trecerea datelor prin sistem, corecta lor procesare si extragerea rezultatului
practicarea testelor de acceptare (verificarea îndeplinirii cerintelor utilizatorului)
practicarea testului de stress (masurarea limitelor de performanta)
estimari preliminare ale sigurantei sistemului si posibilitatii de întretinere
verificarea manualului utilizatorului
Tendinta de aparitie a erorilor (rata aparitiei erorilor) trebuie monitorizata de-a lungul testelor, masurând astfel siguranta sistemului, ea fiind importanta si în estimarea acceptarii sistemului.
Uneori este necesar de a construi simulatoare pentru sistemele cu care sofware-ul se va interfata. Aceste simulatoare reprezinta ele însele un proiect separat. Ele trebuie sa fie finalizate la timp si identice cu sistemul pe care îl simuleaza.
Manualul Utilizarii Sistemului este documentul cheie în timpul testarii sistemului.
Coordonatorul proiectului este cel care decide cât efort se va aloca fazei de testare, aceasta depinzând de cerintele de siguranta ale sistemului, desi din punct de vedere practic nu exista sisteme care sa nu contina erori. În aceste cazuri, costul testarii poate ajunge la aproximativ 45% din costul initial de dezvoltare a produsului. În alte cazuri poate fi mai ieftin a astepta ca erorile sa fie semnalate de utilizatori. Coordonatorul proiectului decide cea mai buna abordare de testare.
|