Explorați Cărți electronice
Categorii
Explorați Cărți audio
Categorii
Explorați Reviste
Categorii
Explorați Documente
Categorii
REFERAT LA DISCIPLINA
TESTAREA SISTEMELOR
NCORPORATE
Profesor Coordonator:
Prof. dr. ing. Nicolae ENESCU
Masterand:
Eduard DRGHICI
CRAIOVA
2016
TESTAREA UNITAR
Profesor Coordonator:
Prof. dr. ing. Nicolae ENESCU
Masterand:
Eduard DRGHICI
CRAIOVA
2016
2
Cuprins
Testarea Unitar
Testarea este necesar si pentru programele scrise ntr-un limbaj static (pentru care se
fac verificri de corectitudine la compilare) dar, mai ales, pentru programe scrise ntr-un
limbaj dinamic si care nu beneficiaz de verificrile efectuate de un compilator.
In cursul dezvoltrii unei aplicatii codul evolueaz (fie datorit modificrii cerintelor, fie
prin reproiectare sau prin refactorizare), dar prin teste ne putem asigura c acest cod
modificat continu s respecte cerintele impuse ( c este corect). Chiar dac scrierea de teste
necesit un efort suplimentar, ele ne permit s avem ncredere c programul va functiona si
dup modificri.
Testarea programelor este bine s se fac pe msura dezvoltrii acestora si nu dup ce
programele au fost scrise. Cu ct mai devreme sunt detectate erorile, cu att e mai bine.
Se pot deosebi urmtoarele tipuri de teste:
- Teste unitare, care verific fiecare unitate de program separat de celelalte (o unitate poate fi
o metod, o clas, o secvent de apeluri de metode).
- Teste de integrare, care verific interactiunile dintre unittile de program (testate separat).
- Teste de sistem, care verific toata aplicatia.
- Teste de acceptare, care verific modul cum programul rspunde cerintelor beneficiarilor.
Testele trebuie s fie rapide, repetabile, izolate si automatizate: rapide pentru a nu
descuraja repetarea testelor dup orice modificare de cod, izolate astfel ca esuarea unui test s
nu aib efecte asupra altor teste, repetabile cu aceleasi rezultate indiferent de rulrile
anterioare ale testului sau de interactiunile firelor de executie concurente din aplicatie,
automatizate pentru
a simplifica executarea lor si analiza rezultatelor.
Chiar dac nu se scriu teste pentru toate metodele din toate clasele aplicatiei, testele
trebuie s acopere prtile cele mai importante si mai sensibile din aplicatie.
Dezvoltarea bazat pe teste (TDD=Test Driven Development) este metodologia n care
testele unitare se scriu nainte de a scrie codul unittilor testate. Scrierea timpurie a testelor
este o activitate de proiectare , deoarece necesit ntelegerea cerintelor si poate conduce la
refactorizrea codului. TDD impune gndirea codului n functie de intentiile lui si nu n
functie de implementare.
4
Teste unitare
Fiecare test unitar (unit test) implementeaza un singur caz de testare;
Unitatile sunt testate independent unele fata de altele;
Pentru fiecare unitate se scriu, in mod uzual, mai multe teste unitare;
Ce facem cu testerii?
O temere ntlnit adesea este c testerii i vor pierde locul de munc o dat cu
introducerea testrii automate. n realitate, testerii devin mult mai importani pentru c acum
doar ei pot descoperi problemele ascunse, greu sau imposibil de gsit prin teste automate. Ei
ajut s creasc probabilitatea c totul funcioneaz corect de la 80+% la aproape 100%.
Testele unitare au cteva caracteristici importante:
Pentru a fi rapide, testele unitare folosesc adesea aa-numitele "duble de testare". La fel
cum piloii de avioane nva ntr-un simulator nainte de a se urca n avion, testele unitare
folosesc buci de cod care seamn cu codul de producie, dar n realitate folosesc doar la
teste. Stub-urile i mock-urile sunt cele mai ntlnite duble de testare, existnd multe altele
mai puin folosite.
Un stub este o dubl de testare care ntoarce valori. Stub-ul este similar cu o simulare
foarte simpl: atunci cnd apei un buton, apare o valoare. n cod, un stub poate arta astfel:
class PaymentProcessorTest{
@Test
public void
paymentDoneWhenPaymentServiceAcceptsPayment(){
7
PaymentServiceStub paymentServiceStub =
new PaymentServiceStub( );
paymentServiceStub.valueToReturn = true;
PaymentProcessor paymentProcessor =
new PaymentProcessor(paymentServiceStub);
paymentProcessor.processPayment(
Money.RON(100));
assertPaymentWasCorrectlyPerformed(
paymentProcessor);
}
}
Un mock este o dubl de testare care valideaz colaborarea ntre clase. Mock-ul
valideaz apeluri de metode, cu anumii parametri, de un anumit numr de ori. Din aceast
cauz, un mock poate fi folosit i la validarea apelurilor de metode care nu ntorc valori.
class PaymentServiceMock
implements PaymentService{
class PaymentProcessorTest{
8
@Test
public void
paymentServiceCalledOnPaymentProcessing(){
PaymentServiceMock paymentServiceMock =
new PaymentServiceMock();
PaymentProcessor paymentProcessor =
new PaymentProcessor(paymentServiceMock);
paymentProcessor.
processPayment(expectedAmount);
assertTrue(paymentServiceMock.payWasCalled);
assertEquals(expectedAmount,
paymentServiceMock.actualAmount);
}
}
Utilizarea de obiecte surogat (Mock Objects)
Majoritatea unittilor de program supuse testelor depind de alti colaboratori care pot fi
unitti locale (alte metode din aceeasi clas), pot fi parametri ai metodelor testate sau pot fi
chiar metode aflate n alt calculator (remote). Pentru a testa unitti cu dependente de alte
unitti trebuie nlocuiti colaboratorii cu obiecte surogat (stub sau mock). Obiectele
surogat se folosesc n testele unitare si vor fi nlocuite cu obiecte reale n testele de integrare.
Crearea de obiecte surogat n Java se poate face n dou feluri:
- Manual, prin scrierea metodelor clasei surogat;
- Automat (dinamic) utiliznd un framework ca EasyMock, JMock, s.a.
Clasa surogat scris manual trebuie s aib aceleasi metode cu clasa pe care o
nlocuieste; acest lucru se poate face prin extinderea clasei colaborator si redefinirea
metodelor sau prin implementarea unei interfete definite n scopul testrii.
In Java, pentru a facilita trecerea de la teste unitare la teste de integrare se folosesc fie
interfete (pentru comunicarea cu obiectele surogat), fie obiecte de tip proxy, care
intercepteaz cererile si le dirijeaz fie ctre obiecte surogat fie ctre obiecte reale.
Schema urmtoare arat o interfat ntre codul testat si codul de care depinde sau codul
surogat (care nlocuieste n teste codul real).
EasyMock este un framework de testare pentru aplicatii Java care genereaz dinamic
clase si obiecte surogat si poate verifica ordinea apelurilor metodelor din obiectul surogat.
Dublele de testare pot fi create i folosind framework-uri speciale, cum ar fi mockito
pentru Java (a fost portat i pe alte limbaje) sau moq pentru .NET.
class PaymentProcessorTest{
@Test
public void
paymentDoneWhenPaymentServiceAcceptsPaymentWithMockitoStub(){
PaymentServiceStub paymentServiceStub =
mock(PaymentService.class);
when(paymentServiceStub.pay(amount)).
thenReturn(true);
PaymentProcessor paymentProcessor =
new PaymentProcessor(paymentServiceStub);
paymentProcessor.processPayment(amount);
assertPaymentWasCorrectlyPerformed(
paymentProcessor);
}
@Test
public void
paymentServiceCalledOnPaymentProcessingWithMockitoMock(){
PaymentProcessor paymentProcessor =
new PaymentProcessor(paymentServiceMock);
paymentProcessor.processPayment(amount);
verify(paymentServiceMock).pay(amount);
}
}
Iniial dublele de testare erau folosite doar n locurile unde era foarte greu s
controlezi sistemul sau unde testele erau ncetinite de apeluri la sisteme externe. n timp,
11
dublele de testare au ajuns s fie folosite n toate testele unitare, dnd natere metodei
"mockiste" de testare unitar.
Testele unitare sunt scrise de programator, n timp ce implementeaz o funcionalitate.
Din pcate, cel mai ntlnit mod de a scrie teste este cndva dup ce a fost terminat
implementarea. Rezultatul este c testele sunt scrise avnd n minte cum ar trebui s
funcioneze codul i nu testarea lui.
Test First Programming este o metod de a scrie teste care implic urmtorii pai:
crearea minimului de cod necesar (compilabil, dac limbajul folosit este compilat) pe
baza design-ului;
scrierea unuia sau mai multor teste care codeaz ceea ce trebuie s fac design-ul;
testele vor pica n acest moment;
Prin aplicarea Test First Programming, programatorii se asigur c scriu teste unitare i c
testeaz ceea ce ar trebui s rezolve, nu implementarea soluiei.
Test Driven Development (TDD) poate fi a treia metod de a scrie teste. De fapt, TDD este o
metod de a face design incremental.
Dureaz mai mult cnd scriu teste!
Studiile de caz i experiena personal a programatorilor a artat c ntr-adevr,
timpul petrecut strict pe dezvoltarea unei funcionaliti crete o dat cu adoptarea unit
testing. Aceleai studii au artat c timpul petrecut pe mentenan scade drastic, artnd ca
unit testing poate aduce o mbuntire net n timpul de dezvoltare.
Acest fapt nu poate schimba percepia programatorului care trebuie s scrie mai mult
cod. De aceea, programatorii presupun adesea c per total proiectul merge mai ncet din
cauza testrii automate.
12
Cum ncep?
Este bine ca adopia unit testing s se fac cu grij, incremental, urmrind cteva puncte
importante:
documentarea din cri (vezi la final crii recomandate), de pe internet sau prin
participarea la evenimente de comunitate.
Testarea automat n primul rnd a celei mai importante pri din aplicaie i apoi a
funcionalitilor cu cel mai mare risc de greeal;
n cazul n care exist mult cod (legacy code), este recomandat nvarea unor tehnici
suplimentare pentru a scrie teste pe cod existent. Mai multe detalii ntr-un articol
viitor.
13
Greeli comune
Cteva greeli comune legate de unit testing sunt:
Scrierea multor teste de integrare(care implic mai multe clase sau module) lente i
fragile n detrimentul testelor unitare mici, rapide i uor de ntreinut
Abandonarea dublelor de testare, sau folosirea lor n scopuri pentru care nu au fost
create. Dublele de testare ajut la obinerea unor teste scurte i rapide.
Folosirea intensiv a debugger-ului pe teste. Testele bine scrise vor spune imediat
unde este problema n cazul n care pic. Debugging-ul este n continuare util n
situaii exotice.
Cod de testare nengrijit. Codul de testare este cel puin la fel de important ca i codul
de producie, i trebuie ntreinut cu aceeai grij.
14
Concluzii
Unit testing-ul (testarea unitar) este una dintre metodele pe care un programator o
poate folosi cu scopul de a reduce numrul de greeli pe care le face cnd scrie cod.
Folosit corect, unit testing-ul poate reduce semnificativ timpul petrecut cu repararea
bug-urilor din aplicaii, reducnd ncrcarea colegilor care se ocup de suport i testare i
permind introducerea de noi funcionaliti mai repede, ceea ce conduce la competitivitate
crescut.
Dar unit testing-ul trebuie adoptat cu grij, urmnd practicile din industrie (piramida
testelor, folosirea dublelor de testare etc). Ajutorul extern (training i coaching tehnic) poate
face diferena ntre o adopie reuit i una cu probleme.
Un software craftsman stpnete unit testing i l folosete atunci cnd e nevoie s se
protejeze de greeli, fie ale sale fie ale colegilor de echip.
Aa este sigur c poate livra software fr bug-uri chiar i atunci cnd e sub presiunea
timpului. Cu condiia, evident, s nvee unit testing att de bine nct s l foloseasc cu
uurin chiar i atunci cnd e sub presiune.
15
Bibliografie
http://www.todaysoftmag.ro/article/377/din-uneltele-artizanului-software-unit-testing
http://mozaicworks.com/blog/5-common-unit-testing-problems/.
16