Upload
stan-alexandru-grecu-diana
View
76
Download
7
Embed Size (px)
DESCRIPTION
Fiabilitate
Citation preview
1
1. TESTAREA SI ASIGURAREA CALITATII SOFTWARE. SCOP SI IMPORTANTA.
Testarea software este: O etapă importantă, plină de provocări, din dezvoltarea software;
• Un proces de descoperire a evidenţelor defectelor (diferit de depanare= descoperirea surselor erorilor, şi diferit de corectarea erorilor);
• Verificare: dacă software este conform specificaţiilor, dar nu numai…
• … ci şi o parte a procesului de asigurare a calităţii unui sistem software- (prin testarea care se execută înainte de scrierea codului).
Testarea si asigurarea calitatii Testarea nu coincide cu asigurarea calităţii: testarea este o parte necesară dar insuficientă din QA (quality assurance); Testarea nu coincide cu asigurarea calităţii: testarea este o
parte necesară dar insuficientă din QA (quality assurance); Asigurarea calităţii cuprinde activităţi destinate prevenirii
defectelor, şi înlăturării acestor defecte; Testarea poate contribui la îmbunătăţirea calităţii prin
identificarea problemelor devreme în procesul de dezvoltare. Perspectiva testarii Este atitudinea testerului, care are sarcina dificilă de a pune sub semnul întrebării toate aspectele legate de softul testat; Fără a citi codul, un tester trebuie să anticipeze greşelile şi optimizările pe care le poate face un dezvoltator şi apoi să construiască teste pentru detectarea acestora;
2
În multe privinţe, a fi un tester bun este mai dificil decât a fi un dezvoltator bun, întrucât testarea solicită:
o bună înţelegere a procesului de dezvoltare şi a produselor sale;
abilitatea de anticipa erori posibile. Perspectiva testarii = un mod de a privi un produs software şi de a chestiona validitatea sa; Căutarea greşelilor este ghidată atât de căutarea sistematică, dar şi de intuiţie; Solicită demonstrarea faptului că un soft se comportă conform specificaţiei sale, şi nu execută nimic din ceea ce nu i se cere să execute. Importanta si scopul testarii Importanţa testării contribuie la:
- asigurarea că un sistem software face ceea ce trebuie să facă (…şi nimic în plus);
- asigurarea utilizatorilor împotriva căderilor sw ce pot duce la pierderi de timp, proprietăţi, clienţi, sau chiar vieţi;
Scop testarii: scrierea de software mai mentenabil, reutilizabil, flexibil.
3
2. TESTAREA INTR-UN PROCES ITERATIV SI INCREMENTAL DE DEZVOLTARE
Procesul este incremental, cu iteraţii la fiecare etapă (increment). (Modificări în modul de dezvoltare a sw introduc implicit modificări în maniera de testare) Proces iterativ de dezvoltare:
1. Analizează puţin. 2. Creează puţin din design. 3. Implementează puţin. 4. Testează ce poţi.
(Testează ce poţi include ceea ce poţi tehnic face, în condiţiile constrângerilor de timp şi resurse). Dacă un sistem sofware poate fi dezvoltat incremental, testarea se poate face la sfârşitul fiecărei etape. Dezvoltare incrementală: sistemul este dezvoltat ca o secvenţă de incremente:
increment = produs finit (model+documentare +cod), pentru o parte din funcţionalităţile cerute de la sistem
Produsele dezvoltate într-un increment sunt folosite de următorul increment, care adaugă (şi uneori schimbă) funcţionalităţi noi.
Incrementul final = sistem ce satisface toate cerinţele Pentru fiecare increment se trece prin etapele analiză- design- implementare-testare. Proces incremental, iterativ (pentru fiecare increment pot exista mai multe iteraţii: pentru soluţionarea erorilor/ lipsurilor depistate la testare) Dezvoltarea OO: adecvată dezvoltării evolutive
– Analiza, design-ul şi implementarea OO implică rafinarea succesivă a aceluiaşi model
4
– Produsele unui increment sunt extinse şi rafinate în incrementul următor (valabil şi pentru cazurile de testare)
– Dezvoltarea incrementală a produselor implică şi testarea lor incrementală
5
3. SPECIFICAREA CLASELOR. PRECONDITIILE SI POSTCONDITIILE OPERATIILOR. INVARIANTI.
Specificarea claselor. = ce reprezintă clasa, ce poate o instanţă a clasei să facă Specificaţia clasei include câte o specificaţie pentru fiecare operaţie a clasei Operaţie= acţiune ce poate fi aplicată unui obiect, cu un anumit efect Operaţii inspector (accesator)- furnizează informaţii despre obiecte, fără a le modifica (valori ale unor date membru, starea obiectului etc.). În C++: trebuie declarate const Operaţii modificatoare- schimbă starea unui obiect prin modificarea valorii unor atribute ale obiectului Testarea operaţiilor inspector diferă de a operaţiilor modificator Este o bună decizie de design OO ca o operaţie să fie ori modificator, ori inspector, dar nu ambele în acelaşi timp – uşurează şi testarea. Fiecare operaţie din specificaţia clasei trebuie să aibă ataşate un înţeles şi nişte constrângeri (fiecare operaţie să aibă o specificaţie care descrie ce face aceasta).
O bună specificare a semanticii operaţiilor este critică atât pentru dezvoltare cât şi pentru testare; Vom specifica semantica în diferite puncte:
• Precondiţii - descriu condiţii ce trebuie să fie îndeplinite înainte ca operaţia să se poată executa. Se exprimă în termenii atributelor obiectului ce conţine operaţia şi/sau atributelor parametrilor actuali ai mesajelor ce solicită executarea operaţiei
• Postcondiţii - descriu condiţii ce trebuie să fie îndeplinite după execuţia operaţiei.
6
Se exprimă în termeni de: - atributele obiectului ce conţine operaţia; - atributele parametrilor actuali ai mesajului ce
solicită execuţia operaţiei; - o valoare de răspuns a operaţiei şi/sau - excepţiilor ce pot apare
• Invarianţi - Descriu condiţii ce trebuie îndeplinite constant pe parcursul duratei de viaţă a obiectului. Un invariant de clasă este o postcondiţie implicită pentru fiecare operaţie dar invarianţii pot fi încălcaţi în timpul execuţiei.
4. SURSE DE ERORI DIN IMPLEMENTAREA CLASELOR Implementarea claselor cuprinde:
• Date membru (variabile)= valori ale atributelor • Funcţii membru/ metode • Constructori • Destructor • Atributele noilor instanţe nu sunt iniţializate corect • Colaborarea cu alte clase în implementarea codului unei
clase: dacă acele clase nu sunt implementate corect, aceasta duce la erori în codul clasei care le-a folosit în definiţia sa
• Implementarea clasei satisface specificaţia, dar nu avem garanţia că specificaţia este corectă
• Implementarea nu conţine toate operaţiile sau defineşte incorect operaţiile
• Clasa nu oferă o modalitate de verificare a precondiţiilor de către transmiţător.
Din perspectiva testarii: • Programarea contractuală: trebuie testate doar situaţiile în
care precondiţiile sunt satisfăcute
7
• Programarea defensivă: trebuie să testăm fiecare intrare posibilă pentru a verifica dacă ieşirea este tratată corespunzător
5. COMPARATI PROGRAMAREA CONTRACTUALA SI PROGRAMAREA DEFENSIVA
Programarea contractuală: accentuează precondiţiile dar are postcondiţii mai simple Programarea defensivă: reversul Programarea contractuala:
• Tehnica de design (Bertrand Meyer): o interfaţă se defineşte în termenii obligaţiilor primitorului/ transmiţătorului implicaţi într-o interacţiune
• Precondiţiile descriu obligaţiile transmiţătorului (înainte ca transmiţătorul să facă o cerere primitorului, transmiţătorul trebuie să se asigure că precondiţiile sunt îndeplinite)
• Postcondiţiile descriu obligaţiile primitorului (care trebuie să verifice că acestea sunt îndeplinite)
• Design-ul interfeţei unei clase: precondiţiile trebuie să fie suficiente pentru:
• a permite primitorului să ajungă la postcondiţii • a permite transmiţătorului să determine dacă toate
precondiţiile sunt îndeplinite înainte de trimiterea unui mesaj
• O mulţime de metode –accesor pentru verificare de condiţii • Trebuie ca postcondiţiile să acopere toate ieşirile posibile ale
unei operaţii, în ipoteza că precondiţiile sunt îndeplinite
8
Programarea defensiva: • Interfaţa se defineşte în primul rând din perspectiva
primitorului, şi a presupunerilor făcute de acesta asupra stării sale, a valorii intrărilor (argumente sau valori de date globale), la momentul cererii
• Operaţiile întorc o indicaţie (sub forma codului returnat) asupra stării cererii: succes/ eşec pentru un anumit motiv (valoare de intrare greşită)
• Scopul principal al programării defensive: să determine “garbage in” pentru a elimina “garbage out”
Dezavantaje: • Abordarea măreşte complexitatea sw: transmiţătorul trebuie
să corecteze în funcţie de ieşirile posibile ale operaţiei – Lipsa de încredere nu poate fi doar de partea
primitorului, ci şi a transmiţătorului (care verifică ieşirile operaţiei)
• Creşte dimensiunea codului şi a timpului de execuţia. Programarea defensivă: reflectă o lipsă de încredere a transmiţătorului faţă de primitor Programarea contractuală: responsabilitate mutuală împărţită de transmiţător şi primitor
– Primitorul procesează o cerere pe baza unor intrări presupuse a îndeplini precondiţiile
– Transmiţătorul presupune postcondiţiile îndeplinite după procesarea cererii
– Tehnicile se pot combina • Design-ul interfeţelor prin programare contractuală elimină
necesitatea ca primitorul să verifice precondiţiile; p.c. este mai eficientă din perspectiva programului şi programatorului
9
• Dezavantaj: în contextul execuţiei programului, nu putem fi siguri de respectarea contractului
– Trebuie ca toate interacţiunile să fie testate în programarea contractuală
• Programarea contractuală simplifică testarea claselor dar complică testarea interacţiunilor (trebuie să ne asigurăm că fiecare transmiţător îndeplineşte precondiţiile)
• Programarea defensivă complică testarea claselor (cazurile de test trebuie să acopere toate rezultatele posibile) dar şi testarea interacţiunilor (trebuie să ne asigurăm că se produc toate rezultatele posibile şi că sunt tratate corect de transmiţător)
• Idee: verificaţi din timpul design-ului dacă precondiţiile, postcondiţiile şi invarianţii sunt testabili
– Sunt constrângerile exprimate clar? – Specificaţia include metode de verificare a precondiţiilor?
6. MOSTENIREA DIN PERSPECTIVA TESTARII Mostenirea: - Permite refolosirea specificaţiei şi implementării unei clase pre-existente (superclasă/ clasă de bază) de către o subclasă / clasă derivată.
- Erorile in cazul mostenirii se propagă de la o clasă la descendenţii săi- prevenire: testarea unei clase imediat ce a fost dezvoltată
- Permite reutilizarea cazurilor de test Polimofismul = este abilitatea de a trata un obiect ca aparţinând la mai mult decât un singur tip Moştenirea ar trebui folosită doar pentru a modela relaţiile “este-un” sau “este-un-fel-de”
– Dacă D este o subclasă a lui C: D este un fel de C
10
Principiul susbstituţiei (Liskov): instanţa unei subclase D a lui C trebuie să poată fi folosită fără excepţii/ erori oriunde se foloseşte o instanţă a superclasei C Constrângerea modificărilor de comportament de la clasă la subclasă – un mod de a forţa substitutabilitatea Comportamentul unei clase se poate defini în termenii stărilor observabile ale unei instanţe şi a semanticii operaţiilor definite pentru o instanţă a clasei Comportamentul unei subclase se poate defini în termenii schimbărilor incrementale ale stărilor observabile şi operaţiilor definite de clasa de bază Pentru respectarea principiului substituţiei, se admit doar următoarele modificări în comportamentul unei subclase: (progamarea contractuala)
• Precondiţiile fiecărei operaţii să fie aceleaşi sau mai slabe (-mai puţin restrictive din perspectiva clientului)
• Postcondiţiile fiecărei operaţii să fie aceleaşi sau mai puternice (să facă cel puţin la fel de mult ca cele definite în superclasă)
• Invariantul de clasă să fie la fel sau mai puternic (să adauge constrângeri noi)
Din perspectiva stărilor observabile: • Stările observabile şi toate tranziţiile între ele din clasa
de bază trebuie să se pastreze în subclasă • Subclasa poate să adauge tranziţii între aceste stări • Subclasa poate adăuga stări observabile noi dacă sunt
concurente sau substări ale unei stări existente
11
Polimorfismul din perspectiva testarii: • Polimorfismul permite extinderea incrementală a sistemelor
prin adăugarea de clase, în loc de modificarea celor existente - în extinderi pot apărea interacţiuni neaşteptate ;
• Permite ca operaţiile să aibă parametri referiţi polimorfic – aceasta măreşte numărul de tipuri posibile de parametri ce trebuie testaţi
• Permite unei operaţii să specifice răspunsuri sub forma de referinţe polimorfice -clasa reală a referinţei pote fi incorectă sau neaşteptată pentru transmiţător
7. ANALIZA RISCULUI CA INSTRUMENT DE TESTARE Analiza riscului este o parte a planificării oricărui efort de dezvoltare Foarte utilă în a determina ce să testăm şi cât de mult Concepte de bază în analiza riscului şi aplicarea lor în testare Comparaţie:
- testarea bazată pe risc cu - testarea pe baza frecvenţei de utilizare a funcţionalităţii
Riscuri: • Risc= orice ameninţă atingerea cu succes a scopului
proiectului – un eveniment cu o oarecare probabilitate de apariţie,
care duce la anumite pierderi dacă apare • Ierarhizarea riscurilor: în funcţie de probabilitatea de apariţie
şi de gravitatea/ impactul pierderilor produse • Testarea pe bază de riscuri:
Să testăm mai aprofundat acele parţi ale sistemului care ascund cel mai mare risc – pentru a identifica erorile cele mai nocive Clasificarea Riscurilor:
1. Riscuri de proiect 2. Riscuri de business 3. Riscuri tehnice
12
1.Riscuri de proiect: – riscuri manageriale sau de mediu ce nu pot fi afectate
de procesul de testare – ex. insuficient personal calificat
2.Riscuri de proiect: • asociate cu noţiunile legate de domeniu
– Când domeniul modelat este volatil, suita de teste a sistemului trebuie să verifice extensibilitatea şi modificabilitatea atributelor sistemului
– Exemplu: modificarea regulilor de raportare fiscală – un risc pentru stabilitatea unui sistem contabil
– Asociate cu funcţionalitatea programului, deci cu testarea la nivel de sistem
3.Riscuri tehnice • includ unele concepte de implementare
– Exemple: stabilitatea codului generat de compilator (limbajul de programare poate fi o sursă de risc)/ stabilitatea componentelor sw
– Sunt asociate cu implementarea, deci cu testarea codului
Analiza riscului: • Este o procedură de identificare a riscurilor şi a modurilor de
prevenire a potenţialelor probleme • Ieşirea analizei riscului este lista de riscuri ierarhizate,
folosită în alocarea resurselor şi prioritizarea deciziilor Tehnica de analiza a riscului: Include 3 sarcini:
1. Identificarea riscului (riscurilor) adus de fiecare caz de utilizare pentru proiect
2. Cuantifică riscul 3. Creează o listă ierarhizată de cazuri de utilizare
13
Cazurile de utilizare cu risc ridicat • Cerinţele volatile prezintă un risc ridicat • Cerinţele aflate în afara domeniului de expertiză a echipei de
dezvoltare sunt un risc şi mai mare • Cerinţe care necesită tehnologii noi (ex. hardware dezvoltat
în paralel cu sw)-risc ridicat Gradele de risc:
• Coborât, mediu, ridicat (pentru început…) • Lista de cazuri de utilizare ordonată în funcţie de risc:
– Folosită de manageri pentru a asigna cazurile de utilizare incrementelor
– Folosită pentru a determina necesarul de testare pentru fiecare item
– Testarea pe bază de riscuri e folosită când riscurile sunt foarte mari (vieţi omeneşti)
• Vom selecta cazurile de test atât pe bază de riscuri cât şi pe baza profilului de utilizare
8. PLANIFICAREA TESTARII – TESTAREA PROIECTULUI,
COMPONENTELOR SI STANDARDUL DE TESTARE IEEE 829 Practica obişnuită:
– Testarea modulelor individuale – Testarea integrării subsistemelor (când sunt asamblate
din module şi alte susbsisteme) – Testarea sistemului – Într-un proces iterativ, incremental, – testarea sistemului se face după fiecare increment – Testarea claselor şi a interacţiunilor după fiecare
iteraţie a unui increment Abordarea curentă: testare înaintea scrierii de cod (testarea modelelor) Modelele de analiză: testarea validităţii sistemului
– Ne asigurăm că este specificat sistemul correct
14
Planul standard de testare IEEE 829 Urmatorii itemi din test sunt importanţi în particular:
• Caracteristici netestate— pentru testarea la nivel de clasă; se raportează rezultatele analizei HIT
– Analiza HIT cuprinde trăsături ce au fost testate şi necesită re-testare, şi trăsături programate pentru dezvoltare în iteraţii/ incremente următoare
– Criterii de suspendare a testului – Testarea se suspendă când numărul de erori găsite pe
oră scade sub criteriul (pragul) setat în această secţiune
– Secţiunea e importantă în dezvoltarea iterativă: vor exista criterii diferite pentru iteraţiile timpurii faţă de cele târzii
Riscuri şi contingenţe, în acest context, un risc identifică potenţialele probleme în ghidarea testului: Erori posibile legate de răspunsurile corecte în mulţimi mari de date şi posibilitatea ca platforme diferite să ducă la rezultate diferite Planul de testare al proiectului Acest document rezumă strategia de testare folosită de proiect
• Trebuie să definească paşii procesului de dezvoltare unde va apare testarea
• Frecvenţa cu care va apare testarea • Cine este responsabil cu testarea • Partea a doua a planului de testare (figura următoare)
asociază fiecărei faze o strategie specifică • Vom descrie în cursurile următoare mai multe strategii
de testare • Tabelul mai reţine standardele proiectului pentru testare
adecvată pentru fiecare nivel de risc, în cadrul fiecaruia din cele 3 faze
15
Plan de testare a componentelor • Scop: definirea strategiei globale şi a cazurilor de test
specifice ce vor fi folosite pentru a testa o anume componentă
• Criteriile proiectului = standarde legate de cât de aprofundat vor fi testate componentele + criterii de acoperire
– Exemplu: 100% din postcondiţiile metodelor modificator să fie testate
• Procedurile proiectului: = tehnici alese pentru o sarcină anume
– Exemplu: construirea unei clase PACT pentru fiecare componentă ce va fi testată
– Dau detaliile pentru strategiile de testare • Obiectivele clasei. Lista prioritizată de obiective:
– ex. componenta este un element al framework-ului de bază al aplicaţiei, abstracţiune de nivel înalt din care se vor deriva variante mai specifice
– Cerinţele inspecţiei dirijate 9. CELE 5 DIMENSIUNI ALE TESTARII CLASELOR
1. Cine testează? 2. Ce părţi vor fi testate? 3. Când se va face testarea? 4. Cum se va face testarea? 5. Cât este suficient să testăm?
1.Cine testeaza ? Dezvoltator – activităţi de generare a produsului
- analiză, design, programare, depanare, documentare Tester –activităţi de detectare a căderilor unui produs
- Selectarea testelor specifice unui scop, construirea testelor, executarea testelor şi evaluarea rezultatelor
Schema “testarea colegului” Testarea sistemului- testeri independenţi “Life critical”: fiecare unitate testată de un tester independent
16
2. Ce testam ?
• Testarea fiecărei clase • Nu vom testa nimic -Căderile sunt descoperite prin:
– operarea aleatoare a sistemului, – copii de evaluare pe web, – rapoarte de erori de la useri
• Calea de mijloc: selectarea statistică a componentelor de
testat • Clasele reutilizate din alte proiecte/ din librării de clase- nu
sunt testate • Unele clase sunt dificil de testat individual
– Necesită drivere complexe pentru furnizare intrări/ examinare ieşiri
• Un echilibru între beneficiul testării (defecte depistate pe oră de efort) şi efortul necesar construirii infrastructurii de testare
• Strategii de alegere a cazurilor de test: – Utilizări probabile ale sistemului – Cazuri patologice de utilizare
3. Cand testam? • Pe parcursul dezvoltării componentelor/ după integrarea într-
un singur executabil • De ce testăm mai târziu, de ce va fi mai costisitor să facem
modificări pe baza rezultatelor testelor
• Testarea sistemului / a acceptării (doar la sfârşit)
– Util când sunt doar câţiva dezvoltatori lucrând pe un set clar de cerinţe
17
• Testarea zilnică • Testarea fiecărei componente pe măsură ce se realizează
– Încetineşte dezvoltarea, dar compensează prin reducerea problemelor mai târziu (la asamblarea componentelor)
• Testarea la sfârşitul fiecărui increment (componentele asamblate)
– Dezavantajoasă dacă e vorba de o funcţionalitate atât de complexă încât e greu de verificat după asamblarea componentelor
– Utilă pentru componente care necesită drivere de testare dificil de implementat
4. Cum testam ? • Pe baza specificaţiei / pe baza implementării
– Specificaţia – intrări – ieşiri corecte (CE?) – Implementarea: algoritm de producere a ieşirilor
corecte (conforme cu specificaţia) (CUM?) – Specificaţii pentru clase, subsisteme, sistem- necesare
în generarea cazurilor de test – Acoperirea specificaţiei: sw face ce trebuie – Acoperirea implementării: sw nu face nimic din ce nu
trebuie să facă – Pentru componentele de risc ridicat: şi testare pe baza
implementării (verificarea fiecărei linii de cod)
• Testarea interacţiunilor între componente: testarea integrării • Erori de interfaţă • Polimorfismul • Tehnici speciale de construire a cazurilor de test pentru
interacţiuni Testarea funcţională (pe bază de specificaţie/ cutie neagră)
• Avantaj: se pot dezvolta cazuri de test înainte de scrierea codului
18
Testarea structurală (pe bază de implementare/ cutie albă) – teste construite pe baza implementării
• Ieşirile cazului de test se determină pe baza specificaţiei, intrările- din analiza codului: valori ce au dus la anumite căi de execuţie în sistem
• avantaj: acoperire îmbunătăţită Adecvarea cazurilor de test
• Testarea completă- imposibilă practic • Cazuri de test pentru situaţiile critice (vieţi omeneşti), şi
pentru utilizările uzuale – adecvarea: testează suficient pentru a fi rezonabil de sigur că va lucra aşa cum se aşteaptă
• Adecvarea se măsoară prin acoperire : – Câte cerinţe din specificaţie sunt testate (ce face) – Cât din sw a fost rulat la executarea unui test (cum
face) 5.Cat testam ?
• Aspecte de luat în vedere: – Durata de viaţă aşteptată a sw – Criticalitatea sw – A nu se confunda cu “ce (piese) testăm”
• Cât testăm= cât de aprofundat testăm o piesă aleasă pentru testare
• Adecvarea: testăm cât costurile de testare sunt acoperite de costurile descoperirii de erori
• Standarde specifice domeniului (producerea medicamente/ mobilă – standarde diferite)
• Acoperirea ar trebui măsurată în primul rând în funcţie de cerinţe
• Acoperirea în funcţie de implementare: – Dacă o porţiune de cod nu a fost executată- ce cazuri
de test lipsesc/ sau dacă sw implementează o funcţionalitate nespecificată
NO TESTING ……………………………EXHAUSTINVE TESTING
19
10. TESTAREA IERARHIILOR DE CLASE De ce se tine cont
• ? cum se testează o subclasă pornind de la testarea superclasei sale (cu metodele din cursurile anterioare)
– Testarea adecvată a subclaselor – Refolosirea cazurilor de test ale superclasei – Implementarea driverelor de testare pentru subclase – PACT: arhitectura paralelă pentru testarea claselor
• Mod de organizare a claselor Tester într-o ierarhie de moştenire
– Testarea claselor abstracte Relatia de mostenire:
• Mecanism de refolosire a codului, în general • Dar: GOOD (good object-oriented design): folosirea
disciplinată a moştenirii (în conformitate cu principiul substituţiei) *
• Folosind principiul substituţiei, moştenirea devine un mecanism de refolosire a interfeţei (vom presupune acest principiu respectat în continuare)
• Considerând principiul substituţiei respectat, mulţimea cazurilor de test ale unei clase reprezintă cazuri de test şi pentru subclase
• Evitarea testelor inutile… • Pentru subclase apar de obicei cazuri de test adiţionale
Cerinţele testării subclaselor • Se testează întâi vârful ierarhiei – pentru interfaţa comună,
apoi se specializează driverul de test pentru fiecare subclasă • Vom presupune iniţial că superclasa a fost testată
20
• Fie D subclasă a clasei C (care a fost deja testată adecvat prin executarea cazurilor de test de către un test driver). Ce trebuie testat în D?
• Cum se extinde testarea din C pentru a testa D? Modalităţi de rafinare a subclasei Modificări incrementale permise în clasa D derivată din clasa C 1. Adaugă una sau mai multe operaţii noi în interfaţa lui D, şi,
eventual, implementează-le (O operaţie nouă poate fi abstractă, lăsând implementarea subclaselor)
2. Modifică specificaţia sau implementarea unei operaţii declarate în C în unul sau două moduri:
– modifică în D specificaţia unei operaţii declarate în C – suprascrie în D o metodă din C (o operaţie moştenită
de D) 3. Adaugă în D una sau mai multe variabile ale instanţei pentru
a implementa mai multe stări şi/sau atribute 4. Modifică invariantul clasei în D.
Presupunem: Moştenirea este folosită doar în concordanţă cu principiul
substituţiei Este respectat principiul ascunderii informaţiei: nici o dată nu
este publică Cazuri necesare pentru testarea subclasei
• Întrucât D moşteneşte o parte din specificaţia sa de la C, toată testarea pe bază de specificaţie folosită în testarea lui C poate fi folosită şi în testarea lui D
– Principiul substituţiei oferă asigurarea că toate cazurile de test se aplică şi pentru D
• Se aplică şi multe din cazurile de test pe bază de implementare şi interacţiuni
21
• Sunt necesare, în plus: – Cazuri de test pe bază de specificaţie adiţionale pentru
operaţiile noi – Posibil- cazuri de test pe bază de specificaţie pentru
operaţiile ale căror precondiţii au fost relaxate sau ale căror postcondiţii au fost întărite
– Cazuri de test pe bază de implementare pentru testarea metodelor noi
– Dacă invariantul clasei a fost rafinat în subclasă, atunci vom avea nevoie de cazuri de teste adiţionale pentru aceste rafinări
Testarea incrementală, ierarhică (HIT) • Modificările incrementale între C şi clasa derivată D pot fi
folosite pentru a identifica ce trebuie testat în D – Ce cazuri de test noi se adaugă pentru D – Ce cazuri de test moştenite trebuie rulate pentru D – Ce cazuri de test moştenite nu mai trebuie rulate
(…posibile capcane) Modificările incrementale prin perspectiva testării 1.o operaţie nouă sau mai multe în interfaţa lui D şi posibil o metodă nouă în D pentru a implementa fiecare operaţie nouă
– O operaţie nouă introduce cod nou şi noi funcţionalităţi de testat; nu afectează direct operaţiile existente/ moştenite
– Sunt necesare cazuri de test pe bază de specificaţie pentru fiecare operaţie nouă
– Dacă operaţia nu este abstractă şi are o implementare, sunt necesare şi cazuri de test ale implementării şi interacţiunilor
22
2. modificarea specificaţiei/ implementării unei operaţii declarate de C în unul sau două moduri:
a. modifică în D specificaţia unei operaţii declarate în C. – Trebuie adăugate cazuri de test noi, pe bază de
specificaţie, pentru operaţie- cu intrări noi (ce corespund precondiţiilor relaxate) şi ieşiri noi- din postcondiţiile întărite
– Cazurile de test asociate cu versiunea din C a operaţiei sunt aplicabile, dar trebuie re-executate
b. Suprascrie în D o metodă din C ce implementează o operaţie moştenită de D
– Se pot refolosi toate cazurile de utilizare pe bază de specificaţie ale metodei
– Trebuie revizuite cazurile de test ale implementării/ interacţiunii
3. Adaugă în D una sau mai multe instanţe de variabile noi pentru a implementa mai multe stări şi/sau atribute
– O variabilă nouă se adaugă de obicei în conexiune cu operaţii noi- testarea se face în cadrul testării operaţiei noi
• Nu trebuie în general să reluăm cazurile de test folosite pentru superclasă
• Totuşi, trebuie re-executate cazurile de test ale unei operaţii dacă metoda sa s-a schimbat indirect deoarece foloseşte o operaţie care s-a schimbat 11. TESTAREA CLASELOR DE TIP COLABORARE
Colaborarea (interacţiunea) corectă între obiecte este critică pentru funcţionarea programului. Clasele de colaborare sunt clasele cu interactiuni mai extinse. Ele sunt clase non-primitive care nu sunt colecţii:
23
• Folosesc obiecte de alt tip în una sau mai multe metode şi ca parte a implementării lor • Exemplu: Clasa BrickPile. Colaborări: – PlayField. O stivă de cărămizi ocupă o parte a câmpului de joc – Hint. O stivă de cărămizi reţine cărămizile sparte într-un “hint”- pentru reactualizarea imaginii – CPoint. Localizarea stivei în câmpul de joc e specificată de un punct ce determină colţul stânga sus – Brick. Stiva creează cărămizi ca parte a propriei construcţii şi înregistrează care cărămizi sunt sparte şi care nu. – MovableSprite. O stivă recunoaşte coliziunile între cărămizile sale şi o minge (element mobil)
12. Testarea sistemelor Se referă la testarea unei aplicaţii complete pentru a verifica dacă oferă toate comportamentele solicitate.
• Vom considera testarea sistemului după fiecare increment ce finalizează o funcţionalitate pentru utilizatori
Vom considera • "sistem” = "aplicaţie” = program + mediul de rulare (sistem
de operare, maşini virtuale, browsere web şi hardware). Testarea este căutarea defectelor, dar nu numai...
• În stadiul testării sistemului se caută mai ales apropierea dintre operarea reală şi cerinţe
• Testarea în stadiul de analiză şi design scade probabilitatea unui comportament diferit de cel aşteptat
Clasificarea Ortogonală a Defectelor (COD) este o tehnică dezvoltată la IBM pentru descoperirea informaţiilor despre tipurile de defecte prezente într-un sistem software în curs de dezvoltare
• O vom folosi pentru selectarea cazurilor de test Construirea profilelor de utilizare:
• Începe cu actorii din diagrama de cazuri de utilizare
24
• Fiecare actor va folosi sistemul într-un anumit fel, cu o anumită frecvenţă pe fiecare caz de utilizare- profilele de utilizare
Folosirea scenariilor pentru construcţia cazurilor de test: • Un caz de utilizare conţine, de obicei, multe scenarii ce pot fi
convertite în cazuri de test • Cazurile de test- din răspunsul normal al sistemului şi din
condiţiile limită Identificarea valorilor specifice ale variabilelor ce apar într-un caz de utilizare:
• Identifică toate valorile ce vor fi furnizate de actorii din model • Identifică clasele de echivalenţă ale valorilor pentru fiecare
tip de dată de intrare • Construieşte tabele cu combinaţii de valori din clasele de
echivalenţă • Construieşte cazuri de test ce combină o permutare a
valorilor cu constrângerile necesare de mediu • Vor fi create cazuri de testare proporţional cu frecvenţa
fiecărui caz de utilizare • O tehnică de estimare a numărului maxim de cazuri de test
este să considerăm numărul de intrări şi numărul de clase de echivalenţă pentru fiecare tip de input şi să le multiplicăm pentru a obţine numărul maxim de permutări:
E1 * E2 * E3 *... * En unde Ei e numărul de clase de echivalenţă pentru intrarea i. Rezultatele aşteptate ale cazurilor de test:
• Uneori sunt foarte dificil/ costisitor de construit Exp: în sistemele de telecomunicaţii, soft de control al rachetelor spaţiale, sisteme de informaţii pentru corporaţii multinaţionale
25
• Pentru fiecare caz de test derivat dintr-un scenariu, trebuie să existe o descriere a rezultatului aşteptat...
• Pentru reducerea numărului de teste necesare pentru a acoperi problema, vom folosi un Sistem de Testare Tabel Ortogonal (STTO)
Ce trebuie testat ? • Testarea Cerinţelor Funcţionale – este abordarea
tradiţională a “testării sistemului”; se bazează pe derivarea cazurilor de test din cazurile de utilizare
• Testarea Atributelor Calitative ale sistemului – Exp: codul va fi refolosibil, sistemul va acoperi mai bine
realitatea decât alte produse similare etc. – Acestea se testează prin Inspecţia Dirijată- examinarea
design-ului, nu prin executarea codului Validarea Cerinţelor Calitative
• Tradu fiecare cerinţă calitativă într-un atribut măsurabil ce variază odată cu/ defineşte atributul calitativ
• Construieşte cazuri de test ce pot depista prezenţa/ absenţa atributului măsurabil de la 1.
• Execută cazurile de test şi analizează rezultatele • Reuneşte rezultatele pentru a verifica cerinţele calitative
Exemplu: cerinţa legată de performanţă- se poate valida prin executarea codului Performanţele bazei de date să rămână acceptabile la o creştere rapidă a numărului de tranzacţii – test de încărcare (load test):
• Cuantifică termenii “performanţă acceptabilă" şi “creştere rapidă"
– Performanţă acceptabilă – cuantificată de numărul de tranzacţii pe secundă, pentru înregistrări de 1024 octeţi
26
– Creştere rapidă cuantificată prin definirea curbei de creştere -, “o creştere patratică pe perioada a 10 minute"
• Testerii creează date noi sau memorează date folosite pentru a le utiliza în teste; se dezvoltă un cadru de testare care să furnizeze numărul maxim de tranzacţii pe secundă ca şi durata serviciilor
• Se rulează testele. Se memorează rezultatele testelor şi datele de temporizare
• Se verifică cerinţa. Tipuri de testare
Testarea stresului • Presupune operarea sistemului în condiţii apropiate de
epuizarea resurselor necesare sistemului – Exemplu: aglomerarea RAM cu obiecte, umplerea
discului cu înregistrări, aglomerarea structurilor de date interne
• Sistemele orientate obiect vor fi de obicei sub stres dacă se creează un număr mare de instanţe ale claselor
• Identificaţi resursele variabile ce pot creşte munca sistemului • Dacă există relaţii între aceste resurse, creaţi o matrice cu
combinaţia nivelelor folosite ale resurselor • Creaţi cazuri de test ce folosesc fiecare combinaţie • Executaţi şi evaluaţi rezultatele Testarea unui ciclu de viaţă • Ciclul de viaţă al unui sistem poate fi mare şi prin urmare
dificil de simulat într-un mediu de testare – Ciclul de viaţă al domeniului – Ciclul de viaţă al aplicaţiei
27
Testarea performanţei Atributele sistemului legate de performanţă variază cu tipul sistemului
– Exemplu: numărul de tranzacţii pe minut, abilitatea de a reacţiona la evenimente individuale suficient de rapid etc.
– În Brickles: viteza de refresh a graficii, viteza de detectarea coliziunilor şi de actualizare a ecranului
Exemple: • Cazurile de test pentru măsurarea ratei de refresh a
graficii folosesc încărcarea maximă a sistemului. • Fiecare caz de test plasează numărul maxim de cărămizi
pe ecran şi apelează la nivele înalte ale inputului: paleta se mişcă înainte şi înapoi foarte rapid- aceasta va produce numărul maxim de calcule şi activităţi de desenare, rezultatul dorit este să nu observăm “licăriri” ale graficii pe ecran iar mişcarea paletei după mouse să fie continuă
• Defineşte contextul în care se aplică măsura performanţei • Descrie starea aplicaţiei de testat • Descrie mediul de execuţie în termenii platformei
utilizate • Descrie celelalte aplicaţii ce rulează la momentul
testelor • Identifică extremele din cadrul acelui context • Defineşte, ca rezultat aşteptat, ce constituie performanţa
aşteptată • Execută testele şi evaluează rezultatele
28
Măsurarea acoperirii testării • Acoperirea este metrica ce indică gradul de încredere în
testare • Ce trebuie acoperit? • Câte intrări/ ieşiri posibile au fost folosite în testare?
Cand e masurata acoperirea? • Datele de acoperire sunt colectate continuu în timpul testării • Fiecare caz de test e selectat pentru un anumit motiv şi
trebuie să fie în mod direct legat de acoperirea unui anumit aspect al sistemului
Cand e folosita acoperirea? • La momentul “livrării" (acoperirea este o parte a criteriilor de
decizie pentru livrare) • Raportul de testare a sistemului asociază nivelul de
acoperire cu calitatea produsului livrat (= procentul defectelor descoperite după livrare).
13. Testarea de baza pe model Model = metodă de reprezentare a comportamentului software Teoria grafurilor în testarea software pe bază de model Probleme cu testarea tradiţională: Paradoxul pesticidelor (Beizer, 1990)-Testele sunt din ce în ce mai puţin eficiente în descoperirea erorilor, întrucât acestea au fost deja fixate Testele tradiţionale trebuie actualizate la modificarea softului Testarea pe bază de model: generează teste din descrierea explicită a aplicaţiei - mai uşor de generat şi menţinut teste utile şi flexibile Graful stărilor =maşina finită de stări- model de reprezentare a comportamentului software
29
Ex: aplicaţia începe într-o stare (“se afişează fereastra principală”), utilizatorul aplică o intrare (“apelează dialogul Help”) şi programul trece într-o stare nouă (“Dialogul Help afişat”). O mare parte din testarea software poate fi privită ca drumul testerului prin stările diferite ale aplicaţiei, cu verificarea corectitudinii fiecărui pas Ce este testarea pe baza de model ?
• În încercarea de a face testarea mai simplă şi mai ieftină, s-a dorit ca testarea să folosească informaţii conţinute în modele explicite (Beizer 1995, Apfelbaum 1997)
• Testarea pe bază de model este o tehnică black-box cu următoarele avantaje asupra testării tradiţionale:
• Construcţia modelelor de comportament poate începe devreme în ciclul de dezvoltare.
• Modelarea descoperă ambiguităţile din specificarea şi design-ul software.
• Modelul cuprinde informaţii comportamentale ce pot fi refolosite în testările viitoare, chiar dacă specificaţia se modifică
• Modelul e mai uşor de actualizat decât o suită de teste individuale
• Modelul furnizează informaţii ce se pot combina cu teoria grafurilor pentru generarea automată a diverselor scenarii de testare
Puncte de reper • Care este lungimea minimală a unui tur prin graf (digraf), cu
muchii direcţionate (arce) (se poate circula doar într-un sens)?
• Ciclu eulerian?
30
• Eulerizarea unui digraf: trebuie să avem un număr de arce ce intră egal cu numărul arcelor ce ies din fiecare nod
• Se numără arcele care intră “+1” şi arcele care ies “-1”, calculându-se polaritatea fiecărui nod în digraf (ex. un nod cu două arce care ies şi unul care intră are polaritatea “ 1 – 2 = -1”. (în figură e afişată polaritatea nodurilor înainte şi după eulerizare)
• Pentru crearea unui digraf eulerian, se duplică arcele între nodurile de polaritate pozitivă şi nodurile de polaritate negativă astfel că toate nodurile vor avea polaritate zero.
• Oricine intră într-un nod printr-un arc de intrare poate ieşi din nod printr-un arc de ieşire .
Testarea combinatiilor de actiuni • Executarea fiecărei acţiuni din model seamănă cu
acoperirea stărilor când testăm codul; dar întrucât există deseori multiple variante de urmat din fiecare nod, ce putem face dacă dorim să testăm combinaţii de acţiuni?
• Testarea combinaţiilor de acţiuni se numeşte “acoperire de switch” în testarea folosind maşini finite de stări
• Există un algoritm simplu în teoria grafurilor -de Bruijn (“de-broyn”) care generează acţiunile corespunzătoare pentru acoperirea switch-urilor (Gross and Yellen 1998)
Secventele de Bruijin • Secvenţele de Bruijn descriu “cea mai scurtă secvenţă
suficientă pentru a verifica toate combinaţiile de lungime n.” (Skiena 1998)
• Secvenţa de Bruijn pentru combinaţii de lungime 2 (toate perechile de acţiuni adiacente) e generată după cum urmează:
31
• 1. Crează graful dual al grafului original (i.e., un graf în care arcele grafului original sunt convertite în noduri)
• 2. Oriunde în graful original intră un arc 1 într-un nod şi un arc 2 iese din nod, crează un arc de la nodul 1 la nodul 2.
Abordarea Dill, Ho, Horowitz &Yang (1995) • Stabileşte o limită superioară a numărului de arce ce pot fi
vizitate într-un singur sub-tur • Algoritmul caută arce nevizitate în graf, vizitând un număr
maxim din acestea, fără să depăşim o limită maximă • Pe măsură ce numărul de arce dintr-un sub-tur se apropie
de limită, algoritmul termină sub-turul, trece în starea “reset” şi începe generarea unui alt subtur
• Algoritmul nu garantează optimul, dar tururile sunt în general eficiente
Drumuri aleatoare • Drum aleator: din nodul curent, alege aleator un arc de
ieşire, urmează arcul respectiv până în nodul adiacent şi repetă procesul
• Lipsa unui plan le face interesante pentru testare, întrucât astfel devin rezistente la paradoxul pesticidelor (au fost folosite cu mare succes în testare la Microsoft)
• Dezavantaj: sunt ineficiente în acoperirea rapidă a unui graf (tind să retraverseze arce prin care au mai fost)
• Lanţurile Markov pot ajuta ghidarea căilor aleatoare prin asignarea de probabilităţi arcelor ce ies din noduri astfel încât, statistic, o cale alatoare este mai probabil să urmeze arcele cu probabilitate mai mare.
Dezavantaj: există încă o doză mare de incertitudine că vom ajunge pe calea dorită
Lanţuri Markov şi teoria grafurilor
32
• Combinăm teoria grafurilor şi probabilităţile lanţurilor Markov pentru a obţine traversări eficiente ale căilor de interes:
1. Asignăm probabilităţi arcelor din graf (ca în lanţurile Markov).
2. Stabilim o probabilitate minimă a căilor de interes, spre exemplu 0.0000001.
3. Începând cu nodul iniţial, înaintaţi prin graf, păstrând probabilitatea cumulativă a arcelor traversate.
4. Continuăm traversarea arcelor din graf până ajungem în nodul final al grafului sau până când probabilitatea cumulativă a drumului urmat scade sub minimul stabilit
5. Dacă am ajuns în nodul final, memorăm calea prin care am ajuns aici şi probabilitatea sa.
6. Dacă am ajuns cu probabilitatea cumulativă sub minimul stabilit, ne întoarcem şi încercăm un alt arc (backtracking).
7. După ce am reţinut toate căile prin graf de probabilitate cumulativă mai mare decât minimul, le sortăm descrescător în ordinea probabilităţilor cumulative.
• Prin testarea mai întâi a căilor de probabilitate mai mare, ne asigurăm că am testat aplicaţia cel mai eficient pentru a asigura validitatea software.
Concluzie • Modelele sunt un mod excelent de reprezentare şi înţelegere
a comportamentului unui sistem, şi oferă o modalitate facilă de actualizare a testelor pentru o aplicaţie ce se modifică şi evoluează constant
• Testarea unei aplicaţii poate fi văzută ca parcurgerea unui drum prin graful modelului; teoria grafurilor ne permite să
33
folosim informaţiile de comportament din modele pentru a genera teste noi şi folositoare
• Întrucât teoria grafurilor abordează direct modelul, – Noi traversări se pot genera automat când se schimbă
modelul – Testele se pot modifica în mod constant folosind
acelaşi model – Diferite tipuri de traversare servesc diferite necesităţi
ale testerilor – Tehnicile de traversare sunt generale şi pot fi refolosite
pe modele diferite
34
Cuprins Testarea si asigurarea calitatii software. Scop si importanta…….1 Testarea intr-un proces iterativ si incremental de dezvoltare…….3 Specificarea claselor. Preconditiile si postconditiile operatiilor. Invarianti. ………………………………………………………………5 Surse de erori in implementarea claselor…………………………..6 Comparati programarea contractuala si programarea defensiva..7 Mostenirea din perspectiva testarii…………………………….……9 Testarea modelului de analiza si design. Diagramele UML- descrierea si utilitatea lor. Analiza riscului ca instrument de testare…….……………………11 Planificarea testarii- testarea proiectului, a componentelor, si standardul de testare IEEE 829…………………………….……..13 Cele 5 dimensiuni ale testarii claselor- descriere detaliata…….15 Testarea ierarhiilor de clase…………………………………….…19 Testarea claselor de tip colaborare……………………………....22 Testarea sistemelor……………………………………………….…23 Testarea pe baza de model………………………………………...28