odjel za matematiku - mrkvemrkve.etfos.hr/pred/ozm/si/sem12.pdf · 2017-06-20 · testiranje...

13
Sveučilište Josipa Jurja Strossmayera u Osijeku Odjel za matematiku Jurica Maltar Automatizacija testiranja Softversko inženjerstvo Osijek, 2017.

Upload: others

Post on 11-Feb-2020

5 views

Category:

Documents


0 download

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.

11

Slika 9 - Hello World u Seleniumu

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.