Structura Proiectului Domoproject In Eclipse Ide Si Metode Ajutatoare
Cuprins
1 Introducere in testare automata
2 Fundamente teoretice
2.1 Testare software
2.2 Selenium WebDriver
2.2.1 Maven
2.2.2 Junit
2.3 Firebug
2.4 GIT
2.5 Jenkins
3 Implementare software
3.1 Prezentare generala
3.2 Diagrama proiectului
3.3 Structura proiectului domoProject in Eclipse IDE si metodele ajutatoare
3.4 Clasele de test
3.5 integrarea Eclipse-Git
3.6 Integrare Git-Jenkins
3.7 Rularea testelor automate
4 Rezultate experimentale
5 Concluzii
6 Bibliografie
7 Anexe
1 Introducere in testarea automata
O platformă de testare automată este un instrument software care permite executarea automată a test case-urilor anterior definite si automatizate. Un test case automatizat poate fi un test de funcționalitate, un test pentru cod, un test de performanta: load, stress sau poate reprezenta un benchmark. Diferite metode de automatizare a testelor software cat si hardware care au fost deja implementate vor fi prezentate in sectiunea de mai jos.
Framework-ul de testare automata Magento[1] – The Magento Test Automation Framework (MTAF), este un sistem de instrumente software utilizate pentru a rula in mod repetat teste funcționale conform aplicatiei Magento supusa procesului de testare. Acest framework de test poate fi utilizat pentru automatizarea celor mai multe procese, cum ar fi: inregistrarea si crearea profilului clientilor din frontend si din Admin Panel; adaugarea adreselor asociate conturilor clientilor; crearea de siteuri web, magazine web si web-views. Framework-ul de testare automata Magento este utilizat atât pentru scrierea script-urilor automatizare de teste cat și pentru efectuarea testelor.
Utilizatorii framework-ului de test poate rula un singur test independent, un grup de teste împreună (o suita de teste-test suite), sau toate testele disponibile cu o singură comandă. În timp ce testeaza versiuni intermediare ale produsului în curs de dezvoltare, echipa de asigurare a calității Magento (echipa QA) are nevoie sa execute o serie de teste. În plus, înainte de publicarea fiecare nouă versiune a platformei, este obligatoriu ca versiunea sa treaca printr-un set de teste de tip: "regression" și "smoke". Aceste teste sunt standard pentru fiecare noua versiune a produselor Magento, și, prin urmare, poate fi automatizat pentru a economisi resurse umane și de timp necesare pentru executarea lor.
În prezent, există două abordări principale folosite pentru testare automată: Unit Testing (denumit în continuare "UT"), și teste funcționale automate (denumit în continuare "AFT"). În Magento, abordările UT este foarte rar folosit, deoarece este nevoie de timp și resurse semnificative pentru a stabili dependențele între diferite module. AFT, pentru Magento, înseamnă un proces automatizat folosit pentru a diagnostica dacă funcționalitatea aplicației este conforma cerințele funcționale, initial stabilite in ciclul de viatza a unui produs software.
Fluxul de lucru pentru utilizarea AFT în aplicații Magento pot fi prezentate după cum urmează: identifice sarcinilor pe care aplicatia (sau o anumita caracteristica) trebuie sa le indeplineasca; crearea datelor de intrare necesare; definirea rezultatelor scontate ca mai apoi să fie utilizată ca referință pentru funcționalitate (sau caracteristica) aplicatiei; executarea testelor de catre specialistii QA si de asmenea compararea, tot de catre acestia, a rezultatele așteptate cu rezultate reale, și determină dacă testul a fost trecut cu succes.
Framework-ul de testare automata Magento utilizeaza urmatoarele instrumente si framework-uri: PHP Unit, Selenium, Selenium Integrated Development Environment (IDE), Selenium Remote Control (RC), Selenium Web Driver si Selenium-Grid. PHPUnit este un cadru de test pentru testarea de tip Unit Testing, pentru limbajul de programare PHP. Scopul său este de a găsi greșeli în codul sursă PHP. Un major beneficiu in utilizarea PHPUnit este abilitatea de a stabili o infrastructură de testare și re-folosirea acesteia ori de câte ori este necesar, pur și simplu prin crearea unor parti unice pentru fiecare test in parte. Selenium IDE este un instrument de tip prototype, utilizat pentru construirea de scenarii de test. Acesta este totodata un plugin Firefox care oferă o "interfață ușor de utilizat" pentru dezvoltarea de teste automate. Selenium IDE are o caracteristică de înregistrare, care înregistrează actiunile utilizatorilor utilizator in momentul in care acestea sunt efectuate, apoi le exportă ca un script reutilizabile care pot fi executate ulterior într-una din diversele limbaje de programre. Selenium RC este un instrument de testare care permite scrierea de teste automate pentru partea de UI a unei aplicatii, in orice limbaj de programare si pentru orice site HTTP utilizand orice browser caruia ii este setata optiunea JavaScript-enabled. Seleniu-Grid este un derivat al Selenium-ului, care permite dezvoltatorilor și echipei de asigurare a calității pentru a accesa Selenium RC fără a stii neaparat unde se afla controalele de tip remote utilizate de Selenium. Atat un developer sau un specialist de asigurare a calității, poate crea scripturi utilizand Selenium RC si apoi sa le ruleze pe acestea. Pentru utilizarea Framework-ului de testare automata Magento este necesar ca urmatoarele programe sa fie instalate: PHP 5.2.0 sau mai nou, PHPUnit 3.5.13 sau mai nou, Java Run-time Environment (JRE) 1.6 sau mai nou, Un environment de integrare a dezvoltarii: NetBeans 6.9.1 sau mai nou, Selenium Remote Control (RC), TortoiseGIT si Magento Community Edition 1.5 sau mai nou.
2. Fundamente teoretice
2.1 Testarea software
Exista mai multe definiti pentru cea ce inseamna testare software printre care se numara si urmatoarele[5]:
“…procesul de a executa un program avand intentia de a-i certifica Calitatea” Mills
“…procesul de a executa un program avand intentia de a descoperi erori. ” Myers
“…procesul de a executa software pentru a determina erori si pentru a verifica daca acesta satisface cerintele functioanel si nefunctioanele cerute” Mills si Myers
“…procesul de a exercita software pentru a verifica satisfacerea cerintelor specificate si pentru a determina erori.” Standardul BS7925-1998
“…procesul constand din toate activitatile ciclului de viata al testarii software, dinamice si statice, avand in vedere planificare, prepararea si evaluarea produselor software si ale altor produse similare pentru a determina ca acestea satisfac cerintele specificate, pentru a demonstra ca sunt adecvat scopului si pentru a detecta erori. ”
Interational Software Testing Qualification Board.
[6]Dezvoltarea produselor software in present nu se realizeaza fara ca toate produsele sa fie supuse unor procese de testare si de asigurare a calitatii tot mai complexe si competitive. Testare nu se realizeaza independent de dezvoltarea unui produs software, ea isi are locul in procesul de dezvoltare a software-ului si astfel modelul de dezvoltare ales are consecinte directe asupra testarii si de asemenea va determina in mare masura modul in care este organizata testarea. Procesul de dezvoltare adoptat pentru un proiect va depinde de obiectivele proiectului. Exista numeroase modele de dezvoltare, care au fost create în scopul obtinerii unor diferite obiective. Acestea variaza de la metodologii usoare si rapide, unde timpul de release in productie este foarte important, pana la metodologii complet controlate si documentate, pentru care calitatea si fiabilitatea sunt factori cheie. Fiecare dintre aceste metodologii are locul său în software-ul modern, dezvoltare si procesul de dezvoltare cel mai adecvat ar trebui să se aplice in functie de specificul fiecarui proiect. Modul in care testarea este organizata trebuie să se potrivească ciclului de dezvoltare sau va esua in livrarea produselor de calitate. In cazul in care timpul de a ajunge in productie este factorul cheie, testarea trebuie sa fie rapida si eficienta. In cazul in care procesul de dezvoltare software propus este complet si documentat la fel va trebui sa fie si partea de testare. In fiecare ciclu de viata al dezvoltarii, o parte a testarii este focusata pe verificare iar alta parte pe validare.
Procesul de verificare este preocupat cu evaluarea unui produs, componentă sau sistem pentru a determina dacă acesta îndeplineste setul de cerinte. De fapt, verificarea se concentrează pe întrebarea "Este construit livrabilul în conformitate cu specificatiile?" Procesul de validarea este preocupat de evaluarea unui produs, componentă sau sistem pentru a determina dacă acesta îndeplineste necesitatile si cerintele utilizatorilor. Validarea se concentrează pe întrebarea: "Se potriveste livrabilul din punctual de vedere al scopului si ofera prin aceasta o solutie problemei?"
Testarea unui sistem software se referă la comportamentul întregului sistem / produs definit de domeniul de aplicare al unui proiect sau al produsului. Aceasta poate include teste bazate pe riscuri, specificațiile cerințelor, procesul business, cazuri de utilizare, sau alte descrieri la nivel înalt al comportamentului sistemului, interacțiunile cu sistemul de operare, și sistemul de resurse.
Unul dintre marile dezavantaje ale dezvoltarii si testarii aplicatiilor software este lipsa cunostiintelor minime tehnice din partea clientului si incapaciteatea acestuia de a oferi documente clar si precise asupra proiectului ce se doreste a fi dezvoltat. Astfel testerii sunt de cele mai multe ori nevoiti sa lucreze cu documente ce incomplete si neclare. Din acest motiv se aleg diferite tehnici de testare, in concordanta cu tipul si caracteristicile proiectului. Testarea sistemului din punctul de vederea al cerintelor functionale se face aplicand tehnica black-box, aceasta fiind bazata pe specificatii. Astfel, un tabel decizie poate fi creat pentru combinațiile efectelor descrise în regulile de business. Tehnicile bazate pe structura se mai numesc white-box si pot fi, de asemenea, utilizate pentru a evalua profunzimea cu care anumite elemente sunt testate, cum ar fi structura unui meniu.
Testarea sistemului necesită un mediu de test controlat în ceea ce privește, printre altele, controlul versiunilor de software, testware și de datele de test. Un sistem de testare este executat de către organizația de dezvoltare într-un mediu controlat în mod corespunzător. Mediul de testare trebuie să corespundă obiectivului final sau mediului de producție cât mai mult posibil, în scopul de a reduce la minimum riscul de a produce defecte din cauza mediului de testare.
2.2 Selenium WebDriver
[7]Majoritatea aplicațiilor software de astăzi sunt scrise ca aplicatii web-based, pentru a fi executate într-un browser si avand o conexiune la Internet. Eficacitatea testarii acestor aplicații variază foarte mult în rândul companiilor și organizațiilor. Într-o eră a proceselor software extrem de interactive si receptiv în care multe organizații folosesc diferite forme a metodologiei Agile, automatizare testarii adesea devine o cerință pentru proiectele software. Automatizare testarii înseamnă utilizarea unui instrument software pentru a rula teste in mod repetat pe aplicatia ce este supusa procesului de testare.
Există multe avantaje ale automatizarii: frecventa cu care se poate testa partea de regresie; feedback-ul rapid pentru dezvoltatori; Iterații practic nelimitate de execuție pentru un caz de test; suport pentru Agile și metodologiile extreme de dezvoltare (Extrem Programing); documentația test case-urilor; raportare personalizate cu defecte; găsirea defectelor ratate de testare manuală. Nu este întotdeauna avantajos sa se automatizeze toate test case-urile. Există momente când testarea manual poate fi mai adecvata. De exemplu, dacă interfața aplicației cu utilizatorul se va schimba considerabil în viitorul apropiat, atunci orice automatizare ar putea avea nevoie de schimbari majore sau chiar să fie rescrisa de la zero. entru Agile și metodologiile extreme de dezvoltare (Extrem Programing); documentația test case-urilor; raportare personalizate cu defecte; găsirea defectelor ratate de testare manuală. Nu este întotdeauna avantajos sa se automatizeze toate test case-urile. Există momente când testarea manual poate fi mai adecvata. De exemplu, dacă interfața aplicației cu utilizatorul se va schimba considerabil în viitorul apropiat, atunci orice automatizare ar putea avea nevoie de schimbari majore sau chiar să fie rescrisa de la zero. De asemenea, uneori pur și simplu nu este suficient timp pentru a construi testele automate. Pe termen scurt, testarea manuala poate fi mult mai eficienta. Dacă o aplicație are un termen foarte strâns in care trebuie sa fie lansata pe piata, nu există timp suficient pentru a investi in automatizare, astef testarea manuala este cea mai bună soluție.
Selenium reprezinta un set de instrumente software diferite, fiecare cu o abordare diferită in sprijinirea testarii automate. Cei mai multi QA engineers care lucreaza cu Selenium se concentreze pe una sau două instrumente care satisfac cel mai bine nevoile proiectului lor. Cu toate acestea învățarea tuturor instrumentelor pe care le are Selenium, ofera diferite opțiuni pentru abordarea diferitelor probleme de automatizare a testelor. Întreaga suită de instrumente duce la un set bogat de functii de testare special adaptate la nevoile de testare a aplicațiilor web de toate tipurile. Aceste operațiuni sunt extrem de flexibile, si permit abordarea mai multor opțiuni pentru localizarea elementele de UI și compararea rezultatelor așteptate ale testelor cu comportamentul real al aplicației. Una dintre caracteristicile cheie ale Selenium este suportul pentru executarea testelor pe platforme browser multiple.
Caracteristica principală in Selenium este integrarea WebDriver API. WebDriver este conceput pentru a oferi o interfață de programare mai simpla si mai concisa, în plus față de abordarea unor limitări în Seleniu-RC API. Selenium WebDriver a fost dezvoltat pentru a sprijini mai bine paginile web dinamice în care elemente unei pagini pot fi modificate fără ca pagina în sine sa fie reîncărcata. Scopul WebDriver este de a furniza un API orientat-obiect bine conceput, care oferă suport îmbunătățit pentru probleme moderne, avansate de testare web-app.
Seleniu-WebDriver face apeluri directe către browser utilizand suportul nativ al acestuia pentru automatizare. Cum sunt realizate aceste apeluri directe, și facilitățile pe care le susțin depinde de browser-ul care este utilizat.
In funcție de modul în care este utilizat Selenium-WebDriver se poate sau nu sa fie nevoie de Selenium Server. Daca se foloseste doar WebDriver API, in acest caz nu este necesar utilizarea serverului. Daca browserele și testele ruleaza pe aceeași mașină, și testele folosesc numai WebDriver API, atunci nu este nevoie pentru a rula Seleniu-Server; WebDriver va rula browser-ul direct. Exista motive pentru a utiliza Selenium-Server iar acestea sunt prezentate mai jos:
Daca se foloseste Seleniu-Grid pentru a distribui testele pe mai multe mașini fizice sau mașini virtuale (VM).
Daca este necesara conexiunea remote la o masina virtuala, care are o versiune de browser diferita fata de cea care este pe mașina curenta.
Daca nu se folosesc legaturile Java (de exemplu, Python, C #, sau Ruby) si este necesara utilizarea HtmlUnit Driver
WebDriver este un instrument pentru automatizarea testarii aplicațiilor web, și în special pentru a verifica dacă acestea funcționează cum era de așteptat. Acesta își propune să ofere un API prietenos, care este ușor de explorat și de înțeles, si mai ușor de utilizat decât Selenium-RC Acest API, ajuta la citirea mai usoara a testelor si la mentenanta acestora. Nu este legat de un framework special, astfel încât să poată fi folosit la fel de bine ca Unit Testing sau simplu ca o metodă de tip "main". Principalele comenzi API si operatori sunt prezentate in sectiunea de mai jos:
Preluarea unei pagini: Primul lucru pe care este foarte probabil de a fi realizate cu WebDriver este navigarea la o pagină web. In mod normal de a face acest lucru este prin apel "get".
Localizarea elementelor de UI (WebElements): Localizarea elementelor în WebDriver se poate face în instanța de WebDriver sau pe un WebElement. Exista doua tipuri de metode: "Find Element" și "Find Elements". Primul returneaza un obiect WebElement, altfel se aruncă o excepție. Acesta din urmă returnează o listă de WebElements, se poate returna o listă goală dacă nu există elemente DOM care sa potriveasca interogării. Metoda “Find” foloseste un locator sau un obiect de interogare numit “By”. Strategiile “By” sunt enumerate mai jos:
By ID: Acesta este modul cel mai eficient și preferat pentru a localiza un element. Gresala comuna pe care dezvoltatorii UI o fac este de a avea ID-uri non-unice pe o pagină sau auto-generarea de ID-uri; ambele ar trebui evitate. O clasa pe un element HTML este mai adecvata decât un id auto-generat.
By Class Name: "Clasa", în acest caz se referă la atributul pe elementul DOM. De multe ori, în practică, există multe elemente DOM cu același nume de clasă, a găsi, astfel, mai multe elemente devine opțiune mai practică de a găsi primul element.
By Tag Name: Numele Tag-ului elementului asociat din DOM.
By Name: Gasirea elementului din pagina care se poriveste atributului “nume”
By Link Text: Gasirea elementului “link” din pagina care se potriveste cu un anumit text vizibil
By Partial Link Text – Gasirea elementului “link” din pagina care se potriveste partial cu un anumit text vizibil
By CSS – Gasirea elementului folosind locator css. Pentru aceasta se foloseste suportul acordat de browser. Astfel aceasta optiune depinde de browserul folosit si de versiuni ale aceluias tip de browser: anumite css-uri care functioneaza pentru o versiune de browser, exista probabilitatea sa nu functioneze pentru o alta versiune.
By XPATH – WebDriver utilizează capabilitățile XPath native din browser ori de câte ori este posibil. Pe acele browsere care nu au suport nativ XPath, a fost implementata alta metoda xpath iar acest lucru poate duce la comportament neasteptat in cazul in care nu se cunosc diferentele dintre cele doua metode diferite XPath.
Input de la utilizator sau completarea formularelor: WebDriver ofera posibilitatea de a comuta starile checkbox-urilor dintr-o pagina si de asemenea se poate folosi optiunea “click” pentru a seta un anumit tag. Aceastea sunt realizate prin folosirea locatorului SELECT, in general pentru o lista de elemente din care se doreste setarea unui anumit element. Folosirea locatorului select nu este cea mai eficienta metoda deoarece SELECT parcurge toate elementele din lista. Exista insa in cadrul claselor oferite de WebDriver clasa “Select” care pune la dispozitia utilizatorului metode utile pentru a interactiona cu astfel de elemente de tip lista. După ce formularul a fost completat sau elementul din lista a fost ales, cel mai probabil că urmatoarea actiune este sa se faca submit pe pagina. O modalitate de a face acest lucru ar fi să găsească butonul "submit" și sa se faca clic pe acesta. Alternativ, WebDriver are o metoda "submit" pe fiecare element. Dacă apelați la acest element într-un formular, WebDriver cauta in DOM până când se găsește sfarsitul formularului și apoi face submit la acesta. Dacă elementul nu se gaseste in niciun formular, exceptia NoSuchElementException va fi aruncata.
Comutarea intre ferestre multiple si cadre: Unele aplicații web au multe cadre sau mai multe ferestre. WebDriver sprijină trecerea între ferestre denumite folosind metoda "switchTo". Toate apelurile către driver vor fi acum interpretate ca fiind direcționate către o anumita fereastra.
In acest caz este insa necesar cunoasterea numele exact al ferestrei. Alternativ se poate atasa un “window handle” la metoda “switchTo().window()”. Cunoscand acest lucru, driverul poate itera printre toate ferestrele deschise. Exista posibilitatea de a se comuta si intre cadre si de asemenea de a accesa subcadre prin separarea cu punct si specificarea cadrului conform indexului acestuia.
Popups: Începând cu Seleniu 2.0 beta 1, a fost construit suport pentru manipularea dialogurilor de tip pop-up. După ce s-a declanșat o acțiune care deschide un pop-up, se poate accesa alerta cu următoarea comanda: ”driver.switchTo().alert()”. Prin aceasta comanda se va returna obiectul alerta deschis. Folosind acest obiect se poate accepta, refuza sau se poate citi continutul pop-up-ului. Aceasta interfata functioneaza atat pentru alerte cat si pentru alte dialoguri gen: confirms sau prompts.
Navigare: Istorie și Locație: Intr-o sectiune de mai sus am aratat ca navigarea catre o anumita pagina in browser se face folosind comanda “get”. WebDriver are o serie de interfete mai mici focusate pe diferite taskuri iar navigarea este una dintre acestea. Deoarece încărcarea unei pagini este o astfel de cerință fundamentală, metoda de a face acest lucru este intergata pe interfata principala WebDriver, dar este pur și simplu un sinonim pentru: driver.navigate().to(“http//..”).
Cele doua comenzi “navigate().to()” si “get()” fac exact acelasi lucru. Interfața "navigate", expune, de asemenea, capacitatea de a muta înainte și înapoi în istoria browser-ului: “driver.navigate().forward(); driver().navigate().back()”. Aceasta funcționalitatea depinde în întregime de browser-ul pe care se fac testele.
Driverele Selenium WebDriver: WebDriver este numele interfeței cheie în care ar trebui să fie scris teste, dar există mai multe implementari, acestea includ: HtmlUnit, Firefox, Internet Explorer, Chrome, Opera, IOS and Android. HtmlUnit Driver este în prezent cea mai rapidă și mai ușoară implementarea WebDriver. După cum sugerează și numele, acest driver se bazează pe HtmlUnit. HtmlUnit este o implementare bazata pe Java a unui WebBrowser fără GUI. Pentru orice alt limbaje de programare (altele decât Java) Serverul Selenium este necesar pentru a utiliza acest driver. Avantajele utilizarii HtmlUnit sunt urmatoarele: cea mai rapida implementare a WebDriver; reprezinta o solutie java, independena de platforma; suporta JavaScript. Nici una dintre cele mai populare browsere nu utilizează motorul JavaScript folosit de HtmlUnit (Rhino). Dacă se utilizeaza JavaScript folosind HtmlUnit rezultatele testarii pot diferi semnificativ fata de aceste browsere. In sectiunea de mai sus JavaScript se refera atat la JavaScript in sine cat si la DOM. W3C Document Object Model (DOM) este o platformă care permite programelor si scripturilor sa acceseze dinamic și sa actualizeze conținutul, structura, și stilul unui document. Deși DOM este definit de W3C fiecare browser are propriile diferențele în implementarea pentru DOM și în modul in care JavaScript-interactioneaza cu el. HtmlUnit are o implementarea completă a DOM și suport bun pentru a utiliza JavaScript, dar nu este diferit de orice alt browser: are propriile diferențele de implementare atât pentru standardul W3C cat și pentru DOM, în ciuda abilitatia sale de a imita alte browsere. Driverul Firefox controlează browser-ul Firefox cu ajutorul unui plug-in de Firefox. Profil Firefox, care este utilizat este descarcat pentru a include numai Selenium WebDriver.xpi (plug-in). Câteva setări sunt, de asemenea, modificate în mod implicit. Driverul Firefox este capabil de a rula și este testat pe Windows, Mac si Linux. Avantajele acestuia sunt: ruleaza într-un browser reală și acceptă JavaScript si este mai rapid decat Internet Explorer. Principalul dezavantaj este faptul ca Firefox este mai lent decat HtmlUnit. Driverul Internet Explorer este este controlat de un. dll și este astfel disponibil doar pe Windows OS. Fiecare versiune noua de Selenium are funcționalitatea de bază testat cu versiunile 6, 7 și 8 pe XP, și 9 pe Windows7. Avantajul principal al utilizarii Internet explorer este faptul ca ruleaza intr-un browser real si accepta JavaScrip. Dezavantajele insa sunt mai multe: acest driver va functiona doar pe plaforma Windows; este un browser relativ lent; Xpath nu este suportat in mod nativ in cele mai multe dintre versiuni; Sizzle este injectat în mod automat, insa este semnificativ mai lent decât alte browsere și mai lent atunci când se compară cu selectorii CSS al aceluiaș browser; CSS nu este nativ susținută în versiunile 6 și 7 ale Internet Explorer; Selectoare CSS în IE 8 și 9 sunt native, dar aceste browsere nu acceptă în totalitate CSS3. Driverul Chrome este mentinut si suportat de catre proiectul Chromium. WebDriver lucrează cu Chrome prin intermediul fisierului binar chromedriver. Pentru a putea rula teste folosind acest driver este nevoie atât de chromedriver cat și de o versiune a browser-ului Chrome instalata pe platforma de lucru. Chromedriver trebuie să fie plasat undeva pe calea sistemului dumneavoastră pentru ca WebDriver să-l descopere în mod automat. Browser-ul Chrome în sine este descoperit de chromedriver pe calea de instalare implicită. Avantajele Chrome sunt: ruleaza într-un browser reală și acceptă JavaScript, insa ca si in cazul Internet Explorer si Firefox, si acest driver este mai lent decat HTML Unit.
Alternative Back-End: Versiunea Java a WebDriver ofera o implementare a Selenium-RC API. Aceasta inseamana ca se poate utliza tehnologia de baza WebDriver cu Selenium-RC API. Acest lucru a fost prevazut in primul rand pentru compatibilitate. Aceasta permite celor care au o suita de teste scrisa in Selenium-RC sa poate sa foloseasca facilitatile WebDriver si a fost creata pentru a ajuta la migrarea catre noua tehnologie, WebDriver. Principalele avantaje sunt: punerea la disozitie a unui mecanism simplu pentru o migrare gestionata al lui Selenium RC API si faptul ca nu are nevoie de Selenium RC Server pentru a rula. Dezavantajele sunt: nu sunt implementate toate metodele; utilizarea facilitatilor mia avansate de Selenium ar putea sa nu functioneze iar unele metode ar putea fi mai lente din cauza diferentelor de implementare.
2.2.1 Maven
Maven este un cuvant care in limba idis inseamna “acumulator de cunostiinte”. Acesta a fost conceput initial ca o încercare de a simplifica procesele de build în proiectul Turbine Jakarta. Au existat mai multe proiecte, fiecare cu propriele lor fișiere care au fost ușor diferite și fisierele jar ale acestora au fost uplodate în CVS. Atunci s-a dorit o modalitate standard de a construi proiecte, o definiție clară in ceea ce proiectul consta, o modalitate ușoară de a publica informații despre proiect și o modalitate de a partaja fisiere JAR în mai multe proiecte. Rezultatul este un instrument care poate fi acum utilizat pentru construirea și gestionarea oricarui proiect bazat pe Java. Maven face munca de zi cu zi a dezvoltatorilor Java mai ușoara și, în general, ajuta la înțelegerea oricărui proiect bazat pe Java. Scopul principal Maven este de a permite unui dezvoltator sa înțeleaga starea completă a unui efort de dezvoltare, în cel mai scurt interval de timp. În scopul de a atinge acest obiectiv, există mai multe zone de interes, pe care Maven încearcă să se le imbunatateasca:
Simplificarea procesului de build
Asigurarea unui sistem de build uniform
Furnizarea de informații despre proiect avand un grad mare de calitate
Asigură informatii pentru aplicarea celor mai bune practici
Permite in mod transparent migrarea catre noi caracteristici
Utlizarea Maven nu elimina nevoia de a cunoaște mecanismele care stau la baza proietului, Maven oferind utilizatorului protectie de la detalii. Maven permite build-ul unui proiect folosind “project object model” (POM) și un set de plugin-uri, care sunt împărtășite de toate proiectele care utilizează Maven, oferind astfel un sistem de build uniform. După ce un utilizator se familiarizeaza cu modul în care se construiește un proiect Maven este usor de dedus cum sunt construite toate proiectele Maven. Astfel se poate economisi timp atunci când utilizatorul încearcă sa navigheze mai multe proiecte. Maven oferă o mulțime de informații utile proiect, care o parte sunt luate din fisierul POM iar altele sunt generate din sursele proiectului. Informatii utile oferite de Maven sunt:
Schimbarea documentului de logare creat direct din sursa de control
Mailing list
Lista de dependinte
Rapoarte ale Unit Test, inclusiv de acoperire
Prin dezvoltarea si imbunatatirea Maven, si setul de informațiile furnizate vor fi îmbunătățite, toate fiind transparente pentru utilizatorii de Maven. Alte produse pot oferi, de asemenea, plugin-uri Maven pentru a permite vizuaizarea atat a setului de informații ale proiectului cat si unele dintre informațiile standard dat de Maven, toate bazează însa pe POM. Maven își propune să adune principiile actuale pentru dezvoltarea celor mai bune practici, și să ușureze ghidarea unui proiect în acest sens. De exemplu specificarea, executia si raportarea Unit testelor sunt parte a ciclului normal de build folosind Maven. Cele mai bune practici in Unit Testing au fost utilizate ca ghidare principala: păstrarea codul sursă de testare intr-un ” source tree” separat si paralel; folosirea anumitor conventii pentru denumirea testelor, pentru a usura localizarea si executia acestora; configurarea mediului de test in test cases si nu in customizarea buildului pentru prepararea testelor. Maven, de asemenea, își propune să asiste în fluxul de lucru al proiectului, cum ar fi gestionarea versiunilor și urmărirea problemelor. Maven sugerează, de asemenea, unele linii directoare cu privire la modul de a structura directoarele proiectului, astfel încât odată ce sa invatat layout-ul se poate naviga cu ușurință orice alt proiect care utilizează Maven. Maven oferă o modalitate ușoară pentru clienții Maven să actualizeze proiectele lor, astfel încât acestia să poată profita de orice modificări care au fost aduse in Maven. Instalarea de plugin-uri noi sau actualizate de la părți terțe sau de la Maven a devenit mult mai usoara din cauza acestui motiv.
Maven încurajaza cele mai bune practici, dar este evident faptul că unele proiecte nu se potrivească cu aceste idealuri. Cu toate ca Maven este conceput pentru a fi flexibil într-o mare măsură, în astfel de situații și la nevoile diferite ale proiectelor, totusi, este imposibil sa se plieze pentru orice situație, fără a face compromisuri vis’a’vis de integritatea obiectivelor sale.
2.2.1 JUnit
Un test de unitate (Unit Test) este o bucată de cod scrisa de către un developer, iar aceasta execută o anumită funcționalitate în codul care este supus testatarii. .Procentul de cod care este testată prin teste de unitate este de obicei numit “test coverage”. Unit Testele au drept tinta unități mici de cod, de exemplu, o metodă sau o clasa, (teste locale), în timp testele pentru componente și integrare vizează testarea comportamentului unei componente sau integrare între un set de componente sau a unei aplicatii complete formate din mai multe componente. Prin Unit teste se asigura ca functionalitatea codului este cea dorita. Testele sunt, de asemenea, foarte utile pentru a se asigura că functionalitatea deja existenta nu a fost afectata, în cazul în care se modifica codul pentru fixarea unui bug sau extinderea funcționalității. Având o acoperire mare a testelor in cod, permite continuarea dezvoltarii caracteristicilor fără a se efectua o mulțime de teste manuale. De obicei teste de unitate sunt create în propriul lor proiect sau folderul sursă propriu pentru a evita amestecarea codului normal și a codului de test. JUnit este un framework de test care utilizează adnotări pentru a identifica metode care specifică un test. De obicei aceste metode de testare sunt conținute într-o clasă care este folosita numai pentru testare. Aceasta este de obicei numita o clasă de test. O metodă de testare JUnit poate fi creata prin intermediul File → New → JUnit → JUnit Test case. JUnit presupune că toate metodele de testare pot fi executate într-o ordine arbitrară. Prin urmare, testele nu ar trebui să depindă de alte teste. Pentru a scrie un test cu JUnit se va adnota o metodă cu “@org.junit.Test” și se va folosi o metodă oferita de JUnit pentru a verifica rezultatul așteptat la executarea codului față de rezultatul real.
Se poate utiliza interfața Eclipse pentru a rula testul, prin click-dreapta pe clasa de test și selectând Run → Run As → JUnit Test. In afara de Eclipse puteți utiliza clasa org.junit.runner.JUnitCore pentru a rula testul. In tabelul de mai jos sunt descrise adnotarile disponibile in JUnit:
Table 1. Adnotare JUnit
JUnit oferă metode statice din clasa Assert pentru a testa anumite condiții. Aceste metode assert, încep de obicei cu notatia assert și permit specificarea mesajului de eroare, rezultatul așteptat și rezultatul efectiv. O metodă de tip assert compară valoarea reală returnată de un test cu valoarea așteptată, și aruncă o excepie: AssertionException, dacă testul comparației nu este unul pozitiv.
In tabelul de mai jos sunt descrise metodele assert disponibile in JUnit:
Tabel 2. Metode Assert
Dacă exista mai multe clase de test, acestea se pot combina într-o suita de teste. Rularea unei suite de teste va executa toate clasele de test din acel ”Test Suite”. Eclipse ofera suport pentru rularea interactiva a testelor în Eclipse IDE. Se pot rula, de asemenea, teste JUnit in afara Eclipse prin codul standard Java. Clasa org.junit.runner.JUnitCore oferă metoda runClasses (), care permite rularea uneia sau mai multor clase de teste. Ca parametru se returneaza un obiect de tipul org.junit.runner.Result. Acest obiect poate fi utilizat pentru a prelua informații despre teste. În folderul de test se poate crea o noua clasa: MyTestRunner avand codul de mai jos. Această clasă va executa clasele de test și va scrie eșecurile in consola.
Imaginea 1. Clasa MyTestRunner
Pentru a rula testele JUnit in afara Eclipse trebuie adăugat la classpath-ul programului biblioteca jar: JUnit. De obicei framework-urile de build, cum ar fi Apache Ant sau Apache Maven sunt utilizate pentru a executa teste în mod automat si regulat.
2.3 Firebug
[8]Firebug este un instrument de dezvoltare web care facilitează depanare, editare, și monitorizarea oricarui site CSS, HTML, DOM, XHR, și JavaScript, și oferă, de asemenea, alte instrumente de dezvoltare web. După ce se instaleaza Firebug apare o icoana "Firebug" gri în bara de navigare Firefox (de-a lungul partii de sus a ferestrei). Daca se face click pe Bug, Firebug se va deschide în partea de jos a paginii web. De îndată ce este deschis Firebug, se poate examina pe pagina web: markup-ul, stilu, și object model (modelul de obiect). Cele trei taburi – HTML, CSS, și DOM – se activeaza imediat ce se deschide Firebug.
În orice site JavaScript, elemente HTML sunt în mod constant create, eliminate, și modificat. Firebug evidențiază imediat modificările aduse HTML în galben, atunci când acestea apar. Dacă se doreste vizualizarea tuturor modificarilor recente, Firebug ofera aceasta optiune utilizatorului pentru a nu rata o posibila modificare importanta. Un alt element important pus la dispozitie de firebug este optiunea “Inspect”. După cum este deplasat pe pagina mouse-ul, ceea ce este sub acesta va fi revelat instantaneu de Firebug, care va arată codul HTML și CSS din spatele elementului. De asemenea cand se foloseste Inspect pe un element in tabul HTML, exista posibilitatea de a reîncărca pagina și Firebug va continua să arate același element (dacă mai există) după reîncărcare. Acest lucru usureaza testarea si vizualizarea modificarilor atunci când se face o schimbare într-un editor extern și a apoi se revine la Firefox pentru a vedea rezultatul modificarii. Prin click dreapta pe orice element se pot accesa o serie de optiuni pentru copierea asepectelor acelui element in clipboard inclusiv fragment de HTML, valoarea proprietatii "innerHTML", sau o expresie XPath care identifică unic elementul. Tabul CSS este utilizat pentru a evidentia style-urile din pagina web iar daca se fac anumite schmbari, efectul acestora poate fi analizat imediat.
Document Object Model este o mare ierarhie de obiecte si functii. Firebug ajută la identificarea obiectelor DOM rapid și apoi editarea simpla a acestora. Există două tipuri de obiecte si functii – cele care fac parte din DOM standard, iar cele care sunt ale propriul cod JavaScript. Firebug poate face diferenta, si va arata propriile obiecte-script și funcții boldate în partea de sus a listei. Firebug permite vizualizarea și gestionarea cookie-urilor din browser. Se pot refuza cookie-uri pentru anumite site-uri, cookie-uri de filtrare, crearea de noi și să ștergeți cookie-urile existente. Puteți vizualiza în debugger atunci când cookie modifică valoarea și a vedea linia de script-ul care a provocat schimbarea.
2.4 Git
[9]Version Control (Controlul Versiunii) este un sistem care înregistrează modificări la un fișier sau un set de fișiere, în timp, astfel încât mai târziu, ofera acces asupra unor versiuni specifice. Chiar dacă in dezvoltarea si testarea software fișierele introduse in acest sistem de control al versiunii sunt fisierele sursa ce contin codul proiectelor sau al testelor autmate, în realitate, orice tip de fișier de pe un calculator poate fi plasat sub controlul versiunii. Daca utilizatorul este un web designer si doreste sa pastreze fiecare versiune a unei imagini sau layout, este foarte important sa se utilizeze un sistem de control al versiunii: Version Control Sistem (VCS).
Pentru foarte multi dintre utilizatorii VCS principala metoda de control a versiunii este este sa copieze fisiere intr-un alt director. Această abordare este foarte comuna, pentru că este atât de simplu, dar este, de asemenea, foarte predispusa la erori. Este ușor ca un utilizator sa incurce directorul in care se alfa și accidental sa scrie in fișierul greșit sau sa se copieze peste fișierele pe care nu nu se doreste a fi modificate. Pentru a putea trece usor peste aceste probleme a fost proiectata care pastreaza fiecare modificare a unui fisier sub forma unei noi revizii.
Diagrama 1. Diagrama Controlului Versiunii – Local
Una dintre cele mai populare instrumente VCS a fost un sistem numit RCS, care este încă distribuit pe multe calculatoare din prezent. Chiar și sistemul de operare Mac OS X include comanda RCS când se instaleaza toolurile de dezvoltarea. Acest instrument practic funcționează prin menținerea seturilor de patch-uri (care reprezinta diferențele dintre fișiere) de la o revizie la alta într-un format special de pe disc. Astfel se poate recrea apoi orice fișier cu formatul de la orice data posterioara crearii sale, prin însumarea tuturor patch-urilor.
Diferența majoră dintre Git și orice alt VCS (ex: Subversion) este modul in care Git lucreaza cu datele sale. Conceptual, cele mai multe sisteme stochiaza informații ca o listă a schimbărilor bazate pe fișiere. Aceste sisteme (CVS, Subversion, Perforce, Bazaar, și așa mai departe), percep informațiile pe care le păstrează ca un set de fișiere și modificările făcute la fiecare fișier în timp. Git nu stocheaza datele în acest fel. În schimb, Git percepe datele cu care lucreaza mai mult ca un set de snapshot-uri ale unui sistem de fișiere mini. De fiecare dată când un utilizator comite, sau salveaza starea curenta a proiectului în Git, acest sistem creaza de fapt o imagine cu ceea ce toate fișierele arata la acel moment, și stochează o referință la aceasta imagine. Pentru a fi eficient, dacă fișierele nu s-au schimbat, Git nu stochiaza fișierul din nou, doar un link la fișierul identic anterior stocat. Aceasta este o distincție importantă între Git și aproape toate celelalte VCSS. Sistemul GIT a reconsiderat aproape fiecare aspect de control al versiunii pe care cele mai multe alte sisteme le-au copiat de la generațiile anterioare.
Cele mai multe operațiuni în Git au nevoie doar de fișierele și resursele locale pentru a opera – în general, nu sunt necesare informații de pe un alt calculator din rețea. In majoritatea sistemelor CVCs cele mai multe operații au ca principala problema latenta retelei, acest aspect insa a fost imbunatatit in Git. Avand întreaga istorie a proiectului pe discul local, cele mai multe operațiuni se intampla aproape instantaneu. Pentru a parcurge istoria proiectului, Git nu are nevoie de conexiune la server pentru a obține istoria și a o afisa, pur și simplu se citește direct din baza de date locală.
2.5 Jenkins
[10]Jenkins, numit inițial Hudson, este un tool de integrare continuă, open source, scris în Java. Cu o cotă de piață dominantă, Jenkins este utilizat de către echipe de toate dimensiunile, de proiecte într-o mare varietate de limbaje și tehnologii, inclusiv. NET, Ruby, Groovy, Grails, PHP și mai multe, precum și Java. În primul rând, Jenkins este ușor de utilizat. Interfața cu utilizatorul este simplă, intuitivă, și atrăgătoare, și Jenkins în ansamblu are o curbă de învățare foarte scăzut. Sute de plugin-uri open source sunt disponibile, iar numarul acestora creste în fiecare săptămână. O mare parte din popularitate Jenkins vine de la dimensiunea și vitalitatea comunității sale. Comunitatea Jenkins este un grup mare, dinamic, reactiv și primitor, cu useri pasionati, liste de discuții active, canale IRC și un blog foarte vocal. Ritmul de dezvoltare este rapid, cu versiuni ieșind săptămânal cu cele mai recente caracteristici noi, buguri fixate, și actualizări pentru pluginuri. Cu toate acestea Jenkins, de asemenea, satisface utilizatorii care nu sunt confortabili, cu upgrade-uri săptămânale. Pentru cei care prefera un ritm de release mai puțin agitat, există, de asemenea, un sprijin pe termen lung, numit Long Term Support (LTS), aceasta oferind utilizatorilor mai multă stabilitate și un ritm mai lent al schimbarilor.
Există mai multe modalități de a rula Jenkins pe o statie. Una dintre cele mai simple modalități de a rula Jenkins pentru prima dată este de a utiliza Java Web Start. Java Web Start este o tehnologie care permite pornirea unei aplicații Java pe computerul local printr-un URL la o pagină web si vine la pachet cu JRE Java. Acesta va porni un server Jenkins care rulează pe calculatorul, și permits experimentarea cu acesta ca și cum ar fi fost instalat local. Tot ce este nevoie pentru ca aceasta să funcționeze este o versiune recenta (Java 6 sau mai recenta) a Java Runtime Environment (JRE). Java Web Start pare să funcționeze cel mai bine în Firefox. Când se alege optiunea Lansare în oricare dintre siteuri în Firefox, browser-ul va întreba dacă utilizatorul doreste să deschida un fișier numit jenkins.jnlp folosind Java Web Start. Daca se alege optiunea de “ok”Jenkins va fi descarcat pe statia locala. Java Web Start va descarca o versiune particulara de Jenkins o singura data. De atunci, când se face clic pe butonul "Launch" din nou, Java Web Start va folosi copia de Jenkins are deja este descarcat (până la noua versiune). Odata ce a fost descarcat, Jenkins va porni pe statia locala si utilizatorul avand posibilitatea sa monitorizeze activitatea tool-ului printr-o fereastra mica numita "Jenkins Console". Pentru a opri Jenkins, în orice moment, pur și simplu se închide această fereastră. Există, de asemenea, installers pentru principalele sisteme de operare disponibili pe site-ul Jenkins. Pentru utilizatorii Java experimentati exista posibilitatea de a downloda softul si de a-l rula direct din linia de comanda. Indiferent dacă se porneste Jenkins folosind Java Web Start sau din linia de comandă, Jenkins ar trebui ae rulează pe computerul local, in mod implicit pe portul 8080, astfel încât se poate accesa Jenkins în browser-ul web pe http://localhost:8080. Alternativ, dacă userul este familiarizat cu servere de aplicații Java, cum ar fi Tomcat, se poate deploya pur și simplu fisierul WAR Jenkins la serverul applicatie. Dacă se execută Jenkins pe un server de aplicații, URL-ul care se utilizeaza pentru a accesa Jenkins va fi ușor diferite. Pe o instalare Tomcat implicita, se poate accesa Jenkins în browser-ul web pe http://localhost:8080/jenkins. Jenkins poate fi configurat din pagina Manage Jenkins, accesibila prin linkul Manage Jenkins din home page.
Unul dintre avantajele procesului de instalare Jenkins maven este faptul ca poate fi configurat sa lucreze cu diferiti agenti de build de tip remote. Se poate defini o modalitate standard de instalare Maven pentru toate serverele de build (descărcarea de pe Internet, dezarhivarea unui pachet de distribuție pe un server partajat, etc), toate aceste opțiuni vor putea fi configurate in mommentul in care se adauga un nou build agent de tip remote sau cand se seteaza un nou server ce utilizează această configurație Jenkins.
Folosind plugin-uri, se pot obține, diferite tipur de notificari, de la trimiterea de mesaje instant sau mesaje SMS, pana la posturi pe Twitter. Totul depinde de ceea ce funcționează cel mai bine pentru cultura organizational. Ultimul lucru ce trebuie configurat inainte de a utiliza Jenkins este toolul de control al versiunii. Jenkins ofera suport pentru Subversion și CVS by default, dar va trebui să se instaleze plugin-ul Git Jenkins pentru ca o aplicatie stocata in GIT sa poata fi rulata din Jenkins. Acest proces este foarte simplu si presupune desciderea ferestrei “Plugin Configuration” ce se poate accesa prin linkul Manage Plugins din pagina principala de configurare.
Build joburile reprezinta centrul procesului de build. Un Jenkins build job este defapt un task particular sau o etapa in procesul de build. Acest lucru poate implica pur și simplu compilarea codului sursă și efectuarea testelor de unitate.
Două dintre cele mai frecvent utilizate variante de builduri sunt: freestyle și Maven. Proiectele free-style permit configurarea a oricarui tip de build, acestea sunt extrem de flexibile și foarte usor configurabile. Buildurile Maven se bazează pe înțelegerea structurii de proiect Maven, și poate folosi acest lucru pentru a configura Maven build jobs cu mai puțin efort și câteva caracteristici suplimentare. Există, de asemenea, plugin-uri care oferă suport pentru alte tipuri de builduri. Cel mai usor mod de configurare ramane insa pentru proiectele free-style. Pentru crearea unui astfel de job se selecteaza optiunea „Build a free-style software project” din pagina „New Job”. Dupa ce utilizatorul alege un nume potrivit jobului, Jenkins va afișa fereastra de configurare a proiectului. Jenkins functioneaza prin verificarea codului sursă al proiectului și construirea acestuia în propriul workspace.
3 Implementare Software
3.1 Prezentare Generala
Sistemul de test automat a fost creat folosind trei software-uri diferite: Java, Git si Jenkins. Cele trei tool-uri diferite formeaza framework-ul de test pentru testarea aplicatiei online www.domo.ro.
Clientul utilizat pentru java a fost Eclipse IDE Indigo Service Release 1. De asemenea plugin-urile principale folosite pentru scrierea si rularea testelor automate direct din Eclipse sunt: selenium-java-2.24.1 si junit-4.10. Prin intermendiul acestor plugin-uri a fost posibila definirea a 110 teste automate pentru aplicatia online: www.domo.ro. Prin folosirea user-agent-ului: „Mozilla/5.0 (Linux; U; Android 4.0.3; de-ch; HTC Sensation Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30”, environmentul simulat este: Android 4.0.3. Proiectul creat este de tip Maven, insa nu a fost necesar instalarea plugin-ului Maven deoarece Eclipse Indigo ofera suport implicit pentru acest soft. Pentru integrarea Eclipse – Git si versionarea codului pe Github a fost instalat in Eclipse plugin-ul: Eclipse EGit.
Testele sunt rulate pe browserul Mozzila Firefox 21.0. Pentru identificarea diferitelor elemente html din aplicatia online folosita pentru test a fost utilizat tool-ul Firebug 1.10.6.
Ca si tool de control asupra versiunii diferitelor release-uri ale codului java pentru testele scrise, a fost utilizat Github. Acest tool se gaseste la adresa: https://github.com/. Crearea unui user si folosirea repository-urilor publice este gratuita pe Github. Astfel repository-ul creat pentru stocarea testelor automate este de tip: public si se numeste domoProject. Fiind un proiect public, orice user poate face check-out la proiect direct din master – branch-ul principal utilizat pentru commituri.
Softul utilizat pentru continous integration este Jenkins. Softul, dupa ce este instalat se poate rula direct in browser la adresa locala: http://localhost:8080. Pentru integrarea Git – Jenkins si rularea testelor s-au instalat urmatoarele plugin-uri: Git Client Plugin, Git Plugin, Maven 2 Project Plugin.
Scopul principal al proiectului a fost crearea unui cadru de test automatizat si studiul asupra integrarii diferitelor tool-uri pentru a obtine rezultatele dorite. Acest tip de testare se utilizeaza deobicei pentru partea de regresie a unei aplicatii care este in dezvoltare. Astfel sunt intrduse functionalitati noi in proiect iar testele automate se folosesc pentru a verifica faptul ca nicio functionalitate nou introdusa nu a afectat in vreun fel sistemul si caracteristicile acestuia. Aplicatia www.domo.ro este deja existenta pe piata si nu presupune schimbari majore, din aceasta cauza scopul principal al testelor este de a confirma functonalitatea si nu de a gasi defecte.
3.2 Diagrama Proiectului
Diagrama 3. Diagrama cadrului de testare automata
3.3 Structura Proiectului domoProject in Eclipse IDE
Proiectul domoProject a fost create in Eclipse IDE si este de tip Maven. Un astfel de proiect se poate crea prin accesarea optiunilor: File-New Project – Maven –Maven Project. Structura acestuia poate fi observata in imaginea de mai jos:
Img 3. Structura Proiectului domoProject
Fisierele sursa ale proiectului sunt grupate in 7 pachete impartite la randul lor in 2 foldere.
src/main/java
com.domo.selenium.util
src/test/java
com.domo.selenium.CosCumparaturi
com.domo.selenium.General
com.domo.selenium.HardExtern
com.domo.selenium.Notebook
com.domo.selenium.Smartphones
com.domo.selenium.TVLED
In pachetul .util au fost definite 4 fisiere clase ajutatoare: Constants.java, FileUtil.Java, logger.java si WebDriverHelper.java.
Img 3. Clasele Ajutatoare
Clasa Constants a fost creata pentru a stoca constante de tip public final static String/int. In aceste constante sunt stocate doua tipuri de informatii: elemente de UI care sunt verificate mai apoi in teste sau cai de acces pentru diferite elemente din pagina. Un exemplu pentru prima categorie ar putea fi: public final static String Contact_C2 ="Tel: 021.319.81.96 (Romtelecom), 0372.679.101 (Vodafone)". In constanta Contact_C2 sunt stocate informatii de pe pagina web legate care vor fi testate prin testul TestContact din clasa Contact.java din pachetul com.domo.selenium.General. Un exemplu pentru cea de a doua categorie mentionata mai sus este: public final static String domo_contact_display_contact_xpath = "/html/body/div/table /tbody/tr[3]/td[3]/table/tbody/tr/td". In constanta domo_contact_display_contact_xpath este stocata calea xpath catre un anumit element din UI, respectiv contactul stocat in constanta Contact_C2. Deoarece exista elemente diferite de UI pe pagini diferite ale aceleiasi aplicatii, care folosesc aceasi cale de acces la element, folosiea constantelor pentru a retine calea de acces catre elementele din pagina, este o buna metoda de a usura munca de refactorizare a codului in cazul in care caile de acces se modifica (ex: se schmba xpath-ul, se modifica calea CSS). Astfel este nevoie de o singura modificare a contantei ce retine xpath-ul elementelor din pagina web pentru ca schimbarea sa aiba loc in toate testele unde se foloseste acel xpath.
Clasa FileUtil.java a fost construita pentru a usura munca scrierii testelor automate. Aceasta clasa este formata din mai multe metode ajutatoare care faciliteaza interactiunea testelor cu diferite tipuri de fisiere. Metodele cuprinse sunt: loadPropertiesBundle(String bundleName, Locale locale), loadPropertiesBundle(String bundleName), loadPropertiesFromFile(String propertiesFile), storeProperty(String filePath, String propertyKey,String propertyValue), String getPropertyAsString(String key), getPropertyAsInteger(String key), getPropertyAsDouble(String key), String readFromExcel(String fileName, String sheetName,int rowNumber, int cellNumber), HSSFWorkbook getWorkbook(String name), getExcelRowsNumber(String fileName, String sheetName), String getTagText(String xmlString, String tagName), getValueOfTagAttribute(String xmlString, String tagName,String attribute), getFileContentsAsString(String fileName). Exista trei formate de fisiere pentru care au fost concepute metodele, si anume: fisiere de tip txt: fisiere de proprietati, fisiere xls si fisiere xml. Pentru testele scrise in acest framework am utilizat metodele ce interactioneaza cu fisiere de tip xls. Prima metoda este:
public String readFromExcel(String fileName, String sheetName,
int rowNumber, int cellNumber) throws IOException {
HSSFWorkbook workbook = getWorkbook(fileName);
HSSFSheet payments = workbook.getSheet(sheetName);
HSSFRow row = payments.getRow(rowNumber);
HSSFCell cell = row.getCell(cellNumber);
switch (cell.getCellType()) {
case HSSFCell.CELL_TYPE_BOOLEAN:
return String.valueOf(cell.getBooleanCellValue());
case HSSFCell.CELL_TYPE_STRING:
return cell.getStringCellValue();
case HSSFCell.CELL_TYPE_NUMERIC:
return String.valueOf(cell.getNumericCellValue());
}
return null;
}
Aceasta metoda este utilizata pentru a prelua anumite valori de tip String dintr-un fisier .xls iar aceste valori sunt apoi folosite in cadrul testelor automate. Deoarece lucrand cu fisiere .xls este important sa se cunoasca si locatia celulei de unde se preiau sau unde se scriu date, metoda getExcelRowsNumber(String fileName, String sheetName) este de asmenea foarte utila. Parametrii acceptati de metoda sunt: numele fisierului .xls, numele paginii de unde se oreste sa se preia date, numarul liniei si numarul coloanei. Prin acestea se identifica unic un element de tip string din cadrul documentului.
public int getExcelRowsNumber(String fileName, String sheetName)
throws IOException {
// get rows number
HSSFWorkbook workbook = getWorkbook(fileName);
HSSFSheet payments = workbook.getSheet(sheetName);
return payments.getPhysicalNumberOfRows();
// return rows;
}
Aceasta este o metoda foarte simpla prin care se returneaza numarul de lini pe care il are un fisier .xls. Parametrii acceptati sunt: numele fisierului si numele paginii. Ambele metode utilizeaza obiecte de tip HSSFWorkbook, astfel un rol important in lucrul cu fisiere xls il are si metoda private private HSSFWorkbook getWorkbook(String name):
private HSSFWorkbook getWorkbook(String name) throws IOException {
if (workbooks.get(name) == null) {
FileInputStream fis = new FileInputStream(new File(name));
FISs.add(fis);
HSSFWorkbook workbook = new HSSFWorkbook(fis);
workbooks.put(name, workbook);
}
return workbooks.get(name);
}
Un alt tip de fisiere care se foloseste destul de des in testele automate sunt fisierele de proprietati. Acestea sunt fisiere text in care sunt stocate proprietati in formatul: proprietate=valoare. In testele din acest proiect, pentru stocarea dieritelor proprietati s-a folosit clasa Constants.java. Cu toatea acestea metodele care au fost implementate pentru acest tip de fisiere pot fi utilizate in cazul in care framework-ul de test este extins si sunt incluse mai multe teste. Astfel cele mai importante metode create pentru lucrul cu fisiere de proprietati sunt:
public void loadPropertiesBundle(String bundleName, Locale locale) {
ResourceBundle bundle = ResourceBundle.getBundle(bundleName, locale);
bundles.put(bundleName, bundle);
}
Metoda de mai sus incarca un fisier de proprietati de la locatia locale. Acelas scop il are si metoda de mai jos care foloseste insa locatia default: src/main/resources:
public void loadPropertiesBundle(String bundleName) {
ResourceBundle bundle = ResourceBundle.getBundle(bundleName);
bundles.put(bundleName, bundle);
}
Principalele actiuni care pot fi realizate cu fisierele de proprietati sunt: stocarea unei proprietati, preluarea unei proprietati de tip String, preluare unei proprietati de tip Integer, preluare unei proprietati de tip Double. Metoda de stocare a proprietatilor:
public void storeProperty(String filePath, String propertyKey,
String propertyValue) {
Properties properties = new Properties();
File file = new File(filePath);
FileInputStream inputStream = null;
FileOutputStream outputStream = null;
try {
// create the properties file if it does not exist.
if (!file.exists()) {
file.createNewFile();
}
// read all properties from the file
inputStream = new FileInputStream(file);
properties.load(inputStream);
inputStream.close();
// add the new property
properties.put(propertyKey, propertyValue);
// store all properties to the same file
outputStream = new FileOutputStream(file);
properties.store(outputStream, null);
outputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Parametrii acceptati de aceasta metoda sunt: calea catre fisierul de proprietati, numele proprietatii si valoarea acesteia. Daca fisierul exista deja noua cheie va fi adaugata in el iar daca nu exista, un nou fisier va fi creat. De asemenea se poate suprascrie o cheie deja existenta. Pentru a putea prelua date de tip integer din fisierele de proprietati se utilizeaza metoda:
public int getPropertyAsInteger(String key) {
for (ResourceBundle bundle : bundles.values()) {
try {
if (bundle.getString(key) != null) {
return Integer.parseInt(bundle.getString(key));
}
} catch (Exception e) {
}
}
return -1;
}
In cazul in care se incearca returnarea datelor dintr-o proprietate care nu exista, metoda va returna o exceptie.
Clasa WebDriverHelper este deosebit de importanta pentru dezvoltatorul testelor automate. Aceasta clasa pune la dispozitia acestuia multiple metode ce faciliteaza interactiunea cu elementele de UI din pagina web si alte metode ajutatoare. Una dintre aceste meode ce a fost utilizata in toate testele automate din acest framework este: screenShoter:
public void screenShooter(String errorLocation, WebDriver driver){
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
try {
String filename = "src/test/resources/screenshots/"+"test_"+errorLocation+"_failed.png";
FileUtils.copyFile(scrFile, new File(filename));
} catch (IOException e) {System.out.println("Couldn't take the screenshot ");}
}
Metoda este apelata in fiecare test in momentul cand se face un assert – cand se verifica o anumita conditie pe pagina. In cazul in care acea conditie nu este indeplinita si testul este considerat picat, prin apelarea metodei screenshooter, se va face screenshoot la ultima pagina web accesata de webDriver. Astfel este mai usor ca in momentul in care se face analiza testelor picate sa se gaseasca motivul pentru care acestea nu au reusit sa fie passed. Metoda primeste ca si parametrii driverul si o variabila de tip String prin care se pot adauga date suplimentare despre imagine (de ex: numele testului care a dus la crearea imaginii). Calea in care screenshot-ul va fi stocat este src/test/resources/screenshots/ iar numele acestuia are formatul: test+locatia_erorii+failed.
Alte metode foarte simple dar folosite in multe dintre teste si avand o uilitate foarte mare sunt: waitForElementPresent(final By by, final int maximumSeconds), waitForTextPresent(final String text, final int maximumSeconds), waitForElementDisplayed(final By by, final int maximumSeconds), checkForTextPresentOnThePage(String text), selectRadioButtonByValue, isRadioButtonValueSelcted, selectWindowByTitle, getDriverWithUserAgent(String userAgent).
Deoarece paginile web au diferiti timpi de incarcare in functie de cantitatea de date stocata in pagina, de conexiune, de interactiunea cu alte elemente web, metodele: waitForElementPresent si isElementPresent sunt foarte importante pentru ca dezvoltatorul testelor automate sa stie exact cand poate accesa un anumit element de pe pagina web si sa nu incerce sa il acceseze inainte ca acesta sa fie incarcat. Aces din urma caz fiind foarte des intalnit ca o cauza a testelor failed.
public boolean isElementPresent(By by) {
try {
driver.findElement(by);
} catch (Exception e) {
return false;
}
return true;
}
public void waitForElementPresent(final By by, final int maximumSeconds) {
(new WebDriverWait(driver, maximumSeconds))
.until(new ExpectedCondition<WebElement>() {
public WebElement apply(WebDriver error1) {
WebElement error = driver.findElement(by);
return error;
}
});
}
In ambele metode principalul parametru este o variabiala de tip By prin care se trimite modul in care se acceseaza un element din pagina web. Alte doua metode care au scop similar: verifica daca un text apare pe o pagina web sau asteapta ca un text sa se incarce pe o pagina web sunt:
public void waitForTextPresent(final String text, final int maximumSeconds) {
(new WebDriverWait(driver, maximumSeconds))
.until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver error1) {
WebElement error = driver.findElement(By
.tagName("body"));
return error.getText().contains(text);
}
});
}
public boolean checkForTextPresentOnThePage(String text) {
WebElement body = driver.findElement(By.tagName("body"));
return body.getText().contains(text);
}
In metodele de mai sus apare parametrul maximumSeconds care da posibilitatea utilizatorului sa setez un anumit interval de timp, pana la care metoda va astepta ca elementul web / textul sa se incarce in pagina web. Daca elementul nu se incarca in acest interval de timp metodele vor returna o eroare. Folosirea metodei checkForTextPresentOnThePage este mai putin recomandata deoarece aceasta pentru a putea verifica daca textul dat de utilizator prin parametrul text, apare pe pagina, citeste tot codul sursa al paginii si astfel timpul de rulare a unui test ce apeleaza aceasta metoda va creste simtitor.
Alte metode care dau posibilitatea utilizatorului de a lucra cu elemente web de tip drop-down sunt: selectOptionFromDropdownByValue, selectOptionFromDropdownByDisplayText, isTextSelectedInDropDown, isValueSelectedInDropDown si deselectAllDropDownOptions.
Cele doua metode prin care se verifica daca exista o anumita valoare / text intr-o lista drop-down sunt:
public boolean isTextPresentInDropDown(By dropDown, String text) {
WebElement element = driver.findElement(dropDown);
List<WebElement> options = element.findElements(By
.xpath(".//option[normalize-space(.) = " + escapeQuotes(text)
+ "]"));
return options != null && !options.isEmpty();
}
public boolean isValuePresentInDropDown(By dropDown, String value) {
WebElement element = driver.findElement(dropDown);
StringBuilder builder = new StringBuilder(".//option[@value = ");
builder.append(escapeQuotes(value));
builder.append("]");
List<WebElement> options = element.findElements(By.xpath(builder
.toString()));
return options != null && !options.isEmpty();
}
De asemenea selectarea unei optiuni din drop-down, valoare sau text, se poate face prin metodele:
public void selectOptionFromDropdownByValue(By dropDown, String value) {
Select select = new Select(driver.findElement(dropDown));
select.selectByValue(value);
}
public void selectOptionFromDropdownByDisplayText(By dropDown,
String displayText) {
Select select = new Select(driver.findElement(dropDown));
select.selectByVisibleText(displayText);
}
Exista situatii care pot aparea in teste, in care utilizatorul, ia o decizie pe baza optiunilor dintr-un element de tip drop-down. Astfel este important ca utilizatorul sa stie daca si care optiuni sunt selectate. Metodele prin care se ofera acces la aceasta informatie sunt:
public boolean isTextSelectedInDropDown(By dropDown, String displayText) {
WebElement element = driver.findElement(dropDown);
List<WebElement> options = element.findElements(By
.xpath(".//option[normalize-space(.) = "
+ escapeQuotes(displayText) + "]"));
for (WebElement opt : options) {
if (opt.isSelected()) {
return true;
}
}
return false;
}
public String getSelectedValue(By dropDown) {
Select select = new Select(driver.findElement(dropDown));
String defaultSelectedValue = select.getFirstSelectedOption().getText();
return defaultSelectedValue;
}
Pentru a simula ca pagina web este deschisa pe un environment diferit decat cel care este instalat pe masina pe care se ruleaza testele, s-a utilizat un plugin de firefox: user-agent. Prin setarea diferitilor user-agents se pot simula diferite sisteme de operare. Pentru testele din acest framework s-a utilizat ca si user agent: Mozilla/5.0 (Linux; U; Android 4.0.3; ko-kr; LG-L160L Build/IML74K) AppleWebkit/534.30 (KHTML, like Gecko)Version/4.0 Mobile Safari/534.30. Prin folosirea acestuia se simuleaza platforma: Android 4.0.3. Pentru a se putea realiza acest lucru, metoda getDriverWithUserAgent(String userAgent) a fost utilizata in toate testele automate.
public static FirefoxDriver getDriverWithUserAgent(String userAgent) {
FirefoxProfile profile = new FirefoxProfile();
profile.setPreference("general.useragent.override", userAgent);
profile.setAcceptUntrustedCertificates(true);
profile.setAssumeUntrustedCertificateIssuer(false);
DesiredCapabilities cap = new DesiredCapabilities();
cap.setCapability(FirefoxDriver.PROFILE, profile);
// cap.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);
FirefoxDriver driver = new FirefoxDriver(cap);
return driver;
}
Acelasi scop il are si metoda de mai jos insa are optiunea de a seta Java Script On sau Off:
public static WebDriver getDriverWithUserAgentAndJavascriptOnOrOff(
String userAgent, boolean javascriptEnabled) {
FirefoxProfile profile = new FirefoxProfile();
profile.setPreference("general.useragent.override", userAgent);
profile.setPreference("javascript.enabled", javascriptEnabled);
WebDriver driver = new FirefoxDriver(profile);
return driver;
}
Clasa logger este o alta clasa ajutatoare importanta care contine o singura metoda: Log(String LOG_FILE, String MESSAGE). Aceasta este de asemenea utilizata in toate clasele de test. Metoda Log este utilia deoarece scopul acesteia este de a adauga diferite comentari din teste in fisierul din pachetul de resurse: REPORT.log. Astfel prin introducerea comentariilor in teste in momente cheie din test si prin logarea acestora in fisierul .log, cel care logheaza testele poate intelege mai bine de ce un test a picat si care este cea mai probabila cauza. De asmenea fisierul contine si ora la care s-a logat informatie in el.
public class logger {
public static void Log(String LOG_FILE, String MESSAGE) throws IOException{
FileWriter fstream;
fstream = new FileWriter(LOG_FILE,true);
BufferedWriter out_file = new BufferedWriter(fstream);
Date timeStamp = new Date();
out_file.write("["+timeStamp+"] " + MESSAGE); // REPORT.log file writer
System.out.println("["+timeStamp+"] " + MESSAGE); //console file writer
out_file.newLine();
out_file.flush();
out_file.close();
}
}
3.4 Clasele De Test
Testele automate sunt scrise cate una in fiecare clasa de test iar acestea sunt grupate in 6 pachete de test: com.domo.selenium.CosCumparaturi, com.domo.selenium.General, com.domo.selenium.hardExtern,com.domo.selenium.Notebook,com.domo.selenium.Smartphones, com.domo.selenium.TVLED. Numele pachetelor a fost astfel ales incat sa reprezinte zona din pagina web unde s-au realizat testele din pachetul respectiv iar numele claselor de test a fost ales astfel incat sa reprezinte punctual caracteristica sau functia care a fost testata. Astfel:
com.domo.selenium.CosCumparaturi – 3 teste legate de diferite scenarii in care userul face diferite achizitii de pe pagina web
com.domo.selenium.General – 7 teste pentru verificarea diferitelor elemente de Ui din pagina web:
Contact
CumCumpar
Logo
MagazineDomo
Rate
Service
TelefonComenzi
com.domo.selenium.HardExtern – 12 teste realizate pe pagina de vanzare a produselor hard extern pentru diferitele optiuni de display a produselor si 1 test pentru verificarea pretului produselor. Testele verifica optiunile de:
Capacitate
Interfata
Marca
Interval de pret
Pret per produs
com.domo.selenium.Notebook – 21 teste realizate pe pagina de vanzare a produselor: laptop pentru diferitele optiuni de display a produselor si 1 test pentru verificarea pretului produselor. Testele verifica optiunile de:
Diagonala
Marca
Interval de pret
Pret per produs
com.domo.selenium.Smartphones – 26 teste realizate pe pagina de vanzare a produselor: smartphones pentru diferitele optiuni de display a produselor si 1 test pentru verificarea pretului produselor. Testele verifica optiunile de:
Marca
Memorie
Interval de pret
Rezolutie
Pret per produs
com.domo.selenium.TVLED – 26 teste realizate pe pagina de vanzare a produselor: televizore led pentru diferitele optiuni de display a produselor si 1 test pentru verificarea pretului produselor. Testele verifica optiunile de:
Diagonala
Marca
Interval de pret
Optiune 3D
Pret per produs
Img 4. Clasele de Test
Clasa CosCumparaturi_Scenariul2 contine metoda de test TestScenariul2(). Clasa este publica si inainte de metoda de test sunt realizate urmatoarele setari: initializarea unui obiect (d) de tip FirefoxDriver folosind si optiunea de user agent, initializarea unui obiect (h) de tip WebDriverHelper, si o variabila statica de tip Strng care reprezinta calea catre fisierul REPORT.log. De asemenea sub adnotatia @Before a fost creata metoda publica void doSetup() in ca sunt sterse toate cookie-urile si obiectului de tip FirefixDriver (d) ii este atribuit adresa http catre pagina web. De asemenea inainte de metoda de test este descris scenariul propus in aces test.
public class CosCumparaturi_Scenariul2 {
FirefoxDriver d =WebDriverHelper.getDriverWithUserAgent(Constants.USER_AGENT);
WebDriverHelper h = new WebDriverHelper(d);
static String LOG_FILE = "src/test/resources/REPORT.log";
@Before
public void doSetup()
{
d.manage().deleteAllCookies();
d.get(Constants.SITE);
}
/**
* Scenariul 2: Un user nou pe site adauga in cosul de cumparaturi un produs (televizor).
* Verific pretul produsului in sectiunea Cos Cumparaturi, atat pe pagina Pasul1 cat si Pasul2
* @throws IOException
*
*/
Metoda de test se afla sub adnotatia @Test si se numeste TestScenariul2(). Prima linie de cod scrisa in aceasta metoda reprezinta apelarea fisierului de logare pentru ca la inceputul executiei testului sa se logheze in fisierul REPORT.log numele testului si sceariul pe care acesta il propune. Apoi se foloseste metoda ajutatoare waitForElementPresent pentru a astepta incarcarea logoului pagini, aceasta insemnand ca pagina web a fost incarcata. Dupa aceea se acceseaza linkul catre sectiunea Televizoare & Home cinema si mai departe catre seciunea LED TV. Apoi se acceseaza xpathul catre primul produs din lista de televizoare.
@Test
public void TestScenariul2() throws InterruptedException, IOException
{
logger.Log(LOG_FILE, "TestScenariul 2: Un user nou pe site adauga in cosul de cumparaturi un produs (televizor). Verific pretul produsului in sectiunea Cos Cumparaturi, atat pe pagina Pasul1 cat si Pasul2");
h.waitForElementPresent(By.className("logo"), 5);
d.findElement(By.linkText("Televizoare & Home cinema")).click();
Thread.sleep(2000);
if (h.isElementPresent(By.linkText("LED TV"))==false)
{
d.navigate().back();
Thread.sleep(3000);
d.findElement(By.linkText("Televizoare & Home cinema")).click();
}
d.findElement(By.linkText("LED TV")).click();
d.findElement(By.xpath(String.format(Constants.domo_product_name_xpath, 1,1))).click();
Dupa ce a fost selectat produsul (televizorul), de pe pagina acestuia se stocheaza pretul produsului in variabila price1. Apoi se selecteaza optiunea de a adauga produsul in cos.
//stochez pretul
h.waitForElementPresent(By.xpath("/html/body/div/div[3]/form/div[2]/div[3]/table/tbody/tr[2]/td/div/span/strong"), 5);
String price1 = d.findElement(By.xpath("/html/body/div/div[3]/form/div[2]/div[3]/table/tbody/tr[2]/td/div/span/strong")).getText();
System.out.println(price1);
//adaug in cos
d.findElement(By.xpath("/html/body/div/div[3]/form/div[2]/div[3]/table/tbody/tr[3]/td/div/span/input")).click();
Pe pagina dedicata cosului de cumparaturi se verifica pretul produsului ca fiind acelasi cu pretul produslui de pe pagina destinata cumparaturilor. In cazul in care preturile difera se loheaza in fisierul REPORT faptul ca testul a picat si de asemenea se face un screenshot pe pagina destinata cosului de cumparaturi pentru a se vedea exact valoare produsului pe acesta pagina. Daca testul trece de acesta verificare se testeaza de asmenea si prezenta butonului Pasul2. Prin aceasta se verifica posibilitatea utilizatorului de a continua procesul de cumparare.
//verific pret pe pagina Pasul1
String price2 = d.findElement(By.xpath("/html/body/div/table/tbody/tr[3]/td/table/tbody/tr[5]/td[4]/strong")).getText();
//Compar preturile
if (price1.equals(price2)!=true)
{
logger.Log(LOG_FILE, "TestScenariul2: TEST FAILLED !!!");
h.screenShooter("TestScenariul2", d);
}
assertEquals(price1, price2);
//Verific butonul Pasul2
if (h.isElementPresent(By.name("Pasul2"))!=true)
{
logger.Log(LOG_FILE, "TestScenariul2: TEST FAILLED !!!");
h.screenShooter("TestScenariul2", d);
}
assertTrue(h.isElementPresent(By.name("Pasul2")));
Dupa ce utilizatorul a ajuns pe pagina Pasul2 din procedeul de cumparare on-line, se verifica ca pretul cumparaturilor –Total plata – ramas acelasi (deoarece utilizatorul a adaugat in cosul de cumparaturi un singur produs) ca si pe pagina originala unde a fost prezentat produsul cat si pe pagina Pasul1 daca testul trece de toate verificarile in fisierul de log se logheaza urmatorul mesaj: "TestScenariul2: TEST PASSED"
//verific pretul pe pagina Pasul2
d.findElement(By.name("Pasul2")).click();
Thread.sleep(2000);
if (h.isElementPresent(By.id("TotalPlata"))==false)
{
d.navigate().back();
Thread.sleep(3000);
d.findElement(By.name("Pasul2")).click();
}
String price3 = d.findElement(By.id("TotalPlata")).getText();
System.out.println(price3);
String price2_int = h.SplitString1(price2);
System.out.println(price2_int);
if (price3.contains(price2_int)!=true)
{
logger.Log(LOG_FILE, "TestScenariul2: TEST FAILLED !!!");
h.screenShooter("TestScenariul2", d);
}
else
logger.Log(LOG_FILE, "TestScenariul2: TEST PASSED");
assertTrue(price3.contains(price2_int));
Dupa metoda de test se implementeaza sub adnotatia @After metoda publica quitDriver() . Prin aceasta se elibereaza resursele din obiectul de tip FirefoxDriver (d).
@After
public void quitDriver()
{
d.quit();
}
Clasa Contact.java este o alta clasa de test din pachetul General. Aceasta clasa contine de asemenea o singura metoda de test care are numele: TestContact() si scopul acesteia, definit in commenturile din inceputul metodei, este de a verifica ca diferitele metode te contact pe care le are la dispozitie vizitatorul paginii web sunt afisate in mod corespunzator si corect in pagina. Inaintea metodei de test este implementata sub adnotatia @Before (la fel ca si in toate clasele de test) aceeasi metoda doSetup() in care sunt sterse toate cookie-urile din browser si este atribuit obiectului d calea http catre siteul supus testarii, prin apelarea constantei SITE din clasa Constants.
@Before
public void doSetup()
{
d.manage().deleteAllCookies();
d.get(Constants.SITE);
}
/**
* TestContact(): Verifica anumite informatii legate de "Contacte" (telefon, call center, adresa)
* @throws IOException
*
*/
Testul in sine este format din mai multe verificari care se aplica pe elementele de UI reprezentand contactele pe care le ofera siteul vizitatorilor acestuia. Astfel contactele sunt: telefon, Call-Center, fax, telverde si casuta postala. Datele pentru aceste contacte sunt stocate in constante din clasa Constants si sunt apelate in momentul in care se face o verificare pe una dintre acestea. De asemenea la fiecare verificare daca aceasta nu se dovedeste a fi indeplinita, testul este considerat picat si se logheaza cauza ce a dus la aceasta situatie si se face screenshot pe ultima pagina inainte ca driverul sa elibereze resursele.
@Test
public void TestContact() throws InterruptedException, IOException
{
logger.Log(LOG_FILE, "TestContact(): Verifica anumite informatii legate de Contacte (telefon, call center, adresa)");
h.waitForElementPresent(By.className("logo"), 5);
d.findElement(By.linkText("Contact")).click();
Thread.sleep(3000);
//Contact
if (d.findElement(By.xpath(Constants.domo_contact_display_contact_xpath)).getText().contains(Constants.Contact_C1)==false)
{
logger.Log(LOG_FILE, "TestContact(): "+Constants.Contact_C1+"not found TEST FAILLED !!!");
h.screenShooter("TestScenariul1", d);
}
assertTrue(d.findElement(By.xpath(Constants.domo_contact_display_contact_xpath)).getText().contains(Constants.Contact_C1));
//Telefon
if (h.checkForTextPresentOnThePage(Constants.Contact_C2)==false)
{
logger.Log(LOG_FILE, "TestContact():"+Constants.Contact_C2+"not found TEST FAILLED !!!");
h.screenShooter("TestScenariul1", d);
}
assertTrue(h.checkForTextPresentOnThePage(Constants.Contact_C2));
//CallCenter
if (h.checkForTextPresentOnThePage(Constants.Contact_C3)==false)
{
logger.Log(LOG_FILE, "TestContact(): "+Constants.Contact_C3+"not found TEST FAILLED !!!");
h.screenShooter("TestScenariul1", d);
}
assertTrue(h.checkForTextPresentOnThePage(Constants.Contact_C3));
//FAX
if (h.checkForTextPresentOnThePage(Constants.Contact_C4)==false)
{
logger.Log(LOG_FILE, "TestContact(): "+Constants.Contact_C4+"not found TEST FAILLED !!!");
h.screenShooter("TestScenariul1", d);
}
assertTrue(h.checkForTextPresentOnThePage(Constants.Contact_C4));
//Telverde
if (h.checkForTextPresentOnThePage(Constants.Contact_C5)==false)
{
logger.Log(LOG_FILE, "TestContact(): "+Constants.Contact_C5+"not found TEST FAILLED !!!");
h.screenShooter("TestScenariul1", d);
}
assertTrue(h.checkForTextPresentOnThePage(Constants.Contact_C5));
//Posta
if (h.checkForTextPresentOnThePage(Constants.Contact_C6)==false)
{
logger.Log(LOG_FILE, "TestContact(): "+Constants.Contact_C6+"not found TEST FAILLED !!!");
h.screenShooter("TestScenariul1", d);
}
else
logger.Log(LOG_FILE, "TestContact(): TEST PASSED");
assertTrue(h.checkForTextPresentOnThePage(Constants.Contact_C6));
}
Clasa PretHDD cuprinde metoda de test: TestPretHDD(). Aceasta metoda a fost creata pentru a verifica corespondenta dintre un anumit produs de pe pagina web si pretul acestuia. Pentru a stoca datele initiale s-a creat un fisier excel: PreturiProduse.xls care cuprinde preturile produselor de tip: HardExtern, Notebook, Smartphnes si TV-LED. Prin acest tip de teste se verifica ca orice produs din aceasta gama are un corespondent corect in pretul afisat pe pagina web. Ca si in cazul celorlalte teste, prima actiune este logarea numelui testului si a scenariului propus de acesta. Apoi se asteapta ca pagina sa fie incarcata si se verifica daca utilizatorul a ajuns pe pagina corecta: titlul paginii trebuie sa fie ”Hard”. In cazul in care nu a fost accesata pagina corespunzatoare: se logheaza urmatoarea eroare: "TestPretHDD(): Wrong page TEST FAILLED !!!", se face screenshot si rularea testului se opreste, acesta fiind considerat picat.
public void TestPretHDD() throws InterruptedException, IOException
{
logger.Log(LOG_FILE, "TestPretHDD(): Verifica pretul produselor HDD pe baza fisierului: PreturiProduse.xls");
//verific daca sunt pe site-ul bun
h.waitForElementPresent(By.xpath(Constants.domo_product_first_title_xpath), 5);
if (d.findElement(By.xpath(Constants.domo_product_first_title_xpath)).getText().contains("Hard")==false)
{
logger.Log(LOG_FILE, "TestPretHDD(): Wrong page TEST FAILLED !!!");
h.screenShooter("TestPretHDD", d);
}
assertTrue(d.findElement(By.xpath(Constants.domo_product_first_title_xpath)).getText().contains("Hard"));
Urmatoarea etapa in test reprezinta definirea unui obiect de tip FileUtil pentru a putea manipula fisierul PreturiProduse.xls. Cu ajutorul metodei getExcelRowsNumber se retine intr-o variabila numarul de linii din fisier si se definesc de asemenea alte doua variabile array pentru stocarea numelui si pretului produsului. Folosind un ciclu for se citesc si se insereaza datele din fisierul excel in cele doua array-uri.
//retin numarul de produse din coloana excelului
f = new FileUtil();
c = f.getExcelRowsNumber("src/test/resources/PreturiProduse.xls", "HDD");
System.out.println("Numarul de produe HDD: "+c);
cod = new String [c];
pret = new int [c];
//citesc cod din fisierul excel
for(int i=0; i<c; i++)
{
cod [i]=f.readFromExcel("src/test/resources/PreturiProduse.xls", "HDD", i, 0);
//System.out.println(cod[i]);
pret[i]= Integer.parseInt(h.SplitString3(f.readFromExcel("src/test/resources/PreturiProduse.xls", "HDD", i, 1)));
//System.out.println(pret[i]);
}
Mai departe se utilizeaza ciclul while in care se citeste numele produselor de tip hdd din aplicatia web si se face o cautare a cestora in lista de produse stocate in fiserul PreturiProduse prin intermediul array-urilor anterior definite. Exista 3 situati posibile: produsul sa nu fie gasit in lista din fisier si atunci se returneaza urmatoarea eroare: "TestPretHDD(): Product "+cod_site+" does not appear in DATABASE !!". O alta varianta ar fi ca produsul sa fie gasit in baza de date dar pretul acestuia sa nu corespunda cu pretul de pe pagina web. Si in acest caz se returneaza eroarea: "TestPretHDD(): "+cod_site+" "+amount+" "+"MATCHED DATABASE". In cazurile de mai sus testul este considerat picat si rularea acestuia nu continua. Al treilea caz este cel fericit in care produsul verificat este conform bazei de date iar atunci se logheaza mesajul: "TestPretHDD(): "+cod_site+" "+amount+" "+"MATCHED DATABASE" si se trece mai departe la testarea urmatoarelor produse. Dupa ce toate produsele de pe site au fost verificate, in cazul in care acestea au avut acelasi pret ca si cel din fisierul cu date, testul este considerat passed.
while (b!=true)
{
if (h.isElementPresent(By.xpath(String.format(Constants.domo_product_name_xpath, i,j)))==true)
{
//procesez
cod_site = d.findElement(By.xpath(String.format(Constants.domo_product_name_xpath, i,j))).getText();
logger.Log(LOG_FILE, "TestPretHDD(): Verify product:"+cod_site);
for (int ii=0; ii<c; ii++)
{
n=5;
if (cod_site.contains(cod[ii]))
{
n=n+i;
if (h.isElementPresent(By.xpath(String.format(Constants.domo_product_previous_price_xpath, n,j)))==true)
pret_site = d.findElement(By.xpath(String.format(Constants.domo_product_previous_price_xpath, n,j))).getText();
else
pret_site = d.findElement(By.xpath(String.format(Constants.domo_product_actual_price_xpath, n,j))).getText();
int amount = h.ConvertAmountToInt(pret_site);
if ((pret[ii]==amount)==false)
{
logger.Log(LOG_FILE, "TestPretHDD(): "+cod_site+" "+amount+" "+"did not match DATABASE – TEST FAILLED !!!");
h.screenShooter("TestPretHDD", d);
}
else
logger.Log(LOG_FILE, "TestPretHDD(): "+cod_site+" "+amount+" "+"MATCHED DATABASE");
assertTrue(pret[ii]==amount);
break;
}
if (ii+1==c)
logger.Log(LOG_FILE, "TestPretHDD(): Product "+cod_site+" does not appear in DATABASE !!");
}
//procesez
k++;
j++;
if (j==5)
{
i=i+9;
j=1;
}
}
else
{ if (d.findElement(By.id("NextPage")).isDisplayed()==true)
{
d.findElement(By.id("NextPage")).click();
Thread.sleep(2000);
i=1;
j=1;
}
else
{
b=true;
i=1;
j=1;
}
}
}
}
3. 5 Integrarea Eclipse-Git
Primul pas spre crearea sistemului de integare continua, dupa scrierea testelor automate in Eclipse IDE, este integrarea cu un repository. Pentru acest sistem s-a folosit Git. Uplodarea proiectului pe Git a presupus crearea unui cont pe github la adresa: https://github.com/. Crearea unui cont pe Git se realizeaza foarte uor si este gratuita. Git pune la dispozitia utilizatorilor doua tipuri principale de repository-uri: public – care sunt gratuite si private – care sunt contra cost. Astfel am folosit optiunea public pentru a crea repository-ul domoProject.
Img 5. domoProject Repository
Urmatorul pas a fost instalarea pluginu-ului: eclipse EGit. Acest plugin reprezinta o implementare Java a sistemului de control al versiunii Git. Dupa instalarea plugin-ului pentru a uploda proiectul pe Github in repository-ul creat se realizeaza urmatorii pasi:
1. Se seteaza pluginul git din Preferences – Git.
Img 6. Share Project – Pasul 1
2. Se face click dreapta pe proiect si se alege optiunea Team- Share Project.
Img 7. Share Project – Pasul 2
3. Se selecteaza din lista de optiuni Git.
Img 8. Share Project – Pasul 3
4. Se creaza un repository local si apoi un Working directory este creat automat in folderul Git de pe statia locala.
Img 9. Share Project – Pasul 4
Dupa parcurgerea cu succes a acestor pasi pentru proiectul care se doreste a fi uplodat pe repository va aparea in optiunea Team o lista lunga de optiuni pentru intercatiunea cu Git. Cele mai folosite optiuni pentru proiectu domoProject au fost: Add to index, commit si push. Optiunea add to index se foloseste atunci cand se adauga un fisier nou pe repository. Optiunea commit reprezinta pregatirea fisierului care a fost modificat si se doreste a fi uplodat pe repository iar optiunea de push este defapt comanda prin care se uplodeaza fisierul in Git. Toate optiunile sunt prezentate in imaginea de mai jos.
Img 10. Comenzi Git
Dupa ce a fost realizat un commit schimbarile pot fi vizualizate pe fiecare fisier in parte in repository, pe Github.
Img 11. Commit-uri vizualizate in Github
3.6 Integrare Git-Jenkins
Dupa ce a fost instalat, Jenkins ruleaza pe portul: 8080: http://localhost:8080. Principalele setari pentru acesta se realizeaza accesand linkul „Manage Jenkins”. Astfel utilizatorul este redirectionat in pagina de configurare unde cele mai importante setari sunt legate de instalarea unei versiuni de JDK, Git si Maven. Acestea pot fi instalate in mod automat sau utilizatorul poate da calea catre fisierel sursa. Astfel au fost configurate:
JDK
Name: JDK7
JAVA_HOME: 3.6 Integrare Git-Jenkins
Git
Name: Default
Installation directory: C:\Program Files\Git\bin\git.exe
Maven
Name: Maven
MAVEN_HOME: C:\apache-maven-3.0.5\bin
De asemenea au fost realizate si alte mici setari legate de Jenkins location si Git plugin.
Img 12. Jenkins Main Configurations
Dupa ce principalele configurari au fost realizate pentru ca tool-ul sa fie functional, urmatorul pas spre integrarea dintre Git si Jenkins este este crearea unui Job nou. In Jenkins fiecare proiect de integrare continua este realizat prin asocierea cu un nou job. Astfel noul job creat pentru a clona local si a rula proiectul domoProject din repository-ul de pe Github se a fost numit: NewDomoProject si configurarea acestuia poate fi observata in imaginea de mai jos. Principalele setari au fost: alegerea ca si Source Code Management optiunea Git si setarea locatei repository-ului: https://github.com/horeahosu/domoProject.git. De asemmenea tot in cadrul tabului Source Code Management se alege si branchul de unde se cloneaza si compileaza codul. In cazul proiectului domoProject exista un singur branch: cel principal. Build triggers este o alta optiune care da posibilitatea utilizatorului sa setez un program conform caruia jenkins sa ruleze testele automate. Optiunea Poll SCM aleasa a fost: „0 0 * * *”. Prin setarea acesteia build-urile vor fi efectute in mod automat de Jenkins in fiecare noapte la ora 00:00 a fiecarei zile. Fiecare job are o optiune de Build care este defapt comanda prin care se specifica ce se doreste ca Jenkins sa faca in jobul respectiv. Deoarece proiectul domoProject este de tip maven, tipul de buid ales a fost Invoke top-level maven targets. Aceste targeturi sunt setate defapt in fisierul pom.xml in proiectul Maven din Eclipse. Goal-ul definit in acest build este: clean package. Aceasta comanda va compila codul, va rula testele setate in pom.xml si va genera un fisier de tip JAR. Alte setari se pot realiza pentru confortul utilizatorului: notificari e-mail de fiecare data cand un build este instabil.
Img 13. Jenkins NewDomoProject Configuration
Jenkins pune la dispozitie un sistem prin care ofera utilizatorului o imaginea asupra stabilitatii buildurilor realizate. Astfel de fiecare data cand un build a fost realizat cu succes- toate testele au trecut -„vremea” pentru jobul respectiv este din ce in ce mai buna. In momentul in care in builduri apar si erori, acestea se reflecta printr-o ”vreme” din ce in ce mai ploioasa. De asemenea istoria builurilor poate fi vizualizata in partea stanga a imaginii de mai sus. Aceasta ofera o imagine de ansamblu asupra stabilitatii proiectului. Detalii specifice fiecarui build se vizualizeaza in momentul in care acesta ruleaza si de asemenea si dupa ce a terminat de rulat in formatul ales de utilizator: consola sau vizualizare ca text.
3.7 Rularea Testelor Automate
Testele automate au fost scrise in java prin intermediul Eclipse IDE. Exista 3 modalitati de a rula testele:
1. Direct din Eclipse IDE – testele pot fi rulate manual ca si teste jUnit, rezultatul fiind afisat in consola Eclipse si fisierul REPORT.txt si eventualele screenshot-uri.
Img 14 Rularea testelor ca Junit – optiune
Img 15 Rularea testelor ca Junit – rezultat
2. Direct din Eclipse IDE – proiectul poate fi rulat ca si Maven build, rezultatul fiind afisat in consola Eclipse si fisierul REPORT.txt si eventualele screenshot-uri.
Img 16. Rularea testelor ca Maven Project- optiune
Img 17. Rularea testelor ca Maven Project- rezultat
3 Din Jenkins prin setarea unui job nou atat manual ( prin optiunea Build now) cat si automat prin selectarea unui program de rulare, rezultatele fiind afisate in consola Jenkins si si fisierul REPORT.txt si eventualele screenshot-uri
Img 18. Rularea testelor ca Maven Project- din Jenkins
4 Rezultate Experimentale
Tabelul de mai jos prezinta rezultatele obtinute in urma rularii testelor atat din Eclipse- cat si din Jenkins.
Tabel 2. Rezultate Obtinute
Eclipse:
Tests run: 106, Failures: 24, Errors: 1, Skipped: 0
Total time: 22:25.416s
Jenkins:
Tests run: 106, Failures: 24, Errors: 1, Skipped: 0
Total time: 4:26:28.073s
5. Concluzii
Aceasta lucrare a fost dedicata studiului si implementarii unui sesitem de testarea automata a site-urilor web. Deoarece marea majoritate a aplicatiilor create in prezent de firmele de soft sunt web-based iar dezvoltarea corecta a acestora implica in mod obligatoriu si un proces riguros de testare, sistemele de testare automata au ajuns sa fie din ce in ce mai utilizate in dezvoltarea software.
Sistemul de test automat a fost creat folosind trei software-uri diferite: Java, Git si Jenkins. Cele trei tool-uri diferite formeaza framework-ul de test pentru testarea aplicatiei online www.domo.ro. Testele atomate au fost scrise in limbajul de programare java iar clientul utilizat a fost Eclipse IDE Indigo. Fisierele sursa ale proiectului sunt grupate in 7 pachete impartite la randul lor in 2 foldere: src/main/java – contine clasele ajutatoare asociate framework-ului si src/test/java – contine clasele de test asociate aplicatiei web supusa procesului de testare. In pachetul .util au fost definite clasele ajutatoare: FileUtil.Java, logger.java si WebDriverHelper.java. Acestea contin metode folosite penntru o mai buna interactiune cu elementele din browser si pentru debug: crearea unui fisier de loguri si pentru crearea de screenshots. Aceste metode sunt utilizate in clasele de test. Au fost create 106 teste automate in care se verifica elemente din UI si anumite functionalitati ale aplicatiei web. Clasele de test pot fi extinse pentru a cuprinde alte elemente de UI din aplicatie sau alte functionalitati. Pentru a stoca diferitele versiuni de cod ale proiectului a fost utilizat softul Github. Astfel a fost creat un repository public in care sunt stocate toate vesiunile claselor de test. De asemenea pentru a complea sistemul de testarea automata cu un soft de integrare continua s-a utilizat: Jenkins. Softul a fost configurat pentru a prelua codul java din repository-ul creat in Github si pentru a rula tesele automate la intervale de timp regulate. Testele a fost rulate in 3 moduri diferite: in mod individual – ca si junits, ca si maven project – din Eclipse, ca si maven project – din Jenkins. Avantajul major al rularii testelor din Jenkins reprezinta faptul ca utilizatorul poate seta un job (un proiect in Jenkins) ca sa ruleze independent – fara interventia acestuia, la anumite intervale de timp prestabilite. Acest sistemul de testare automata poate fi aplicat si altor siteuri web – prin introducerea noilor clase de test corespunzatoare aplicatiilor testate. Testele scrise pentru aplicatia de test au fost rulate atat din Eclipse cat si din Jenkins iar rezultatele au fost introduse in tabelul de la capitolul: Rezultate. Timpul total de rulare a testelor din Eclipse: 22:25.416s iar din Jenkins: 4:26:28.073s. Timpul utilizat de Jenkins este mai mare deoarece acesta creaza o copie a ultimului commit al proiectului si foloseste un buffer intern pentru a rula testele. Din totalul de teste rulate: 106, picate au fost considerate 24 de teste iar 1 a fost considerat avand o eroare in cod (aceasta a fost mai apoi corectata printr-un nou commit). Motivul pentru care au picat 24 de teste este modificarea optiunilor si a elementelor de UI din aplicatia web si nu din cauza unor defecte pe pagina.
Scopul principal al proiectului a fost crearea unui cadru de test automatizat iar acest tip de testare se utilizeaza deobicei pentru partea de regresie a unei aplicatii care este in dezvoltare. Astfel sunt intrduse functionalitati noi in proiect iar testele automate se folosesc pentru a verifica faptul ca nicio functionalitate nou introdusa nu a afectat in vreun fel sistemul si caracteristicile acestuia. Focusul nu reprezinta gasirea bug-urilor in pagina.
6. Bibliografie
[1]http://www.magentocommerce.com/images/uploads/download/MagentoTestAutomationFrameworkUsersGuide.pdf
[2]http://www.coverity.com/wpcmeresources/DS_Coverity_Development_Testing_Platform_Jav a_0213.pdf
[3] 2013, http://www.qualitiasoft.com/
[4] CarlNagle, http://safsdev.sourceforge.net/FRAMESDataDrivenTestAutomationFrameworks.htm
[5] Thomas Muller, Dorothy Graham, Klaus Olsen, Foundation Level Syllabus, 2011
[6] 2004-2006 Qualitiy House, Basics of Software Testing, www.qualityhouse.biz
[7] 2008-2010, http://docs.seleniumhq.org/docs/03_webdriver.jsp#selenium-webdriver-s-drivers
[8] 2005-2010, Mozzilla, http://getfirebug.com/faq/
[9] Scott Chacon, Pro Git, Apress, July 29- 2009
[10] John Ferguson Smart,Jenkins The Definitive Guide, Wakaleo Consulting, 111 Donald Street, Karori, Wellington 6012, NewZealand, 2011
. Bibliografie
[1]http://www.magentocommerce.com/images/uploads/download/MagentoTestAutomationFrameworkUsersGuide.pdf
[2]http://www.coverity.com/wpcmeresources/DS_Coverity_Development_Testing_Platform_Jav a_0213.pdf
[3] 2013, http://www.qualitiasoft.com/
[4] CarlNagle, http://safsdev.sourceforge.net/FRAMESDataDrivenTestAutomationFrameworks.htm
[5] Thomas Muller, Dorothy Graham, Klaus Olsen, Foundation Level Syllabus, 2011
[6] 2004-2006 Qualitiy House, Basics of Software Testing, www.qualityhouse.biz
[7] 2008-2010, http://docs.seleniumhq.org/docs/03_webdriver.jsp#selenium-webdriver-s-drivers
[8] 2005-2010, Mozzilla, http://getfirebug.com/faq/
[9] Scott Chacon, Pro Git, Apress, July 29- 2009
[10] John Ferguson Smart,Jenkins The Definitive Guide, Wakaleo Consulting, 111 Donald Street, Karori, Wellington 6012, NewZealand, 2011
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: Structura Proiectului Domoproject In Eclipse Ide Si Metode Ajutatoare (ID: 163754)
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.
