Calculatoare și Tehnologia Informației [602056]
UNIVERSITATEA TEHNICĂ „Gheorghe Asachi” din IAȘI
FACULTATEA DE AUTOMATICĂ ȘI CALCULATOARE
DOMENIUL: Calculatoare și Tehnologia Informației
SPECIALIZAREA: Tehnologia Informației
Serviciu web pentru gestiune a
sondajelor de opinie
LUCRARE DE LICENȚĂ
Coordonator șt iințific
conf. dr. ing. Elena Șerban
Absolvent: [anonimizat], 2016
DECLARAȚIE DE ASUMARE A AUTENTICITĂȚII
LUCRĂRII DE LICENȚĂ
Subsemnatul(a) GEORGE ALEXANDRU MIRON ,
legitimat(ă) cu CI seria MX nr. 985522, CNP [anonimizat]
autorul lucrării SERVICIU WEB PENTRU GESTIUNE A SONDAJELOR DE OPINIE
elaborată în vederea susținerii examenului de finalizare a studiilor de licență
organizat de către Facultatea de Automatică și Calculatoare din cadrul Universității
Tehnice „Gheorghe Asachi” din Iași, sesiunea IUNIE-IULIE a anului universitar
2015-2016, luând în considerare conținutul Art. 34 din Codul de etică universitară al
Universității Tehnice „Gheorghe Asachi” din Iași (Manualul Procedurilor, UTI.POM.02 –
Funcționarea Comisiei de etică universitară), declar pe proprie răspundere, că această
lucrare este rezultatul propriei activități intelectuale, nu conține porțiuni plagiate, iar
sursele bibliografice au fost folosite cu respectarea legislației române (legea 8/1996) și a
convențiilor internaționale privind drepturile de autor.
Data Semnătura
27.06.2016
Cuprins
Introducere…………………………………………………………………………………………………………………….. 1
1.1. Domeniul și contextul abordării temei ……………………………………………………………………… 1
1.2. Tema propusă……………………………………………………………………………………………………….. 2
Capitolul 2. Proiectarea aplicației ………………………………………………………………………………………. 3
2.1. Avantajele separării serviciilor ………………………………………………………………………………… 3
2.2. Dezavantajele separării serviciilor …………………………………………………………………………… 3
2.3. Schema bloc a aplicației …………………………………………………………………………………………. 4
2.3.1. Baza de date ………………………………………………………………………………………………….. 5
2.3.2. Nivelul de date (DAL – Data Access Layer) ……………………………………………………… 6
2.3.3. Entități (Entities) …………………………………………………………………………………………… 7
2.3.4. Testarea………………………………………………………………………………………………………… 8
2.3.5. Nivelul logic (BLL – Business Logic Layer) ……………………………………………………… 8
2.3.6. Obiecte de transfer (DTOs – Data Transfer Objects) …………………………………………… 9
2.3.7. Nivelul de prezentare ……………………………………………………………………………………… 9
2.3.7.1. De ce AngularJS ? …………………………………………………………………………………… 9
Capitolul 3. Implementarea aplicației ……………………………………………………………………………….. 11
3.1. Crearea bazei de date ……………………………………………………………………………………………. 11
3.2. Crearea nivelului de date ………………………………………………………………………………………. 13
3.3. Crearea nivelului logic …………………………………………………………………………………………. 14
3.4. Crearea nivelului de prezentare ……………………………………………………………………………… 16
3.4.1. Crearea serviciului ASP .NET Web API …………………………………………………………. 16
3.4.2. Crearea aplicației client AngularJS ………………………………………………………………… 19
3.5. Crearea obiectelor de transfer ……………………………………………………………………………….. 23
Capitolul 4. Testarea aplicației …………………………………………………………………………………………. 24
4.1. Testarea unităților ………………………………………………………………………………………………… 24
4.2. Testarea la încărcare …………………………………………………………………………………………….. 28
4.3. Testarea la stres …………………………………………………………………………………………………… 31
Concluzii……………………………………………………………………………………………………………………… 34
Bibliografie………………………………………………………………………………………………………………….. 35
Serviciu web pentru gestiune a sondajelor de opinie
George Alexandru Miron
Rezumat
Tema Serviciu web pentru gestiune a sondajelor de opinie mobilizează interesul datorită
importanței sale în contextul societății actuale. Având în vedere faptul că sondajele de opinie tradiționale,
imprimate pe hârtie, au fost folosite de-a lungul timpului ca mijloc principal de colectare a datelor, există
o serie de probleme care pot afecta validarea rezultatelor. În general este dificil ca hârtiile să fie distribuite
unei mase mari și diversificate de persoane care doresc să participe la un astfel de sondaj.
Conform specialiștilor în domeniu, sondajele online au avantajul de a ajunge la un grup mult mai
larg de persoane și, ca urmare, se poate realiza o analiză mai amănunțită asupra rezultatelor. Acest tip
poate avea efecte benefice atât pentru cei care inițiază sondajul, cât și pentru persoanele care răspund la
întrebări. De exemplu, atunci când o companie consideră oportună aducerea pe piață a unui nou produs
sau serviciu, aceasta trebuie să anticipeze modul în care clienții vor răspunde. Oferirea unui sistem de
votare clienților este o modalitate bună pentru a aduna răspunsurile acestora și de a estima câți oameni ar
cumpăra noul produs sau ar investi în noul serviciu. Aceste rezultate pot oferi o imagine clară asupra
produsului, dacă este sau nu o decizie financiară care poate aduce profit și cum poate fi acesta îmbunătățit
pentru a satisface nevoile potențialilor clienți.
Lucrarea conține trei capitole ce prezintă tema aleasă din punct de vedere teoretic și practic. În
această lucrare sunt prezentate principalele etapele din cadrul procesului de dezvoltare a unei aplicații
web.
Capitolul întâi intitulat „Proiectarea aplicației” conține modul în care trebuie structurată aplicația,
rolul fiecărui modul și cum se integrează acestea. Astfel, se lămurește proiectarea treptată a aplicației și
se analizează avantajele și dezavantajele metodei alese. Sunt ilustrate schema aplicației și diagrama bazei
de date . De asemenea, se stabilește tehnologia aleasă pentru implementare și se justifică alegerea făcută.
Al doilea capitol, „Implementarea aplicației” propune o parcurgere amănunțită a modului în care
este creat codul aferent aplicației proiectate, îndeplinind restricțiile de resurse, acuratețe și performanță
indicate de specificații.
Ultimul capitol, „Testarea aplicației”, conține rezultatele obținute în urma testării și dezvăluie
comportamentul aplicației atât în condiții normale, cât și în contextul supraîncărcării serverului cu un
număr crescut de cereri.
Privirea în ansamblu asupra lucrării permite deprinderea concluziei că un s erviciu web pentru
gestiune a sondajelor de opinie reprezintă o aplicație care necesită întreținere constantă (mentenanță).
Astfel, în cadrul acestei aplicații, utilizatorii vor putea să vizualizeze și să voteze sondajele create de către
un administrator. De asemenea, aceștia vor avea acces la statisticile sondajului și vor putea observa atât
procentajul fiecărei variante de răspuns, cât și numărul de persoane care au votat. Utilizatorii se vor putea
conecta la această aplicație atât de pe desktop, cât și de pe dispozitivele mobile. Pornind de la faptul că
sondajele de opinie reprezintă un obiectiv permanent în societatea actuală, lucrarea de față reprezintă
rezultatul unor căutări pe linia optimizării care dorește o modularizare a aplicației.
Introducere
Introducere
1.1. Domeniul și contextul abordării temei
Sondajele de opinie tradiționale, imprimate pe hârtie, au fost folosite de-a lungul timpului
ca mijloc principal de colectare a datelor. Deși acestea pot fi ușor de creat și administrat, există o
serie de probleme care pot afecta validarea rezultatelor. De exemplu, este dificil ca hârtiile să fie
distribuite unei mase mari și diversificate de persoane care doresc să participe la un astfel de
sondaj. O alternativă a metodei tradiționale de a crea sondaje de opinie este realizarea sondajelor
online.
Această lucrare are ca temă dezvoltarea unei aplicații de gestiune a sondajelor de opinie
folosind servicii web. Am ales această temă deoarece o astfel de aplicație are avantajul de a
ajunge la un grup mult mai larg de persoane și, ca urmare, se poate realiza o analiză mai
amănunțită asupra rezultatelor. În acest moment există o varietate de aplicații care permit crearea
unui sondaj de opinie online. În ciuda numărului mare de aplicații, fiecare dintre acestea prezintă
avantaje și dezavantaje. Dintre acestea se remarcă:
PollDaddy a fost menționată de către directorul comunității The Next Web’ s ca fiind
„regele sondajelor”. Ca lider în industrie, oferă posibilitatea de a crea rapid un sondaj de opinie.
Această aplicație face parte din familia WordPress, răspunsurile fiind colectate prin intermediul
site-ul personal, e-mail, Facebook și Twitter. Există, de asemenea și o aplicație IOS, astfel încât
utilizatorii pot vota de pe iPad. Printre avantajele aplicației PollDaddy se numără faptul că poate
fi legat de rețelele de socializare, este compatibil cu dispozitivele mobile și este ușor de
personalizat. Cu toate acestea, are și dezavantaje: având în vedere dispozitivele mobile, aplicația
este disponibilă doar pentru IOS, necesită un cont WordPress și poate fi greu de configurat dacă
utilizatorii nu sunt obișnuiți cu WordPress. De asemenea, versiunea gratuită este limitată la 10
întrebări și 200 răspunsuri pe lună. Aplicația este disponibilă la adresa https://polldaddy.com.
PollCode.com (http://pollcode.com ) este un site web simplu ce permite crearea rapidă a
unui sondaj sau partajarea unui sondaj personalizat printr-un simplu link. Printre avantajele site-
ului se numără faptul că este ușor de utilizat, iar timpul pentru crearea sondajelor este relativ
scurt. Ca dezavantaje se evidențiază structura simplificată și lipsa unei aplicații ce poate fi
utilizată pe dispozitivele mobile.
Poutsch Voice Polls (https://voicepolls.com ) este este un startup franco-belgian care, spre
deosebire de celelalte aplicații, conține elementele unei rețele de socializare. Crearea unui sondaj
de opinie este simplă, utilizatorii trebuind să-și deschidă un cont gratuit. În această aplicație,
utilizatorii se pot răzgândi după ce au votat și, astfel, își pot schimba răspunsul. Deși oferă o
platformă web completă, Poutsch Voice Polls este lipsită o analiză detaliată a rezultatelor, analiză
de care marile întreprinderi au nevoie. De asemenea, nu există o versiune gratuită, utilizatorul
fiind obligat să plătească atât numărul întrebărilor, cât și cel al răspunsurilor. [1]
99Polls.com (http://www.99polls.com ) este un site web ce permite generarea codului unui
sondaj de opinie pentru un site personal. Printre avantajele site-ului se numără faptul că este ușor
de utilizat, iar timpul pentru crearea sondajelor este scurt. Dezavantajul principal al acestui site
este faptul că utilizatorul trebuie să aibă un site propriu pentru a posta sondajul.
În urma analizării acestor aplicații am constatat că pentru a realiza o aplicație care
permite crearea sondajelor de opinie, aceasta trebuie să fie simplă, cu o interfață intuitivă. De
asemenea, trebuie să fie disponibilă pe un număr cât mai mare de dispozitive (atât mobile, cât și
desktop), astfel încât cât mai mulți utilizatori să poată răspunde întrebărilor propuse. Numărul
ridicat de persoane care răspund în cadrul unui sondaj conduce spre validarea eșantionului și a
rezultatelor.
1
George Alexandru Miron
1.2. Tema propusă
Lucrarea de față își propune dezvoltarea unei aplicații de gestiune a sondajelor de opinie
folosind servicii web. În cadrul acestei aplicații, utilizatorii vor putea să vizualizeze și să voteze
sondajele create de către un administrator. De asemenea, aceștia vor avea acces la statisticile
sondajului și vor putea observa atât procentajul fiecărei variante de răspuns, cât și numărul de
persoane care au votat. Utilizatorii se vor putea conecta la această aplicație atât de pe desktop,
cât și de pe dispozitivele mobile.
Acest tip de sondaj poate avea efecte benefice atât pentru cei care inițiază sondajul, cât și
pentru persoanele care răspund la întrebări. De exemplu, atunci când o companie consideră
oportună aducerea pe piață a unui nou produs sau serviciu, aceasta trebuie să anticipeze modul în
care clienții vor răspunde. Oferirea unui sistem de votare clienților este o modalitate bună pentru
a aduna răspunsurile acestora și de a estima câți oameni ar cumpăra noul produs sau ar investi în
noul serviciu. Aceste rezultate pot oferi o imagine clară asupra produsului, dacă este sau nu o
decizie financiară care poate aduce profit și cum poate fi acesta îmbunătățit pentru a satisface
nevoile potențialilor clienți.
2
Capitolul 2.Proiectarea aplicației
Capitolul 2. Proiectarea aplicației
În cazul programării tradiționale, logica programului este incorporată în rutinele de acces
la date. Astfel, logica programelor este amestecată cu logica de generare a interfeței vizuale,
rezultând un cod dificil de întreținut în cazul aplicațiilor majore. Un alt dezavantaj major al
acestui tip de programare apare în cazul în care există mai multe aplicații care folosesc aceeași
bază de date. În momentul în care se dorește schimbarea unei reguli, logica duplicată va impune
programatorului să o modifice în toate aplicațiile. Acest lucru duce la probleme de distribuție și
poate îngreuna întreținerea aplicației. În cazul în care este necesară modificarea unei metode de
acces la date, va fi necesară rescrierea unei părți semnificative din cod, apoi vor trebui distribuite
noile drivere și DLL-uri1 către utilizatori.
Toate aceste probleme pot fi rezolvate separând aplicația în module. O practică obișnuită
constă în separarea interfeței grafice de logica aplicației, astfel încât interfața grafica să poată
evolua independent de logica aplicației și viceversa. Prin realizarea acestei separări,
dezvoltatorul interfeței grafice va fi scutit de cunoașterea logicii aplicației, astfel putându-se
concentra pe deplin doar asupra dezvoltării interfeței grafice. De asemenea, dezvoltatorul logicii
se va putea concentra doar pe partea de business-logic, ignorând pe deplin elementele grafice.
Modulele aplicației vor fi proiecte de tip Class Project (DLL) și vor conține elemente
diferite. În acest fel, dacă se dorește schimbarea unei reguli, va exista un singur loc unde aceasta
va trebui modificată.
2.1. Avantajele separării serviciilor
În cazul separării serviciilor aplicației în componente individuale se remarcă o
multitudine de avantaje:
✔Clasele din servicii definesc un set standard de proprietăți și metode care pot fi reutilizate în alte
aplicații.
✔Testarea se realizează mai ușor. Fiecare set de servicii se poate testa independent de celelalte. Acest
lucru conduce la o mai bună calitate a codului.
✔Se reduce considerabil cantitatea de cod necesară pentru crearea aplicației client. Prin mutarea logicii
într-un serviciu separat, se realizează mai ușor schimbarea interfeței.
✔Întreținerea centralizată a regulilor și a bazei de date. Dacă este necesară modificarea regulilor de
acces la baza de date, atunci doar serviciul respectiv poate fi modificat, nefiind impusă rescrierea
întregului cod.
2.2. Dezavantajele separării serviciilor
În ciuda avantajelor prezentate, implementarea arhitecturii multi-strat întâmpină și
dezavantaje:
✗În funcție de modul de implementare, apelurile metodelor și proprietăților pot conduce spre o scădere
a performanței.
✗Numărul proiectelor (modulelor) crește. Urmărirea acestora poate deveni greoaie.
✗Dacă se creează câte o clasă pentru fiecare tabel din baza de date, ar putea duce spre o multitudine de
clase. În plus, dacă se realizează proprietăți pentru fiecare coloana din tabel, cantitatea codului crește
considerabil.
✗În cazul în care serviciile sunt implementate pe sisteme distribuite, comunicarea dintre acestea poate
mări timpul de așteptare. Performanța rețelei poate suferi, de asemenea, din cauza traficului realizat
între sisteme.[2]
1O bibliotecă dinamică reprezentată de un fișier executabil care permite programelor să împartă cod și resurse
necesare pentru îndeplinirea anumitor sarcini.
3
George Alexandru Miron
Având în vedere argumentele prezentate în cazul separării aplicației în module, se
observă faptul că avantajele depășesc considerabil dezavantajele. Astfel, pentru dezvoltarea unei
aplicații de gestiune a sondajelor de opinie, cea mai potrivită arhitectură este arhitectura multi-
strat (adesea menționată ca arhitectura „n-tier”). Cea mai utilizată arhitectură multi-strat este
arhitectura pe trei niveluri („three-tier architecture”) Figura 2.1. În cazul în care se va dori
reutilizarea componentelor acestui proiect, nu va fi necesară copierea codului sau a fișierelor,
simpla referențiere a DLL-urilor folosite va fi suficientă.
2.3. Schema bloc a aplicației
Figura 2.2 exemplifică atât principalele module ale aplicației de gestiune a sondajelor de
opinie, cât și modul în care acestea comunică între ele.
4 Figura 2.1: Arhitectura pe trei niveluri
Figura 2.2: Schema bloc a aplicației
Capitolul 2.Proiectarea aplicației
2.3.1. Baza de date
Baza de date va fi creată folosind Microsoft SQL Server Management Studio. Schema
bazei de date este reprezentată în Figura 2.3. Tabela „User” va conține informațiile utilizatorilor.
Fiecare utilizator va avea un identificator unic (userID), un nume, o parolă, o adresă de email și
un rol (user sau admin). Coloana „Verified” va fi un câmp predefinit cu șirul de caractere „no” în
momentul în care un utilizator creează un cont. Atunci când acesta va accesa adresa trimisă prin
email, contul va fi verificat. Fiecare user va avea un identificator unic (token) pe care îl va folosi
pentru trimiterea cererilor către server.
Sondajele de opinie create vor fi stocate în tabela „Form”. Tabela va conține și date
referitoare la categoria din care face parte un sondaj, titlul, data publicării, data la care va expira
și starea sondajului (deschis sau închis). Întrebările și răspunsurile vor fi stocate în tabelele
„Question” și „Answer”.
Atunci când un utilizator votează un sondaj, aceste date sunt reținute în tabela
„VotedForms”. Dacă un sondaj este șters, se vor șterge înregistrările aferente din această tabelă.
Același efect are și ștergerea unui utilizator.
5Figura 2.3: Schema bazei de date
George Alexandru Miron
2.3.2. Nivelul de date (DAL – Data Access Layer)
Nivelul de date va fi nivelul responsabil de comunicarea cu o colecție de informații.
Acesta va conține metodele de creare, citire, actualizare și ștergere, gestionarea tranzacțiilor,
coroborarea datelor, precum și un mecanism de interogare, pentru a permite nivelului logic să
preia obiecte după diferite criterii. De asemenea, nivel de date nu trebuie să conțină operații de
logică, ci trebuie să fie accesat de nivelul logic prin intermediul intefețelor. Astfel se respectă
principiul separării responsabilităților („Separation of concerns principle”) și se asigură faptul că
nivelul logic rămâne în legătură cu strategia de implementare din nivelul de date.
Maparea relațional-obiectuală sau obiectual-relațională sau O/RM este o tehnică de
programare care leagă bazele de date de limbajele de programare orientate-obiect, creând o bază
virtuală de obiecte. Două dintre cele mai importante framework-uri (eng.) O/RM pentru
platforma .Net sunt NHibernate și ADO .Net Entity Framework .
Nhibernate este o soluție de mapare relațional-obiectuală pentru platforma .Net ce
asigură un framework pentru maparea unui model orientat obiect pe o bază de date relațională.
Acesta reprezintă o portare pe platforma .Net a soluției Java Hibernate. Hibernate rezolvă
problema „object-relational impedance mismatch”, problema ce apare atunci când un sistem de
gestiune al bazelor de date relaționale este folosit de un program scris într-un limbaj de
programare orientat obiect.
Soluția pe care o voi folosi este cea oferită de Microsoft, ADO .Net Entity Framework
(Figura 2.4). Acesta este un framework open source de mapare relațional-obiectuală pentru
platforma .Net.
Per ansamblu este un set de tehnologii în ADO .Net ce susține dezvoltarea de aplicații
software orientate pe date. Arhitecții și dezvoltatorii de aplicații orientate pe date s-au străduit să
atingă doua obiective foarte diferite:
•să modeleze entitățile, relațiile și logica de bussiness a problemei pe care o rezolvă;
•să lucreze cu motorul de date folosit pentru a stoca și regăsi datele;
Acest framework le permite să lucreze cu date sub forma unor obiecte și proprietăți
specifice domeniului, cum ar fi clientul, sau adresa clientului fără să fie preocupați de tabelele
care stau la baza bazei de data sau coloanele unde vor fi stocate aceste date. Astfel dezvoltatorii
pot lucra la un nivel superior de abstractizare a datelor și pot crea și întreține aplicații orientate
pe date cu mai puține linii de cod decât aplicațiile tradiționale. ADO.Net Entity Framework
foloseste o variantă de limbaj structurat de interogare denumit Entity SQL ce a fost creat pentru
6 Figura 2.4: Entity
Framework
Capitolul 2.Proiectarea aplicației
a scrie interogări și update-uri asupra entităților și relațiilor la nivel conceptual .[3] Avantajul
folosirii ADO.Net Entity Framework îl reprezintă eliberarea dezvoltatorului de structura bazei
de date. Întregul acces la baza de date și stocarea datelor se face prin intermediul unui model de
date conceptual care reflectă propriile entități. [4]
În cadrul acestui nivel se vor regăsi clasele pentru maparea tabelelor din baza de date,
contextul și repository-urile. Un repository reprezintă o interfață care înglobează totalitatea
acțiunilor ce se pot efectua asupra unei entități din baza de date.
2.3.3. Entități (Entities)
Entitățile reprezintă un model conceptual al unei baze de date fizice. [5] O entitate
reprezintă o tabelă stocată în baza de date. Fiecare instanță a clasei corespunde unei înregistrări
din tabela. Relațiile cu alte entități sunt exprimate prin metadate obiectual/relaționale.
La baza Entity Framework-ului stă Entity Data Model (EDM). Acesta se vrea a fi
limbajul comun între structurile de date și modelele de prezentare. EDM-ul definește un limbaj
menit să descrie datele fără să trebuiască să descrie modul de stocare al acestuia. Deasupra
EDM-ului lucrează un set de servicii care permit manipularea datelor, spre beneficiul întregii
aplicații. Cu ajutorul EDM putem defini entități, relații între ele, precum și colecții de entități.
Sunt suportate diverse scenarii, precum ierarhia, scheme stea, tabele universale și altele.
Definițiile de entități sunt denumite modele conceptuale și sunt păstrate în format XML.
În plus, EDM-ul oferă un limbaj schematic pentru a descrie modul în care datele sunt
stocate. Acesta se numește StorageModel. Modelul de stocare oferă posibilitatea de a defini
scenarii simple, precum acela de a crea câmpuri și tabele, dar și scenarii mai complexe, precum
specificarea unor query-uri sau proceduri stocate pentru salvarea sau obținerea datelor. Tot acest
model este salvat în format XML.
Între aceste două modele acționează o schemă de mapare ( Figura 2.5) care informează
Entity Framework-ul despre cum să mapeze proprietățile entităților la câmpurile structurii de
date. Entitățile folosite vor fi tabelele stocate în baza de date.
7Figura 2.5: Maparea tabelelor
George Alexandru Miron
2.3.4. Testarea
Se remarcă două modalități de a efectua testarea aplicației:
1.testarea manuală a fiecărei funcționalități;
2.testarea automată începând la cel mai de jos nivel (unit testing).
Unit testing-ul reprezintă procedeul de testare a unităților elementare din program. În
abordarea orientată obiect, acestea reprezintă metodele unei clase. Ideea este izolarea fiecărui
modul de funcționalitate a unui program și asigurarea corectitudinii individuale. În afară de unit
testing, se mai intalnesc:
•integration testing (analizează comunicarea între mai multe module)
•acceptance testing (reprezintă testele beneficiarului produsului, la nivelul specificației).
În cazul testării unităților elementare se remarcă o multitudine de avantaje:
✔Înlesnește schimbările: o dată scrisă, suita de teste poate fi rulată la fiecare modificare a
codului sursă, pentru a investiga apariția unor bug-uri la adăugarea de funcționalitate
(regression testing).
✔Simplifică integrarea modulelor, prin asigurarea validității individuale.
✔Documentează funcționalitatea: testele oferă exemple de utilizare a modulului pentru
dezvoltatorii nefamiliarizați.
✔Reprezintă o modalitate de design: testele pot fi scrise înaintea implementării, fapt ce
garantează înțelegerea funcționalității de către dezvoltator.
✔Încurajează proiectarea modulară: crearea unor unități mici ce pot fi testate individual. [6]
8 Figura 2.6: Ciclul Unit Testing
Capitolul 2.Proiectarea aplicației
2.3.5. Nivelul logic (BLL – Business Logic Layer)
Nivelul logic va coordona aplicația, va procesa comenzile, va efectua decizii, evaluări
logice, validări și va realizea calcule. De asemenea, va asigura comunicarea între nivelul de
prezentare și nivelul de date, acționând precum o interfață între celelalte două. Întreaga logică a
aplicației, toate acțiunile de care un utilizator are nevoie, va fi înglobată în acest nivel. Aici vor fi
implementate regulile de validare la nivel de aplicație. Acest strat se va ocupa cu transferul și
procesarea datelor între cele două straturi care îl vor încadra.
Scopul de a separa logica este dublu. În primul rând, apare câștigul de performanță
obținut prin lăsarea serverului de date să se ocupe strict de stocarea și extragerea datelor. În al
doilea rând, ușurăm mentenanța și sporim posibilitatea reutilizării codului.
Logica principală a aplicației va comunica cu stratul superior prin obiecte de tipul Data
Transfer Object.
2.3.6. Obiecte de transfer (DTOs – Data Transfer Objects)
Obiectele de transfer sunt obiecte care vor fi utilizate pentru a îngloba date și pentru a le
trimite de la un modul la celălalt. Principalul avantaj este faptul că acestea reduc volumul de date
care trebuie transmis. De asemenea, sunt vor fi utilizate pentru a transmite parametrii metodelor,
în cazul în care numărul acestora este crescut.
2.3.7. Nivelul de prezentare
Acest nivel va acționa ca punctul de intrare în aplicație și va reprezenta interfața cu
utilizatorul. Acesta va interacționa direct cu nivelul logic.
În cazul de față, rolul nivelului de prezentare este însușit de serviciul web. Un serviciu
web reprezintă orice serviciu disponibil pe Internet, care folosește un sistem de mesaje
standardizat și care nu este legat de nici un sistem de operare. ASP .NET Web API este un
framework care permite construirea serviciilor HTTP, care ajunge la o gama largă de clienți,
inclusiv browsere, dispozitive mobile și tablete. Acesta este un model Web unificat de dezvoltare
care include resursele necesare pentru construirea rapidă a serviciilor web . [7]De asemenea,
acesta facilitează crearea unei aplicații REST.
Acesta va face legătura între aplicațiile de tip client și nivelul logic. La acest serviciu se
vor putea conecta o diversitate de clienți, folosind orice .platformă. Aplicația client va fi creată
folosind AngularJS. AngularJS este un framework JavaScript open-source dezvoltat de Google.
Acesta oferă dezvoltatorilor JavaScript o abordare foarte structurată pentru dezvoltarea
aplicațiilor complexe, bazate pe browser, ceea ce duce la o mare productivitate. [8]
2.3.7.1. De ce AngularJS?
✔AngularJS este un framework JavaScript open-source care ușurează dezvoltarea
aplicațiilor web.
✔AngularJS standardizează aplicațiile la nivel de client (browser), oferind o structură
robustă și ușor de implementat în dezvoltarea site-urilor.
✔AngularJS este alegerea potrivită pentru orice aplicație web, în special dacă se preferă
efectele vizuale spectaculoase. Rezultatul este un site fluid și rapid. Acesta este motivul
pentru care se pretează SPA-urilor (Single Page Application) și aplicațiilor web destinate
dispozitivelor mobile.
9
George Alexandru Miron
✔AngularJS se integrează ușor cu Bootstrap, permite crearea de aplicații responsive care
pot fi accesate atât din browserul calculatorului cât și de pe dispozitivele mobile.
✔Astfel, este ușor să creezi o singură aplicație web care să se vadă perfect pe orice
dispozitiv de pe care este accesată – PC, tabletă, telefon, smartTV.
Structura aplicațiilor dezvoltate cu Angular este intuitivă și framework-ul este suficient
de flexibil pentru a ușura și a crește viteza de dezvoltare a proiectelor. Platforma impune un mod
de dezvoltare după o structură MVVM (Model View View Model), design pattern care preia
modularitatea din conceptele MVC și face extrem de ușoară integrarea template-urilor HTML cu
procesările ce se fac pe Javascript (prin two-way data-binding).
Modulele create la nivel de Javascript în Angular sunt ușor de integrat căci framework-ul
vine cu capacitatea de injectare a dependințelor, ceea ce contribuie și la scalabilitatea codului.
Viteza de încărcare a paginilor este mică întrucât majoritatea comunicației cu serverul este
asincronă iar apelurile la server sunt reduse, majoritatea interfeței vizuale fiind mutată pe client
(în browser).
AngularJS permite crearea de aplicații responsive și îmbunătățeste experiența
utilizatorului pe site datorită platformei sale flexibile, poate fi ușor integrată cu alte framework-
uri de testare automată (Enterprise-level Testing – Unit Testing) precum și cu framework-uri de
design la nivel de UI. [9]
10 Figura 2.7: Structura Two-Way Data-Binding
Capitolul 3.Implementarea aplicației
Capitolul 3. Implementarea aplicației
3.1. Crearea bazei de date
Baza de date a fost creată folosind Microsoft SQL Server Management Studio. SQL
Server este un DBMS (Data Base Management System) produs de Microsoft. Microsoft SQL
Sever folosește o variantă de SQL numită T-SQL, sau Transact-SQL, o implementare de SQL-92
(standardul ISO pentru SQL) cu unele extensii. T-SQL în principal adaugă sintaxă adițională
pentru procedurile stocate și pentru tranzacții. [10] Standardele SQL necesită ACID – patru
condiții pentru orice tranzacție – sintetizate prin acronimul ACID: atomicitate, consistență,
izolare, durabilitate. MS SQL Server suportă ODBC (Open Database Connectivity). Gestionarea
serverului se face foarte ușor prin aplicația SQL Server Management Studio.
Atunci când un utilizator votează un sondaj, aceste date sunt reținute în tabela
„VotedForms”. Dacă un sondaj este șters, se vor șterge înregistrările aferente din această tabelă.
Același efect are și ștergerea unui utilizator. Pentru a evita ștergerea în cascadă atât a sondajului,
cât și a utilizatorului, tabela are o singură cheie străină („FormID”). În acest caz a fost creat un
trigger pe tabela „User”( Figura 3.1). Acesta așteaptă ștergerea unui utilizator și elimină din
tabela „V otedForms” sondajele votate de către utilizatorul respectiv.
Întreaga bază de date locală a fost mutată pe serverul Microsoft SQL Azure. Pașii
parcurși sunt ilustrați în Figura 3.3, Figura 3.2, Figura 3.5, Figura 3.4 și Figura 3.6
11Figura 3.1.: Trigger din tabela User
Figura 3.2: Alegerea opțiunii pentru exportarea datelor
Figura 3.3: Alegerea bazei de date care va fi mutată
George Alexandru Miron
12 Figura 3.4: Alegerea destinației
Figura 3.5: Alegerea metodei de copiere a datelor
Figura 3.6: Selectarea tabelelor care vor fi mutate
Capitolul 3.Implementarea aplicației
3.2. Crearea nivelului de date
Crearea nivelului de date începe cu instalarea ADO .Net Entity Framework. Pentru
stabilirea conexiunii cu baza de date se adaugă în fișierul App.config setările pentru conectare.
Folosind opțiunea „Reverse Engineer Code First” din Entity Framework ( Figura 3.7) se
generează entitățile, clasele pentru maparea tabelelor și contextul bazei de date. Entitățile sunt
clase, fiecare reprezentând corespondența unui tabel din baza de date ( Figura 3.8).
Pentru fiecare entitate este necesară definirea operațiilor care vor fi efectuate asupra
tabelelor corespunzătoare. Folosind șablonul Repository a fost creat un strat de abstractizare între
nivelul de acces la date și nivelul de logica. Toate repository-urile sunt derivate dintr-o clasă
generală (GenericRepository ) care implementează o interfață ce definește funcțiile CRUD
(creare, citire, actualizare și ștergere). Fiecare repository va implementa în plus doar operațiile
specifice. Se creează o nouă clasă ( AzureDataAccess) care va conține câte o instanță din fiecare
repository și va fi folosită de nivelul logic pentru efectuarea operațiilor dorite. Figura 3.9
ilustrează ierarhia claselor și a interfețelor din nivelul de date.
13Figura 3.7: Reverse Engineer Code First
Figura 3.8: Entități
Figura 3.9: Ierarhia repository-urilor
George Alexandru Miron
3.3. Crearea nivelului logic
Întreaga logică a aplicației, toate acțiunile de care un utilizator are nevoie, este înglobată
în acest nivel. În cadrul nivelului logic ( Figura 3.10) sunt create clasele pentru logica de
autentificare a utilizatorilor, logica sondajelor, a categoriilor și a utilizatorilor. De asemenea, sunt
implementate și metodele pentru expedierea mesajelor. Clasa BusinessLogic conține câte o
instanță din fiecare clasă componentă.
O clasă prezentă în Business Logic Layer este AuthLogic care se ocupă de logica de
autentificare și înregistrare. Metodele care aparțin acestei clase sunt:
•private int Validate(string username, string password)
Această metodă verifică dacă în baza de date există un tuplu ce corespunde cu datele
introduse.
•public string Authenticate( string username, string password)
Această metodă apelează metoda Validate. Dacă userul și parola corespund, se
actualizează tokenul în baza de date și se întoarce noul token.
•public string Register(string username, string password, string
email)
Această metodă verifică disponibilitatea numelui, a parolei și a email-ului introduse
de către un nou user în baza de date.
•public bool VerifyTokenDate( string tokenString)
Această metodă verifică tokenul din baza de date. În cazul în care nu există sau este
expirat aruncă o eroare. Altfel se actualizează data de expirare a tokenului.
Figura 3.11 și Figura 3.12 ilustrează modul în care atât serverul, cât și clientul
gestionează cererile de autentificare. În cazul în care un client dorește să se autentifice, acesta va
trimite către server username-ul și parola. Serverul verifică dacă datele trimise se regăsesc în
baza de date. Dacă sunt valide, se creează un token (eng.) cu durata de valabilitate 3 ore pe baza
username-ului, parolei, identificatorului unic, data, adresa MAC a serverului și se actualizează în
baza de date. De asemenea, este extras și rolul userului. Tokenul și rolul userului sunt trimise
către client.
În cazul în care datele nu sunt valide se răspunde cu un mesaj conținând codul de eroare
(403 – Forbidden).
14 Figura 3.10: Structura nivelului logic
Capitolul 3.Implementarea aplicației
După primirea răspunsului, clientul va reține într-un cookie tokenul și rolul. Tokenul va fi
folosit pentru operațiile viitoare, fără a fi necesară retrimiterea la server a username-ul și a
parolei. Dacă userul va efectua o acțiune, va trimite tokenul în header. Serverul verifică tokenul.
În cazul în care acesta este expirat sau este invalid, serverul respinge cererea și obligă clientul să
se autentifice.
15Figura 3.11: Diagramă UML Logică Server autentificare
Figura 3.12: Diagramă UML Logică Client autentificare
George Alexandru Miron
În cazul în care un utilizator va dori să se înregistreze, acesta va trebui să completeze un
formular și vor fi trimise către server username-ul, parola și email-ul dacă acestea au fost
validate. Utilizatorul va primi un mail conținând o adresă de validare a contului. Dacă această
adresă va fi accesată, contul va fi validat, fiind setată coloana Verified cu valoarea yes, urmând
ca utilizatorul să fie logat automat.
3.4. Crearea nivelului de prezentare
3.4.1. Crearea serviciului ASP .NET Web API
Acest nivel reprezintă punctul de intrare în aplicație și interacționează direct cu nivelul
logic. Pentru crearea serviciului web se folosește framework-ul ASP .NET Web API (Figura
3.13). Tipul de autentificare este No Authentication deoarece acest modul este creat separat.
În cadrul acestui serviciu se primesc cererile utilizatorilor, se analizează și se întorc
răspunsurile corespunzătoare. Cererile sunt de tipul http://host/controller/parameter. În funcție
de verbul HTTP, numele controller-ului și parametrii primiți în cerere, serviciul va ști ce metodă
să apeleze și ce parametri să folosească. În Figura 3.14 sunt enumerate controllere-le care
gestionează cererile primite.
16 Figura 3.13: Creare serviciu Web API
Figura 3.14: Structura claselor de tip
Controller
Figura 3.15: Structura claselor de
tip Model
Capitolul 3.Implementarea aplicației
Fiecare controller folosește funcțiile definite în clasele de tip Model ( Figura 3.15). Aceste
funcții apelează metodele create și implementate în cadrul nivelului logic ( Figura 3.16).
Conform principiului Inversiunii dependențelor, clasele de nivel înalt nu trebuie să
depindă de clasele de nivel scăzut. Ambele trebuie să depindă de abstracțiuni. În plus, principiul
precizează și faptul că abstractizarea nu trebuie să depindă de detalii, ci detaliile trebuie să
depindă de abstractizare. Acest principiu este foarte important pentru reutilizarea componentelor
software. De asemenea, aplicarea corectă a acestui principiu face ca întreținerea codului să fie
mult mai ușor de realizat. Pentru a pune în practică acest lucru, la fiecare nivel, care accesează
funcționalitate dintr-un nivel inferior, a fost adăugată o interfață care este implementată de
nivelul inferior. În acest fel interfața prin care două niveluri comunică este definită în nivelul
superior. Dependența a fost inversată, astfel încât nivelul inferior depinde de cel superior.
Pentru a inversa dependența între clasa AuthLogic și AuthModel trebuie eliminată
inițializarea obiectului care va apela baza de date ( DataAccess). Astfel, acesta va fi primit ca
parametru din clasa AuthLogic.
public AuthLogic(IAzureDataAccess objDataAccess)
{
_dataAccess = objDataAccess;
}
În acest caz, trebuie creat un container care să dețină toate obiectele de tip DataAccess și
să decidă în momentul apelării ce obiect va fi trimis către AuthLogic. Acest lucru se rezolvă
folosind clasa UnityContainer din biblioteca Microsoft.Practices.Unity.
public AuthModel()
{
IUnityContainer objContainer = new UnityContainer();
objContainer.RegisterType<BusinessLogic. BusinessLogic>();
objContainer.RegisterType<AzureDataAccess. IAzureDataAccess,
AzureDataAccess.AzureDataAccess>();
bl = objContainer.Resolve<BusinessLogic. BusinessLogic>();}
17Figura 3.16: Apelarea funcțiilor între nivelurile aplicației
George Alexandru Miron
Securitatea browser-ului împiedică o pagină web de a face cereri de AJAX către un alt
domeniu. Această restricție se numește same-origin policy și împiedică un site rău intenționat să
aibă acces la citirea datelor pe un alt site. Cu toate acestea, uneori, este necesară permiterea unor
site-uri să aibă acces la un serviciu. Schimbul de resurse (Cross Origin Resource Sharing) este un
standard W3C, care permite unui server să relaxeze same-origin policy . Cu ajutorul CORS, un
server poate permite în mod explicit unele cereri în timp ce respinge altele. CORS este mai sigur
și mai flexibil decât tehnicile anterioare, cum ar fi JSONP. Această problemă se rezolvă prin
instalarea Microsoft.AspNet.WebApi.Cors . De asemenea, în fișierul WebApiConfig.cs trebuie
inițializate setările:
var cors = new EnableCorsAttribute ("http://votemypoll.azurewebsites.net" , "*", "*");
config.EnableCors(cors);
Pentru configurarea serviciului astfel încât să comunice prin mesaje de tip JSON se
adaugă în același fișier:
config.Formatters.Remove(config.Formatters.XmlFormatter);
config.Formatters.JsonFormatter.SupportedMediaTypes.Add( new
MediaTypeHeaderValue ("application/json"));
Pentru a preveni utilizatorii rău intenționați să apeleze metodele serviciului, s-a creat o
serie de filtre (Figura 3.17) care verifică drepturile fiecărui client și se decide cine poate avea
acces la informații și cine nu.
RequireAdminToken verifică token-ul primit în header și decide dacă acesta aparține unui
utilizator cu rolul de admin. În cazul în care tokenul este invalid, serverul r ăspunde cu un mesaj
conținând codul de eroare (403 – Forbidden).
RequireAdminTokenOrUsername verifică token-ul primit în header și decide dacă acesta
aparține unui utilizator cu rolul de admin sau unui utilizator care a creat sondajul curent. Acest
filtru se aplică asupra metodelor de ștergere a sondajelor de opinie. Acestea pot fi șterse doar de
către un utilizator cu rolul de admin sau de către utilizatorul care a creat sondajul.
RequirePasswordForScheduler verifică dacă cererea primită conține în header o variabilă
cu o anumită valoare. Acest filtru se aplică metodei de actualizare a bazei de date. La un anumit
interval de timp, Microsoft Azure este setat să trimită o cerere către serviciu pentru ca acesta să
elimine din baza de date conturile utilizatorilor neactivați și să marcheze sondajele expirate ca
fiind închise.
RequireAdminToken verifică token-ul primit în header și decide dacă acesta aparține unui
utilizator, oricare ar fi rolul acestuia. În cazul în care tokenul este invalid, serverul r ăspunde cu
un mesaj conținând codul de eroare (403 – Forbidden).
18 Figura 3.17: Lista filtrelor folosite
Capitolul 3.Implementarea aplicației
3.4.2. Crearea aplicației client AngularJS
Pentru crearea aplicației client folosit framework-ul JavaScript AngularJS. Acesta este
utilizat în proiecte de tip Single Page Application (SPA) și extinde HTML DOM cu atribute
suplimentare, devenind mai receptiv la acțiunile utilizatorului. AngularJS este open source,
complet gratuit și folosit de mii de dezvoltatori din întreaga lume.
Se creează un nou proiect de tipul ASP .NET Empty Web Site (Figura 3.18), apoi se
instalează bibliotecile bootstrap, AngularJS Core, AngularJS Resource, AngularJS Route,
Chart.JS și jQuery (Figura 3.19).
19Figura 3.18: Creare client AngularJS
Figura 3.19: Adăugare biblioteci în aplicația client
George Alexandru Miron
Bootstrap reprezintă cel mai popular framework HTML, CSS și JS pentru dezvoltarea
aplicațiilor disponibile pe dispozitive de toate formele și a proiectelor de toate dimensiunile.
Bootstrap ajută la dezvoltarea front-end, aceasta fiind mai rapidă și mai ușoară. Biblioteca
AngularJS Core conține fișierele angular.js, angular.min.js, angular.min.js.map și
angular.mocks.js. Acestea, împreună cu AngularJS Resource sunt fișiere de bază pentru un
proiect AngularJS. Biblioteca Chart.JS conține elemente care sunt folosite în crearea graficelor
care indică rezultatele sondajelor de opinie.
Aplicația AngularJS se bazează în principal pe controlere pentru a controla fluxul de date.
Un controler este definit folosind directiva ng-controller. Un controller este un obiect JavaScript
care conține atribute / proprietăți și funcții. Fiecare controller acceptă variabila $scope ca
parametru. Aceasta se referă la aplicația / modulul pe care controller-ul o va controla. Figura 3.20
ilustrează lista controllere-lor folosite în cadrul aplicației.
Un controller se declară folosind directiva ng-controller:
<div ng-controller="UserController as ctrl">
…
</div>
În continuare se definește controllerul UserController la fel ca un obiect JavaScript,
având ca argument variabila $scope. Acest controller folosește modulele userResource și
cookies, astfel acestea au fost adăugate înainte de funcția principală.
(function () {
"use strict";
angular
.module("userManagement")
.controller( "UserController", ["userResource","$cookies", "$rootScope",
UserController]);
function UserController(userResource,$cookies, $rootScope) {
…
}
}());
20 Figura 3.20: Lista controllere-lor
folosite
Capitolul 3.Implementarea aplicației
În cadrul aplicației AngularJS directivele se utilizează pentru a extinde limbajul HTML.
Acestea sunt atribute speciale care încep cu prefixul ng-.
•Directiva ng-app indică punctul de start al aplicației. Ea definește elementul rădăcină.
Acesta inițializează automat aplicația atunci când pagina web care conține aplicația este
încărcată. De asemenea, este folosită pentru a încărca diverse module AngularJS.
•Directiva ng-init inițializează datele din cadrul aplicației. Este folosit pentru a pune
valorile variabilelor care urmează să fie utilizate.
•Directiva ng-model definește modelul / variabila care urmează să fie utilizat / utilizată în
aplicație.
•Directiva ng-repeat repetă elemente HTML pentru fiecare obiect dintr-o colecție.
Pentru a trimite cereri către server, clientul trebuie să cunoască locația serviciului, trebuie
să stabilească modul prin care creează cererea și ce date sunt transmise. Locația serviciului se
adaugă în fișierul common.services.js :
(function () {
"use strict";
angular
.module("common.services", ["ngResource"])
.constant("appSettings",
{
serverPath: "http://pollwebapi.azurewebsites.net"
});
}());
Modul prin care se creează cererile este stabilit în fișierele din folderul common. Liniile
de cod prezentate mai jos indică aplicației faptul că atunci când utilizatorul dorește să apeleze
funcția de înregistrare, clientul trebuie să trimită o cerere de tip POST către locația
http://pollwebapi.azurewebsites.net/api/registration, atunci când dorește să apeleze funcția de
logare, să trimită o cerere de tip POST, având ca header 'Content-Type': 'application/x-www-
form-urlencoded' către locația http://pollwebapi.azurewebsites.net/api/auth .
(function () {
"use strict";
angular
.module("common.services")
.factory("userAccount", ["$resource", "appSettings","$cookies", userAccount])
function userAccount($resource, appSettings, $cookies) {
return {
registration: $resource(appSettings.serverPath + "/api/registration" , null,
{
'registerUser': { method: 'POST' }
}),
login: $resource(appSettings.serverPath + "/api/auth", null,
{
'loginUser': {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
transformRequest: function (data, headersGetter) {
var str = [];
21
George Alexandru Miron
for (var d in data) {
str.push(encodeURIComponent(d) + "=" +
encodeURIComponent(data[d]));
}
return str.join("&");
}
}
})
Funcțiile sunt apelate din cadrul controllere-lor. Astfel, pentru trimiterea cererii de logare
se va apela funcția:
userAccount.login.loginUser(vm.userData,
function(response) {
…
},
function(error) {
…
});
3.5. Crearea obiectelor de transfer
Serviciul Web și aplicația client comunică prin mesaje Json. În cadrul acestor mesaje sunt
codificate obiecte de transfer definite atât la server, cât și la client. Serializarea reprezintă
procesul de conversie a unui obiect într-o secvență lineară de octeți care poate fi stocată sau
transferată. Deserializarea este procesul de conversie a unei secvențe de octeți serializate
anterior într-un obiect. [11] În acest context codificarea se realizează automat, serviciul Web
convertind la momentul trimiterii răspunsului orice tip de date la tipul string.
json = new JSendMessage("success", "Your account has been successfully verified" );
response = Request.CreateResponse( HttpStatusCode.OK, json);
22 Figura 3.21: Lista obiectelor de transfer
Capitolul 3.Implementarea aplicației
Obiectele de transfer sunt obiecte utilizate pentru a îngloba date și pentru a le trimite de
la un modul la celălalt. Principalul avantaj este faptul că acestea reduc volumul de date care
trebuie transmis. Lista obiectelor de transfer folosite este reprezentată în Figura 3.21.
Implementarea reprezintă etapa în care este creat codul aferent aplicației proiectate în
capitolul anterior, îndeplinind restricțiile de resurse, acuratețe și performanță indicate de
specificații. Indiferent de structura programului, aceasta trebuie optimizată prin refactorizare ori
de câte ori este necesar. Pentru controlul versiunilor aplicației se folosește GitHub Extension for
Visual Studio.
Adresa la care poate fi găsit codul sursă este https://github.com/GeorgeMi/AzurePollApp .
Aplicația client poate fi accesată folosind adresa https://votemypoll.azurewebsites.net.
23
George Alexandru Miron
Capitolul 4. Testarea aplicației
Testarea unei aplicații se realizează cu scopul de a adăuga o anumită valoare acesteia.
Adăugarea valorii prin testare este echivalentă cu creșterea calității și a fiabilității programului.
Creșterea fiabilității programului are loc odată cu găsirea și eliminarea erorilor. Testarea este
procesul de execuție a unui program cu intenția de a găsi erori. [12] Prin urmare, nu se testează
un program pentru a arăta că funcționează; mai degrabă, începe cu presupunerea că programul
conține erori (o ipoteză valabilă pentru aproape orice program) și apoi se testează pentru a găsi
cât mai multe dintre acestea.
4.1. Testarea unităților
Pentru ca asupra unui cod să poată fie efectuată testarea unităților, acesta trebuie să
respecte principiul separării responsabilităților, astfel încât modulele să poată fi testate separat și
într-un mod izolat. Obiectele de tip mock sunt obiecte simulate care imită comportamentul
obiectelor reale în mod controlat. Un mock poate simula comportamentul obiectelor complexe,
reale și este, prin urmare, util atunci când un obiect real este imposibil de integrat într-un test de
unitate.
În cadrul acestei aplicații, mock-urile sunt create pentru a simula n ivelul de date, astfel
încât operațiile efectuate în cadrul testelor să nu aibă impact asupra bazei de date, ci să se
realizeze asupra unor colecții de date care simulează conținutul bazei de date. Interfața generală a
repository-urilor care sunt simulate este reprezentată în secvența următoare de cod.. Pentru
crearea mock-urilor se folosește Moq, unul dintre cele mai populare framework-uri .NET pentru
simulare.
public class AzureDataAccessMock : IAzureDataAccess
{
public IUserRepository UserRepository { get; set; }
public ICategoryRepository CategoryRepository { get; set; }
public ITokenRepository TokenRepository { get; set; }
public IQuestionRepository QuestionRepository { get; set; }
public IAnswerRepository AnswerRepository { get; set; }
public IFormRepository FormRepository { get; set; }
public IVotedFormsRepository VotedFormsRepository { get; set; }
}
Colecțiile care simulează conținutul bazei de date sunt alcătuite de liste a căror obiecte
sunt reprezentate de entități. Fiecare entitate corespunde unei tabele din baza de date. Astfel,
pentru a simula tabel User se creează o listă de obiecte de tip User. Pentru fiecare operație
efectuată asupra tabelei se vor adăuga, modifica sau șterge date din lista creată.
List<User> usersList = new List<User>
{
new User {UserID = 1, Username = "user1", Password = "pass1", Email = "user1@email.com", Role
= "admin",Verified = "yes"},
new User {UserID = 2, Username = "user2", Password = "pass2", Email = "user2@email.com", Role
= "user",Verified = "yes"},
new User {UserID = 3, Username = "user3", Password = "pass3", Email = "user3@email.com", Role
= "user",Verified = "no"}
};
24
Capitolul 4.Testarea aplicației
Crearea unui mock începe odată cu declararea și inițializarea acestuia:
Mock<IUserRepository> userRepositoryMock = new Mock<IUserRepository>();
Pentru a configura fiecare metodă să utilizeze colecția de date creată se folosesc
atributele Setup().Returns() pentru metodele care returnează un tip de dată și Setup().Callback()
pentru metodele care nu returnează nimic. Metoda GetAll(), care este folosită pentru a returna
toate obiectele de un anumit tip, este configurată astfel:
// Get All
userRepositoryMock.Setup(m => m.GetAll()).Returns(usersList.AsQueryable());
Această funcție returnează întreaga listă de obiecte de tipul User. Metoda Add() simulează
autoincrementarea id-ului din baza de date și adaugă un obiect în lista creată. Metoda
FindAllBy() returnează toate obiectele care îndeplinesc o restricție specificată ca parametru, în
timp ce metoda FindFirstBy() returnează primul obiect care îndeplinește o restricție specificată
ca parametru. Metoda Delete() șterge un obiect din lista creată.
// Add
formRepositoryMock.Setup(x => x.Add( It.IsAny<Form>())).Callback(new Action<Form>(f =>
{
f.FormID = formsList.Last().FormID + 1;
formsList.Add(f);
}));
// FindAllBy
userRepositoryMock.Setup(m => m.FindAllBy( It.IsAny<Expression<Func<User, bool>>>()))
.Returns<Expression<Func<User, bool>>>(usersList.AsQueryable().Where);
// FindFirstBy
formRepositoryMock.Setup(m => m.FindFirstBy( It.IsAny<Expression<Func<Form, bool>>>()
.Returns<Expression<Func<Form, bool>>>(
predicate => formsList.AsQueryable().Where(predicate).FirstOrDefault()
);
// Delete
formRepositoryMock.Setup(x => x.Delete( It.IsAny<Form>())).Callback(new Action<Form>(x =>
{
var i = formsList.FindIndex(f => f.FormID.Equals(x.FormID));
formsList.RemoveAt(i);
}));
Pentru crearea cazurilor de test este necesară construirea unei clase pentru fiecare modul
testat. Astfel, pentru testarea operațiilor folosind obiecte de tipul User se creează clasa
UserLogicTests având atributul [TestClass()]. Setarea mock-ului folosit și alegerea clasei ce
încorporează logica se realizează astfel:
IAzureDataAccess _mockDataAccess = new AzureDataAccessMock ();
UserLogic _userLogic;
25
George Alexandru Miron
[SetUp]
public void Setup()
{
_mockDataAccess = new AzureDataAccessMock ();
_userLogic = new UserLogic(_mockDataAccess);
}
Primele metode testate sunt cele pentru preluarea tuturor utilizatorilor din baza de date
(GetAllUsers()) și pentru preluarea rolului unui anumit utilizator ( GetUserRole()). Metoda
GetAllUsers() trebuie să returneze trei utilizatori la apelare dacă numărul de elemente de pe
pagină este mai mare decât numărul de utilizatori din colecția de date. În cazul în care numărul
de utilizatori din colecție este mai mare decât numărul de elemente de pe pagină, metoda
returnează numărul de elemente de pe pagină.
[Test]
public void GetAllUsers_Test()
{
Assert.AreEqual(3, _userLogic.GetAllUsers(0, 5).Count);
}
[Test]
public void GetAllUsers_Test2()
{
Assert.AreEqual(1, _userLogic.GetAllUsers(0, 1).Count);
}
Metoda GetUserRole() trebuie să returneze rolul utilizatorului care are username-ul
trimis ca parametru. Dacă username-ul nu există în baza de date, trebuie aruncată o excepție care
să atenționeze asupra acestui aspect.
[Test]
public void GetUserRole_Test()
{
Assert.AreEqual(0, _userLogic.GetUserRole( "user1").CompareTo("admin"));
}
[Test]
public void GetUserRole_Test2()
{
Assert.AreEqual(0, _userLogic.GetUserRole( "user2").CompareTo("user"));
}
[Test]
public void GetUserRole_Test3()
{
try
{
_userLogic.GetUserRole( "user4");
}
catch (Exception)
{
Assert.Pass();
}
Assert.Fail();
}
26
Capitolul 4.Testarea aplicației
Folosind aceeași metodă de creare a mock-urilor și a testelor, se creează mock-uri pentru
fiecare repository. De asemenea, se construiesc clase de testare pentru fiecare clasă din nivelul de
logică al aplicației ( Figura 4.1).
Toate testele construite trebuie validate, astfel încât aplicația să ruleze în parametri
optimi, având cât mai puține defecte. În cadrul acestei aplicații toate testele sunt validate ( Figura
4.2). În cazul unei refactorizări este suficientă rularea testelor asupra noului cod. Dacă acestea
trec, refactorizarea s-a realizat cu succes.
27Figura 4.1: Clase testare
Figura 4.2: Validarea testelor
George Alexandru Miron
4.2. Testarea la încărcare
Testarea la încărcare asigură faptul că sistemul poate gestiona un volum așteptat de date.
De asemenea, se verifică eficiența sistemului. Pentru crearea testării la încărcare se folosește
opțiunea Performance Test din portalul Azure. Având în vedere că resursele disponibile pe server
sunt reprezentate de un procesor, 1 GB RAM memorie și 1 GB memorie de stocare, se așteaptă
ca aplicația să ruleze normal în cazul în care se realizează 10 cereri pe secundă timp de un minut
(Figura 4.3).
Rezultate obținute sunt valide, întrucât serverul nu a cedat, toate cererile au primit câte un
răspuns de tip Success (200 OK) și timpul mediu de răspuns este de 0.04 secunde ( Figura 4.4).
O altă metodă pentru realizarea testării la încărcare este folosirea aplicației aflată la
adresa https://loader.io. Aceasta, prin adăugarea unui token pe serverul unde se află serviciul,
realizează o serie de cereri către server, în funcție de datele configurate. În acest caz aplicația
simulează cazul în care se realizează 100 de cereri pe secundă timp de un minut ( Figura 4.5 și
Figura 4.6).
28 Figura 4.4: Rezultatele testării la încărcare
Figura 4.3: Configurarea testului de încărcare
Capitolul 4.Testarea aplicației
Rezultatele obținute sunt valide, întrucât serverul nu a cedat, toate cererile au primit câte
un răspuns de tip Success (200 OK) . Cu toate acestea, timpul de răspuns variază între 1.2
secunde și 13.9 secunde.
29Figura 4.5: Configurarea testului de încărcare
Figura 4.6: Configurarea cererilor pentru testul de încărcare
George Alexandru Miron
30 Figura 4.7: Creșterea numărului de cereri timp de 1 minut
Figura 4.8: Graficul cererilor trimise și tipul răspunsurilor primite
Capitolul 4.Testarea aplicației
4.3. Testarea la stres
Testarea la stres solicită sistemul dincolo de încărcarea maximă proiectată. Pentru
realizarea testării la stres se folosește aplicația loader.io. În acest caz aplicația simulează cazul în
care se realizează 200 de cereri pe secundă timp de un minut ( Figura 4.10).
31Figura 4.10: Configurarea testului la stres
Figura 4.9: Graficul încărcării lățimii de bandă
George Alexandru Miron
În acest caz, nu toate cererile au primit câte un răspuns de tip Success (200 OK). Unele
cereri nu au primit niciun răspuns. Cu toate acestea, timpul de răspuns variază între 5.4 secunde
și 13.7 secunde.
32 Figura 4.12: Graficul cererilor trimise și tipul răspunsurilor primite
Figura 4.11: Creșterea numărului de cereri timp de 1 minut
Capitolul 4.Testarea aplicației
Testarea unei aplicații se realizează cu scopul de a adăuga o anumită valoare acesteia.
Aceasta reprezintă o metodă dinamică de verificare și validare, unde modulele sunt executate și
li se observă comportamentul. Testarea unităților este un proces iterativ (mereu vor exista
defecte care nu sunt prinse în cadrul testării unităților). Însă, numărul de defecte raportate în
timp și raportul dintre numărul de defecte nerezolvate față de problemele rezolvate oferă
informații semnificative în ceea ce privește sănătatea aplicației. [13]
În afara cazurilor de testare prezentate mai sus, aplicația client a fost supusă și testelor de
tip cutie neagră. Astfel s-a efectuat testarea navigării utilizatorului. Având în vedere rezultatele
obținute în urma testelor, aplicație nu prezintă defecte majore. Cu toate acestea, niciodată nu se
poate afirma că testarea unei aplicații este completă.
33Figura 4.13: Graficul încărcării lățimii de bandă
George Alexandru Miron
Concluzii
Lucrarea de față și-a propus dezvoltarea unei aplicații de gestiune a sondajelor de opinie
folosind servicii web. Acest tip de sondaj poate avea efecte benefice atât pentru cei care inițiază
sondajul, cât și pentru persoanele care răspund la întrebări. În momentul în care o companie
consideră oportună aducerea pe piață a unui nou produs sau serviciu, aceasta trebuie să
anticipeze modul în care clienții vor răspunde. Oferirea unui sistem de votare clienților este o
modalitate bună pentru a aduna răspunsurile acestora și de a estima câți oameni ar cumpăra noul
produs sau ar investi în noul serviciu. Aceste rezultate pot oferi o imagine clară asupra
produsului, dacă este sau nu o decizie financiară care poate aduce profit și cum poate fi acesta
îmbunătățit pentru a satisface nevoile potențialilor clienți.
În cadrul acestei aplicații, utilizatorii pot să vizualizeze și să voteze sondajele create de
către un administrator. De asemenea, aceștia au acces la statisticile sondajului și pot observa atât
procentajul fiecărei variante de răspuns, cât și numărul de persoane care au votat. Ideea inițială
era ca utilizatorii să se conecteze la această aplicație atât de pe desktop, cât și de pe dispozitivele
mobile folosind două aplicații diferite, specifice fiecărui sistem de operare. Cu toate acestea,
aplicația client s-a concretizat printr-un site. Astfel, utilizatorii de pe orice platformă pot accesa
aplicația folosind adresa http://votemypoll.azurewebsites.net. Soluția are avantajul de a ajunge la
un grup mult mai larg de persoane și, ca urmare, se poate realiza o analiză mai amănunțită asupra
rezultatelor. De asemenea, aceasta lucrare a descris etapele importante din cadrul procesului de
dezvoltare a unei aplicații web, urmărind, în același timp, o modularizare cât mai bună.
Deși în acest moment există o varietate de aplicații care permit crearea unui sondaj de
opinie online, fiecare dintre acestea prezintă avantaje și dezavantaje. În urma analizării acestor
aplicații s-a constatat că pentru a realiza o aplicație de crearea sondajelor de opinie, aceasta
trebuie să fie simplă, cu o interfață intuitivă și trebuie să fie disponibilă pe un număr cât mai
mare de dispozitive (atât mobile, cât și desktop). Astfel cât mai mulți utilizatori să poată
răspunde întrebărilor propuse. Numărul ridicat de persoane care răspund în cadrul unui sondaj
conduce spre validarea eșantionului și a rezultatelor.
În concluzie, pentru dezvoltarea unei aplicații de gestiune a sondajelor de opinie, cea mai
potrivită arhitectură este arhitectura multi-strat. Pe parcursul lucrării s-a stabilit modul în care
trebuie structurată aplicația, care este rolul fiecărui modul și cum se integrează acestea. De
asemenea, s-a descris modul în care este creat codul aferent aplicației proiectate, îndeplinind
restricțiile de resurse, acuratețe și performanță indicate de specificații. Rezultatele obținute în
urma testării au dezvăluit comportamentul aplicației atât în condiții normale, cât și în contextul
supraîncărcării serverului cu un număr crescut de cereri.
34
Bibliografie
Bibliografie
[1]Ben Woods, The best polling apps on the Web to create, publish your own survey and, of course, vote
[Online], Disponibil la adresa: http://thenextweb.com/apps/2013/11/26/best-polling-apps-web/#gref,
Accesat: 2015.
[2]Paul Sheriff (2009), Fundamentals of N-Tier , PDSA Inc., 4th Edition, 169 pagini
[3]Ilie Mihai-Gabriel (2013), Integrarea sistemelor informatice .NET vs JAVA
[4]Julia Lerman (2010), Programming Entity Framework , O'Reilly Media, 2nd Edition, 914 pagini
[5]Andrew Troelsen (2010), Pro C# 2010 and the .NET 4 Platform , 5th Edition, 1753 pagini
[6]Vlad Dragoi (2015), Unit testing, Dependency Injection, Mockups [Online],
Disponibil la adresa: http://elf.cs.pub.ro/idp/laboratoare/lab-05, Accesat: 2016.
[7]Emanuele DelBono (2013), ASP .NET Web API Succinctl y, Syncfusion Inc, 94 pagini
[8]Frederik Dietz (2013), AngularJS Succinctly, Syncfusion Inc, 108 pagini
[9]Beler Ingenierie (2015), De ce să dezvolți o aplicație cu AngularJS? [Online],
Disponibil la adresa: http://blog.beleringenierie.com/ro/2015/02/12/pourquoi-developper-une-application-
web-avec-angularjs/, Accesat: 2015.
[10]Introducing Microsoft SQL Server [Online], Disponibil la adresa: https://www.microsoft.com/en-us/server-
cloud/products/sql-server/, Accesat: 2016 .
[11]Tony Northrup (2009), Microsoft .NET Framework – Application Development Foundation , 2nd Edition,
829 pagini
[12]Glenford J. Myers, Corey Sandler, Tom Badgett, The Art of Software Testin g, JohnWiley & Sons, Inc.,
Hoboken, New Jersey, 2012.
[13]Marc Clifton (2013), UnitTesting Succinctly, Syncfusion Inc, 128 pagini
35
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: Calculatoare și Tehnologia Informației [602056] (ID: 602056)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
