odjel za matematiku - mrkvemrkve.etfos.hr/pred/ozm/si/sem12.pdf · 2017-06-20 · testiranje...
TRANSCRIPT
Sveučilište Josipa Jurja Strossmayera u Osijeku
Odjel za matematiku
Jurica Maltar
Automatizacija testiranja
Softversko inženjerstvo
Osijek, 2017.
1
Sadržaj Uvod ........................................................................................................................................................ 2
Ručno vs. automatizirano testiranje ................................................................................................... 4
Testiranje API-ja ...................................................................................................................................... 5
Testiranje grafičkog korisničkog sučelja .................................................................................................. 8
Princip rada Selenium WebDriver frameworka................................................................................. 10
Zaključak ................................................................................................................................................ 12
2
Uvod
„Computers are incredibly fast, accurate and stupid; humans are incredibly slow,
inaccurate and brilliant; together they are powerful beyond imagination.“ Ovaj je citat
nepoznatog podrijetla, doduše, neki ga pripisuju Albert Einstein-u, a neki Leo Cherne-u. Bez
obzira na podrijetlo citata, on savršeno opisuje sinergiju između čovjeka i računala. Ipak,
upravo zbog ljudske netočnosti, prilikom implementacije softvera, moguće je potkradanje
greške, ili popularno bug-a. Sam bug uzrokuje netočan ili neočekivani ishod korištenja
softvera, a posljedice ponekada mogu biti katastrofalne. Najčešći uzročnici bugova su:
specifikacija, dizajn i kod (slika 2).
Kako bi greške bile izbjegnute, a i s druge strane, kako bismo se uvjerili da softver radi
ono što bi trebao, odnosno, da je softver primjeren za uporabu, rabimo tehnike testiranja
softvera. Testiranje je postupak izvršavanja programa u svrhu pronalaženja bugova, odnosno
postupak validacije („pravimo li dobar proizvod?“ ) i verifikacije („pravimo li proizvod na dobar
način?“) softvera (slika 3). Jedan od načina testiranja softvera jest i test automation
(automatizirano testiranje/automatizacija testiranja). U ovome radu navode se karakteristike
automatiziranog testiranja, prednosti, nedostaci i tehnologije za implementaciju.
Regresijskim testovima (slika 1) verificiramo je li prethodno definirani dio softvera
nakon nadogradnje korektan. Stoga, utvrđujemo jesu li nove funkcionalnosti narušile samu
korektnost. Takvi se testovi izvršavaju nakon svake nadogradnje. Dakle, testiranje je
ponavljajuće i iscrpljujuće – ukoliko se testovi izvršavaju ručno, odnosno, osoba koja je
zadužena za testiranje svaki put kada je dodana nova funkcionalnost, ručno izvrši test – dolazi
do gubitka vremena, a samim time i ostalih resursa. Nakon što se jedan test izvrši, osoba
pokreće drugi i tako u nedogled. Takave iscrpljujuće zadatke moguće je automatizirati.
Automatizacija testiranja postupak je korištenja posebnih alata u svrhu kontrole izvršavanja
testova. Automatizacija omogućava izvršavanje testova na brz i efikasan način. Ukratko,
potrebno je definirati testove koji će tada jedan za drugim biti izvršeni neovisno o prisustvu
čovjeka i neovisno o uvjetima – bilo kada, u bilo kojim uvjetima i na jednom računalu.
Glavni pristupi automatizacije testiranja su:
Automatizacija testiranja API-ja
Automatizacija testiranja grafičkog korisničkog sučelja
Slika 1 – Regresijski test
3
Prije nego li se testovi izvrše, potrebno ih je definirati. To može biti postignuto na
klasičan način pomoću kodiranja, pomoću zadavanja makronaredbi (unaprijed definirani niz
koda koji će se izvršiti), ili pomoću snimanja interakcije korisnika. Samim time, osoba koja je
zadužena za testiranje, ne mora nužno poznavati kodiranje, ali treba biti upoznata s logikom
softvera kako bi bila u mogućnosti pronaći potencijalne pogreške.
Tehnologije koje služe za automatizaciju testiranja nisu lako dostupne, odnosno, takve
su tehnologije uglavnom namijenjene velikim kompanijama s kompleksnim projektima zbog
svoje cijene. Ipak, kako se radi o kompleksnom projektu s mnogo definiranog koda, to je na
dulje relacije automatizacija testiranja isplativa. Za male projekte ponekad nije isplativo
koristiti automatizaciju testiranja, ali je moguće je pronaći kompromis između ručnog i
automatiziranog testiranja.
Slika 2 - uzročnici bugova
Slika 3 - Validacija i verifikacija proizvoda
4
Ručno vs. automatizirano testiranje
Kako je rečeno, potrebno je promisliti kada bismo u svome projektu koristili ručno, a
kada automatizirano testiranje. S iskustvom tima moguće je pronaći zlatni sredinu, odnosno,
neki će testovi biti izvršeni ručno, a neki na automatizirani način. Npr. jedan od mogućih
rješenja u agilnom razvoju jest da se u parnoj iteraciji koristi ručno, a u neparnoj
automatizirano testiranje. U nastavku slijede tvrdnje za i protiv oba načina testiranja.
Prednosti automatiziranog testiranja:
Testovi se izvršavaju brže
Nisu potrebni dodatni ljudski resursi
Testovi se mogu izvršavati u bilo koje zakazano vrijeme
Potrebno je samo jedno računalo da bi se svi testovi na sustavu izvršili
Osoba koja provodi testove ne mora znati programirati (testovi se mogu snimiti)
Ishod svih testova može se sažeti u jedan dokument, tako da ti ishodi mogu biti lako
dostupni i razumljivi svima
Nedostaci automatiziranog testiranja:
Cijena alata je velika
Effort za konfiguraciju je mnogo veći nego kod ručnog testiranja
Automatizirani testovi nemaju intelekt poput čovjeka
Prednosti ručnog testiranja:
Cijene alata su jeftinije i effort za konfiguraciju je manji
Tester se može koncentrirati na isključivo jedan test i izvršavati ga više puta
Tester posjeduje intelekt i uočava nedostatke koje automatiziranim testiranjma ne bi
mogli biti uočeni – npr. boja neke komponente korisničkog sučelja
Nedostaci ručnog testiranja:
Vrijeme izvršavanja je sporije
Trošak ljudskih resursa
Nepreciznost pri testiranju vremenske efikasnosti softvera
5
Testiranje API-ja
Testiranje API-ja vrši se na message levelu. Takvim testiranjem provjeravamo
funkcionalnost samoga koda iz raznih perspektiva, počevši od najosnovnijih metoda, preko
klase, skupa klasa pa sve do samih modula. Najjednostavniji oblik testiranja API-ja jest da
testiramo njegovu najmanju gradivnu jedinicu – klasu ili metodu, a takva se paradigma
testiranja naziva unit testiranje (unit testing). Unit testiranje je jedan od najstarijih načina
testiranja koda. Tijekom vremena se pokazalo da je unit testiranje ujedno i jedan od najboljih
načina testiranja koda kako bi se popravila kvaliteta, te kako bi se dobilo bolje razumijevanje u
funkcionalne zahtjeve metode ili klase. Sam koncept unit testiranja je 90-ih godina prošlog
stoljeća imenovao Kent Back u programskom jeziku Smalltalk.
Definicija unit testa jest sljedeća: Unit test je dio koda koji poziva drugi dio koda i
provjerava njegovu korektnost s obzirom na pretpostavke, a ukoliko se pretpostavke pokažu
krivima, unit test nije uspio.
Sam unit test je definiran u obliku klase ili metode, a kod koji provjeravamo unit
testom se u literaturi naziva sustav pod testom (SUT), a ponekad i klasa pod testom ili kod pod
testom (zajedno CUT).
Kako navodi Osherove, po njegovom mišljenu, definicija unit testa je sljedeća:
Unit test je dio koda koji poziva jedinicu rada (unit of work) i provjerava specifični krajnji
rezultat te jedinice rada. Ukoliko se pretpostavke pokažu krivima, unit test nije uspio. Sam unit
test provjerava barem jednu metoda unutar sustava pod testom, a može se prožimati i kroz
nekoliko klasa.
Osherove navodi da je jedinica rada skupina akcija koje se događaju prilikom pozivanja
neke metode u sustavu i krajnjeg rezultata tog poziva.
Osobine dobrog unit testa su:
Mogućnost automatizacije i mogućnost ponovnog izvšavanja
Lakoća implementacije
Otpornost na promjene
Jednostavno pozivanje testa
Brzina
Konzistentnost (isti rezultat u ovisnosti o istim parametrima)
Potpuna kontrola nad jedinicom rada
Neovisnost i izoliranost s obzirom na ostale unit testove
Lako detektiranje pogreške u kodu
Popularni unit test framework za .NET framework je NUnit, za Javu JUnit, a oba
pripadaju obitelj takozvanih xUnit frameworka, gdje je prvi takav bio SUnit (Kent Back,
Smalltalk). Takvi se testovi izvršavaju pomoću test runner-a, a svaki test nasljeđuje osnovnu
6
gradivnu jedinicu zvanu test case. Potrebno je definirati ulazne parametre i ishod testa, a sam
ishod testa se zapisuje u neki fajl za pohranjivanje podataka (uobičajno *.xml fajl).
Slika 4 – okolina izvršavanja unit testova
Slika 5 - test runner unutar Visual Studija
7
Unit testovima testiramo prethodno definirani kod, ali pritom izuzimamo sve ostale
resurse. Pod povečalom su klase i skupine klasa koje testiramo. Iako ne postoji striktna teorija
o tome kako provodimo unit test nad kodom, važno je promisliti koliki obim business logike
testiramo. U praksi se često se događa da dijelić koda, npr. jedna metoda, za koju smo sigurni
da radi na valjan način, ima grešku. Stoga je važno napraviti što više unit testova počevši od
najmanjih gradivnih jedinica – metoda, pa sve do samih komponenti i modula koje se sastoje
od mnoštva klasa (npr. neka funkcionalnost se proteže kroz nekoliko klasa) kako bismo se
uvjerili u valjanost softvera i potvrdili njegovu konstruktivnost. Takav konstruktivan softver
namijenjen za korištenje u stvarnome svijetu u obzir uzima i baze podataka, vrijeme sustava,
datotečni sustav itd., odnosno uzima u obzir vanjske resurse. Podklasa unit testa koja se
izvršava nad softverom s vanjskim resursima s mnoštvom modula naziva se integracijski test
(integration test). Definicija je sljedeća:
Integracijski test testira jedinicu rada pritom nemajući punu kontrolu nad tom jedinicom rada
jer ona ovisi o vanjskim resursima kao što su vrijeme, mreža, baza podataka, niti izvršavanja,
generatori slučajnih brojeva itd.
Možemo zaključiti kako je integracijski test prirodna nadogradnja na unit test, budući
da je sam unit test izoliran s obzirom na vanjske čimbenike, a i obim koda koji testiramo je
mnogo manji (klasa ili nekoliko klasa kod unit testiranja; nekoliko modula kod integracijskog
testiranja). Kako je pokazano, unit testovi se mogu izvršavati na automatizirani način pomoću
test runnera. Pritom, ukoliko su dobro napisani, trebali bi se brzo izvršiti. Sam postupak
izvršavanja može potrajati par minuta, ali i manje u ovisnosti o broju jedinica koje testiramo.
Istu stvar ne možemo reći i za integracijske testove, jer u obzir se uzimaju i vanjski resursi.
Npr. ako automaniziranim manevrom pokrenemo integracijske testove, gdje u svakom testu
neka od klasa komunicira s bazom podataka, sa drugim „vanjskim“ API-jima itd., svaki će
mrežni poziv dodati određeno, iako na prvi pogled zanemarivo, vrijeme. Kada se zbroje
minute svakoga od testa, sam postupak može potrajati satima.
Slika 6 - jednostavni unit test
8
Testiranje grafičkog korisničkog sučelja
Iako je na prvi pogled očigledno da je najjednostavniji način testiranja grafičkog
korisničkog sučelja taj da sam tester koristi softver i prijavljuje bugove (ručno testiranje), na
duge relacije to nije tako jednostavno. Kako je rečeno, često je potrebno pronaći sredinu
između ručnog i automatiziranog testiranja. Ručno testiranje zahtjeva testera, dok
automatizacijom tester nije potreban. Iako, postoje prednosti i mane oba načina – ponekada
je ekonomičnije nešto automatizirati, a ponekada je jedino rješenje ručno testiranje. Naime,
smisao testiranja grafičkog korisničkog sučelja u širem pogledu jest „glumiti ljudsko korištenje
grafičkog sučelja softvera od strane računala“. Svako takvo sučelje sastoji se od niza
elemenata koji prihvaćaju korisnikovu interakciju te provode definiranu funkcionalnost. Npr.
korisnik unosi svoje korisničko ime i lozinku u input prozore te pritišće button za submit.
Interakcije korisnika ishoduju rezultat koji se manifestira, između ostalog, i na grafičkom
sučelju.
Smislen skup više interakcija od strane korisnika koje daju smisleni rezultat naziva se
scenarij, a takav scenarij se lako preslikava u okvire testiranja grafičkog sučelja - test case u
slučaju testiranja grafičkog korisničkog sučelja niz je redova koda koji enkapsulirani u jednu
klasu naređuju računalu da upravlja softverom na način na koji to radi korisnik. Kao i kod
testiranja API-ja, potrebni su ulazni parametri, koji u ovom slučaju predstavljaju ono što
korisnik kani unijeti u program (npr. korisničko ime i lozinku), koji će nakon provedbe scenarija
(korisnik je upisao i submitao podatke) dati smisleni rezultat (prikazan je korisnički profil). Kao
što je i slučaj s testiranjem API-ja, test se mora definirati.
Test je moguće snimiti koristeći recorder (slika 7.) tako da korisnik, jednako kao i npr.
kod snimanja video zapisa, pritisne record button. Time se generira skripta koja definira test, a
moguće ju je uređivati i debuggirati. Kod jednostavnih scenarija, snimanje testa putem
recordera je primjenjivo, ali kod složenijih nastaje problem. Naime, rekorder će zapamtiti
interakciju s obzirom na postupke korisnika i identifikatore elemenata. Primjera radi, ukoliko
bismo željeli izlistati tablicu s paginationom gdje svaka stranica sadrži 10 redaka tražeći zapis
koji u stupcu „Ime“ ima vrijednost „John Doe“ te otvoriti njegov profil (neka se John Doe
nalazi na 4. stranici u 5. retku), rekorder će shvatiti da izlistavamo prve četiri stranice tablice i
na četvrtoj stranici izabiremo 5. redak, a neće tražiti John Doe-a. Kada dodamo novi zapis
„Jane Doe“ u tablicu koji se pojavljuje po novom poretku prije ili na 4. stranici u 5. retku, John
Doe će se nalaziti na 4. stranici u 6. retku, a prethodno snimljena test skripta otvorit će profil
na 4. stranici u 5. retku. U ovome primjeru, potrebno je izlistavati pagination sve dok
pronađemo John Doe-a (a ne trebamo ići do 4. stranice i 5. retka), a ukoliko ga ne
pronađemo, a trebali smo, test nije uspio. Stoga, kodiranjem testa imamo potpunu kontrolu
nad njegovim izvršavanjem.
9
Klasa u kojoj je definiran test za grafičko korisničko sučelje dohvaća elemente sučelja
te vrši interakciju s njima. To se ne događa na način na koji čovjek vrši interakciju sa sučeljem -
čovjek vizualno identificira element pa služeći se mišem ili tipkovnicom „dohvaća“ taj element
i na njemu vrši radnju. U pogledu računala, stvar je obrnuta. Kako bi računalo dohvatilo
element sučelja potreban je identifikator tog elementa (npr. u HTML-u to može biti id, class,
xpath, ime elementa, tip elementa itd.). Tada računalo određuje apsolutnu poziciju elementa i
vrši interakciju. Iako, prilikom definiranja samog testa kojim testiramo neki element sučelja,
element može biti dohvaćen tako da hardkodiramo njegov identifikator, bolja je praksa
nanovo definirati taj element u samoj okolini u kojoj se izvršava test, tzv. model, te služeći se
mehanizmima objektno-orijentiranog programiranja napraviti hijerarhiju više modela,
odnosno, na neki način mapirati grafičko korisničko sučelje u kod razumljiv samome okruženju
unutar kojega se vrši test. Npr. forma se može sastojati od više inputa, button za submit i
odustajanje – unutar forme, koja, budući da je element korisničkog sučelja, ima identifikator,
enkapsuliramo njenu djecu koja se nalaze unutar HTML DOM-a – inpute koji imaju svoj
identifikator i buttone s identifikatorima. Ponekada identifikatori ne znače nužnu
jedinstvenost u smislu sadržaja identifikatora. Npr. imamo button klase „test-button“ i
susjednu formu sa identifikatorom koja sadrži button klase „test-button“. Očigledno je da
postoji razlika između ova dva buttona budući da je prvi klase button i nije dijete forme, a
drugi jest dijete forme. Imajući to na umu, možemo na potpuno odeđeni način dohvatiti
potreban element.
Slika 7 - Snimanje testa za GUI
Popularni alati za GUI testiranje su: Ascentialtest, Autolt, Dojo Objectiv Harness,
eggPlant Functional, HP WinRunner, IcuTest, iMacros, Linux Desktop Testing Project, Maveryx,
Oracle Application Testing Suite, QF-Test, Ranorex, Rational Functional Tester, Robot
Framework, Sahi, Selenium WebDriver, SiklTest, SOAtest, Squish, Test Studio, TestComplete,
Test Anywhere, TestPartner, Tricentis Tosca, Twist, UFT, Visual Studio Coded UI Test, Watir,
Xnee.
10
Princip rada Selenium WebDriver frameworka
Selenium WebDriver je popularni GUI automation framework koji služi za testiranje
web aplikacija (web application under testing). Dostupan je za mnoge programske jezike,
između ostaloga i za Javu, C#, Python, Ruby, Scala, PHP... Testove napisane u Seleniumu
moguće je izvršavati na svim popularnijim preglednicima.
Princip po kojemu Selenium WebDriver izvršava testove jest sljedeći:
Developer pokreće skriptu koja naređuje WebDriver-u da provodi određene
interakcije na aplikaciji
WebDriver pokreće određeni preglednik (npr. WebDriver može biti Firefox Driver,
Chrome Driver, IE Driver, ...), a izvan tog preglednika pokreće se interakcija – jednako
kako i stvarni korisnik koristi preglednik
Završetkom WebDriver generira ishod testiranja te se on sprema u neku datoteku.
Slika 8 - Princip rada Selenium WebDriver-a
Osnovna metoda unutar SeleniumWebDrivera je findElement(), a osnovna klasa
objekta je WebElement. Kako je rečeno, Selenium radi na principu dohvaćanja elemenata s
obzirom neku specifičnost. Ukoliko npr. želimo pritisnuti hyperlink s natpisom „Info“, to ćemo
učiniti sljedećim kodom:
driver.findElement(by.linkText(„Info“)).click();
Sama metoda findElement() vraća objekt klase WebElement koji može pohraniti svaki od
HTML elemenata. Ipak, pametno je specijalizirati takvu klasu kako bismo imali enkapsulirane
članove s obzirom na specifičnu strukturu HTML elemenata.
12
Zaključak
Automatizacijom testiranja na efikasan način osiguravamo kvalitetu softvera.
Automatizacija je provediva pri testiranju API-ja i GUI-ja. Iako automatizacijom na duže relacije
postižemo veću efikasnost po pitanju vremena i novca, ne postoji univerzalni odgovor kada
koji način testiranja primjeniti. Ukoliko se radi o malom startupu, jedan tester će biti dovoljan,
a u drugu ruku, za velike korporacije, automatizacija testiranja je neizbježna u vidu
smanjivanja troškova ljudskih resursa. Pri razvoju softvera, važno je uzeti u obzir prednosti i
nedostatke oba načina izvršavanja testiranja.