• Rezultati Niso Bili Najdeni

Vsi testi, ki se bodo z naˇsim ogrodjem izvajali, imajo nekaj skupnih potreb.

Vsi potrebujejo zagnano aplikacijo oz. inicializirano sejo Appium in inicializi-rano spremenljivko current page, ki bi na zaˇcetku morala vsebovati objekt prve strani aplikacije. Da nam ne bi bilo vsakiˇc treba te logike pisati na novo, bodo vsi razredi, ki vsebujejo skupek testov, definirani kot podrazredi (dediˇci) razreda po imenu BaseCase, v katerem se nahaja vsa logika in vse metode, ki so potrebne ali pa uporabne za testiranje katerekoli aplikacije.

Razred BaseCaseimplementira metodosetup class, v kateri se iniciali-zirata seja Appium in spremenljivkacurrent page, v katero se shrani objekt prve strani aplikacije, preden se testi zaˇcnejo izvajati. Potrebne podatke za inicializacijo pridobi iz konfiguracijske datoteke (veˇc v razdelku 4.6).

Diplomska naloga 23

4.3.1 Inicializacija nove seje Appium

Za inicializacijo nove seje Appium moramo pridobiti primerek razreda po imenu WebDriver. Ta se uporablja kot gonilnik, s pomoˇcjo katerega ko-municirata testna skripta in streˇznik Appium. Da bi ga pravilno inicia-lizirali, mu podamo konfiguracijo iz konfiguracijske datoteke in preverimo, ˇce je bil ˇze inicializiran. ˇCe gonilnik ˇse ni inicializiran, pokliˇcemo funkcijo driver.load driver, sicer pa funkcijo driver.reload driver (izpis 4.4).

Situacija, ko je gonilnik ˇze inicializiran, lahko nastopi v primeru, ko hoˇcemo naenkrat zagnati veˇc sklopov testnih primerov (veˇc razredov, ki vsebujejo teste). Takrat se gonilnik inicializira ˇze pri prvem sklopu testnih primerov.

V tem primeru ˇzelimo samo ponovno zagnati aplikacijo, da bi se vsak sklop testov izvajal pod enakimi pogoji, zato pokliˇcemo metodo reload driver, ki ponovno zaˇzene aplikacijo. Lahko bi v obeh primerih klicali funkcijo load driver, vendar bi bilo to poˇcasneje, saj bi ta funkcija ponovno kre-irala sejo Appium in ˇsele potem ponovno zagnala aplikacijo [3].

d r i v e r = WebDriver ( c o n f i g=l o a d c o n f i g ( p y t e s t . c o n f i g p a t h ) )

RazredBaseCasevsebuje funkcijo za nalaganje objekta nove strani, ki ustvari objekt na podlagi razreda strani in ga shrani v spremenljivkocurrent page.

Metoda deluje tako, da ji podamo ime ˇzelenega razreda strani, ki je enako imenu datoteke, v kateri je shranjen razred strani (brez konˇcnice .py), potem pa s pomoˇcjo pythonove knjiˇznice importlib ustvari objekt na podlagi razreda strani in s klicem funkcije wait page poˇcaka, da se stran naloˇzi. ˇCe se stran uspeˇsno naloˇzi, potem se objekt strani zapiˇse v spremenljivkocurrent page.

4.3.3 Inicalizacija prve strani

Za vsako aplikacijo, ki jo ˇzelimo testirati z naˇsim ogrodjem, moramo izdelati razred, kamor zapiˇsemo vse metode, ki so skupne vsem stranem doloˇcene aplikacije. Temu razredu reˇcemo tudi osnovna stran aplikacije, saj se njegov primerek pri inicializaciji testnih primerov najprej ustvari. V tem razredu moramo zapisati ime razreda prve strani aplikacije (stran, ki se ob zagonu aplikacije po njeni namestitvi prva prikaˇze), da bi ga lahko naloˇzili pri ini-cializaciji testov. Pri iniini-cializaciji razreda prve strani aplikacije najprej iz konfiguracijske datoteke preberemo ime aplikacije in s pomoˇcjo knjiˇznice im-portlib naloˇzimo primerek razreda osnovne strani aplikacije (izpis 4.5). Iz tega (razreda osnovne strani aplikacije) potem preberemo ime razreda prve strani aplikacije in ga naloˇzimo tako, kot je to opisano v razdelku 4.3.2.

app name = p y t e s t . app name

p a g e m o d u l e = i m p o r t m o d u l e ( f ’ c o r e . p a g e s .{app name}.{app name}) a p p c l a s s = g e t a t t r( page module , g e t c l a s s n a m e ( app name ) )

a p p b a s e p a g e = a p p c l a s s ( )

r e t u r n s e l f . l o a d p a g e ( a p p b a s e p a g e . g e t f i r s t p a g e n a m e ( ) )

Izpis 4.5: Nalaganje instance prve strani aplikacije

4.4 Razredi strani

Razredi strani so kljuˇcnega pomena v naˇsem ogrodju. V vsakem tovrstnem razredu so zapisane metode za pridobivanje elementov na pripadajoˇci strani aplikacije. S tem si olajˇsamo razvoj, saj imamo vse elemente strani dosto-pne na enem mestu, in poenostavimo vzdrˇzevanje, saj je treba spremeniti samo dostop do elementa v razredu strani, ˇce se element ali njegov atribut spremenita.

Diplomska naloga 25

4.4.1 Osnovna stran

Razred osnovne strani (BasePage) je nadrazred vseh ostalih razredov strani, zato vsi drugi razredi strani od njega podedujejo vse metode in atribute.

V njem se nahajajo vse metode in atributi, ki so skupni ali uporabni za vse razrede, ki implementirajo metode in atribute za doloˇceno stran. Pri inicializaciji vsakega razreda strani se razredu BasePage posreduje primerek gonilnika (veˇc v razdelku 4.5), ki ga razredi strani uporabljajo za dostop do elementov. V testnih primerih pogosto uporabljamo metode iz razreda BasePage, kot so:

• is element visible, ki preveri, ali je podani element trenutno viden;

• is element usable, ki preveri, ali lahko dostopamo do podanega ele-menta;

• clear input, ki poˇcisti besedilo v podanem vnosnem polju;

• is checked, ki preveri, ali podani element vsebuje atribut checked in ali je nastavljen na vrednosttrue, kar je uporabno pri razliˇcnih gumbih;

• scroll page, ki pomakne stran navzgor ali navzdol.

Poleg naˇstetih je pomembno izpostaviti ˇse metodo wait page. V tej me-todi povemo, ali se je naˇsa stran dokonˇcno naloˇzila in koliko ˇcasa ˇzelimo ˇcakati, da se stran naloˇzi. Zato se od vseh razredov strani priˇcakuje, da im-plementirajo svojo razliˇcico te metode in s tem definirajo, kdaj se je njihova stran dokonˇcno naloˇzila. To je zelo pomembno, saj v testnih primerih ne ˇzelimo dostopati do elementov, preden se stran naloˇzi do konca. Preverjanje dokonˇcnega nalaganja strani ponavadi izvedemo tako, da poskusimo prido-biti element, za katerega vemo, da ˇce ga bomo uspeˇsno pridobili, bomo lahko pridobili tudi druge elemente na strani (izpis 4.6). Poleg tega je smiselno po-dati parameterwait, s katerim povemo, koliko ˇcasa ˇzelimo poˇcakati, preden vrnemo podatek, da elementa ni bilo moˇzno pridobiti.

d e f w a i t p a g e ( s e l f , w a i t =20) :

r e t u r n s e l f . g e t l o g i n b u t t o n ( w a i t )

Izpis 4.6: Primer implementacije metode wait page

4.4.2 Osnovna stran aplikacije

Kot smo omenili v razdelku 4.3.3, moramo za vsako aplikacijo izdelati ra-zred za osnovno stran aplikacije kot podrara-zred rara-zreda BasePage, v katerem podamo ime datoteke, ki vsebuje razred prve strani aplikacije (izpis 4.7).

Poleg tega lahko v ta razred dodamo tudi vse ostale atribute in metode, ki so skupne vsem stranem za doloˇceno aplikacijo.

d e f g e t f i r s t p a g e n a m e ( s e l f ) : r e t u r n ” l o g i n p a g e ”

Izpis 4.7: Ime datoteke, ki vsebuje razred prve strani aplikacije

4.4.3 Dostop do elementov

Ko testiramo z orodjem Appium, imamo veˇc naˇcinov za iskanje elementov.

Naslednji naˇcini se lahko uporabljajo na vseh platformah [22]:

• Accessibility ID: Elemente iˇsˇcemo z uporabo unikatnega identifika-torja (izpis 4.8). Pri platformi iOs se identifikator zapiˇse kot niz v polje accessibility-id, katerega namen je ta, da skriptam za testi-ranje uporabniˇskega vmesnika olajˇsa iskanje in dostop do elementov.

Poslediˇcno se pri platformi iOs preteˇzno uporablja ta naˇcin iskanja [1].

Na platformi Android se pri tem naˇcinu iskanja iˇsˇce identifikator znotraj poljacontent-desc, katerega namen je ta, da opiˇse vsebino doloˇcenega elementa in s tem olajˇsa uporabo mobilne naprave osebam s posebnimi potrebami. Poljecontent-descponavadi vsebuje presledke in ni nujno unikatno, zato se pri platformi Android ta naˇcin iskanja ponavadi ne uporablja.

Diplomska naloga 27

driver.find elements by accessibility id(’SomeAccessibilityID’)

Izpis 4.8: Primer iskanja z uporabo Accessibility ID

• Ime razreda: Elemente iˇsˇcemo z uporabo imena njihovega razreda (izpis 4.9). Pri platformi Android je to kar polno ime razreda (npr.

android.view.TextView), pri platformi iOs pa polno ime elementa, ki se zaˇcne z nizom XCUIElementType. Ta naˇcin iskanja je uporaben, kadar ˇzelimo pridobiti veˇc elementov istega tipa (npr. vse slike na strani).

d r i v e r . f i n d e l e m e n t s b y c l a s s n a m e (” some . c l a s s . name”)

Izpis 4.9: Primer iskanja z uporabo imena razreda

• Domorodni identifikator elementa: Element iˇsˇcemo z uporabo do-morodnega identifikatorja elementa (izpis 4.10), ki se kot niz zapiˇse v polje name pri platformi iOs in v polje resource-id pri platformi Android. To je najpogosteje uporabljeni naˇcin iskanja pri platformi Android, saj se polje resource-id skoraj vedno uporablja ˇze pri ra-zvoju aplikacij za to platformo.

d r i v e r . f i n d e l e m e n t s b y i d (’ s o m e i d ’)

Izpis 4.10: Primer iskanja z uporabo domorodnega identifikatorja

• Ime elementa: Elemente iˇsˇcemo z uporabo atributaname(izpis 4.11).

Ta naˇcin iskanja uporabljajo predvsem hibridne ali spletne aplikacije, ki imajo definiran atributname. Pri platformi iOs ta naˇcin iskanja sicer lahko uporabljamo, vendar je bolje, ˇce uporabljamo domorodni identi-fikator elementa, saj ga v nekaterih primerih lahko ponovno uporabimo pri platformi Android. Pri platformi Android polje name ponavadi ni definirano v atributih elementa, zato se ta naˇcin iskanja obiˇcajno ne uporablja.

d r i v e r . f i n d e l e m e n t s b y n a m e (’ some name ’)

Izpis 4.11: Primer iskanja z uporabo imena elementa

• XPath: Elemente iˇsˇcemo z uporabo poizvedovalnega jezika XPath (iz-pis 4.12). To je najrobustnejˇsi naˇcin iskanja po dokumentih XML.

Pogosto se uporablja pri seznamih elementov, saj lahko iˇsˇcemo element po indeksu in razredu hkrati. ˇCeprav je ta naˇcin najrobustnejˇsi, je tudi najpoˇcasnejˇsi, zato se mu poskuˇsamo izogniti.

d r i v e r . f i n d e l e m e n t s b y x p a t h (

’ // a n d r o i d . w i d g e t . TextView [ @text=” H e l l o World ” ] ’)

Izpis 4.12: Primer iskanja z uporabo poizvedovalnega jezika XPath

• Slika: Slike iˇsˇcemo z uporabo poizvedbene slike, zakodirane v formatu base64.

4.4.4 Implementacija razreda strani

Ce ˇˇ zelimo testirati doloˇceno stran aplikacije, moramo izdelati tri nove razrede.

Po en razred potrebujemo za vsako platformo, saj ˇzelimo imeti loˇcene metode za pridobivanje elementov za platformi iOs in Android. Tretji razred bo uporabljen kot generiˇcni razred, ki bo vseboval metode in atribute, ki si jih delita obe platformi.

Najprej izdelamo generiˇcni razred kot podrazred razreda osnovne strani aplikacije (BasePage) in v njem implementiramo metodo wait page (izpis 4.13). V tej metodi vrnemo logiˇcno resnico, ko se stran dokonˇcno naloˇzi (ˇce se to zgodi v podanem ˇcasovnem obdobju).

Diplomska naloga 29

c l a s s LoginPage ( BasePage ) :

d e f w a i t p a g e ( s e l f ) :

r e t u r n s e l f . g e t u s e r n a m e i n p u t ( w a i t =20)

Izpis 4.13: Primer generiˇcne strani za prijavo

Ko je generiˇcni razred izdelan, lahko implementiramo razreda strani za platformi Android in iOs (izpisa 4.14 in 4.15). Oba razreda strani podedu-jeta metode in atribute od omenjenega generiˇcnega razreda in implementirata metode za dostop do elementov. Pri pisanju imen metod pazimo, da imajo metode, ki pridobivajo iste elemente, tudi ista imena. S tem si olajˇsamo razvoj testnih primerov, ker nam ni treba preverjati, na kateri platformi iz-vajamo teste. ˇCe sta strani identiˇcni na obeh platformah, je edina razlika v njunih razredih samo naˇcin dostopanja do elementov. Kot smo povedali v razdelku 4.4.3, se pri platformi Android najpogosteje uporablja iskanje z domorodnim identifikatorjem elementa, pri platformi iOs pa iskanje z dosto-pnostnim identifikatorjem.

classLoginPage(GenericLoginPage):

defget username input(self,∗∗kwargs):

returnself.driver.find element by id(’username input’,∗∗kwargs)

defget password input(self,∗∗kwargs):

returnself.driver.find element by id(’password input’,∗∗kwargs)

defget login button(self, ∗∗kwargs):

returnself.driver.find element by id(’login button’,∗∗kwargs)

Izpis 4.14: Primer implementacije razreda strani za platformo Android

c l a s s LoginPage ( G e n e r i c L o g i n P a g e ) :

d e f g e t u s e r n a m e i n p u t ( s e l f , ∗∗kwargs ) :

r e t u r n s e l f . d r i v e r . f i n d e l e m e n t b y a c c e s s i b i l i t y i d (

’ u s e r n a m e i n p u t ’,

∗∗kwargs )

d e f g e t p a s s w o r d i n p u t ( s e l f , ∗∗kwargs ) :

r e t u r n s e l f . d r i v e r . f i n d e l e m e n t b y a c c e s s i b i l i t y i d (

’ p a s s w o r d i n p u t ’,

∗∗kwargs )

d e f g e t l o g i n b u t t o n ( s e l f , ∗∗kwargs ) :

r e t u r n s e l f . d r i v e r . f i n d e l e m e n t b y a c c e s s i b i l i t y i d (

’ l o g i n b u t t o n ’,

∗∗kwargs )

Izpis 4.15: Primer implementacije razreda strani za platformo iOs

4.5 Odjemalec Appium

Naˇse ogrodje uporablja orodje Appium, da bi izvajalo interakcije na mobilnih napravah. Kot smo omenili v razdelku 3.2.1, je Appium le streˇznik HTTP, zato je potreben tudi odjemalec HTTP, ki nam bo omogoˇcil komunikacijo s streˇznikom. Za programski jezik Python obstaja odjemalec Appium [6], ki ga lahko naloˇzimo s pomoˇcjo orodja Pip. Da bi ga zaˇceli uporabljati, moramo iz odjemalca Appium uvoziti razredwebdriver, ki nam nudi metode za komunikacijo z streˇznikom Appium.

Diplomska naloga 31

4.5.1 Zelene zmogljivosti ˇ

Za zaˇcetek nove seje moramo streˇzniku Appium povedati, kako ˇzelimo izvajati naˇse teste. To storimo tako, da zgradimo slovar ˇzelenih zmogljivosti (angl.

desired capabilities), ki jo odjemalec Appium poˇslje streˇzniku Appium kot objekt JSON. Obstaja veliko razliˇcnih nastavitev, s katerimi opiˇsemo, na kakˇsen naˇcin in v kakˇsnem okolju ˇzelimo, da se naˇsi testi izvajajo. ˇCeprav obstaja veliko razliˇcnih nastavitev, naˇse ogrodje uporablja le najbolj osnovne, ki so potrebne za zagon testnih primerov na obeh platformah [4]:

• Nastavitev platformName, kjer povemo, katero platformo ˇzelimo te-stirati (iOS, Android).

• Nastavitev deviceName, kjer podamo ime naprave, na kateri ˇzelimo izvajati teste. Pomembno je, da se ime ujema z imenom, ki ga naprava sporoˇci raˇcunalniku.

• Nastavitev automationName, kjer povemo, kateri gonilnik ˇzelimo uporabiti.

• Nastavitevapp, kjer podamo absolutno pot ali naslov URL aplikacije, ki jo ˇzelimo testirati. Pri platformi Android je to absolutna pot do datoteke s konˇcnico .apk, medtem ko je pri platformi iOs to absolutna pot do datoteke s konˇcnico .app ali .ipa.

Poleg omenjenih bi izpostavili ˇse nekaj pogosto uporabljenih nastavi-tev pri testiranju mobilnih aplikacij, ki sicer niso implementirane v naˇsem ogrodju, vendar se jih lahko z malo truda hitro doda [4]:

• NastavitevplatformVersion, kjer podamo razliˇcico platforme, na ka-teri ˇzelimo, da se testi izvajajo.

• Nastavitevlanguage, kjer povemo, kateri jezik naj testirana aplikacija uporablja.

• Nastavitevorientation, kjer povemo, ali ˇzelimo, da je naprava v vodo-ravni ali navpiˇcni orientaciji pri izvajanju testov (to lahko uporabimo le pri simulatorjih).

• Nastavitev otherApps, kjer naˇstejemo poti do vseh ostalih aplikacij, katere ˇzelimo namestiti, preden se testirana aplikacija zaˇzene.

.

4.5.2 Razred Webdriver

Da bi lahko funkcionalnosti razreda webdriver nadgradili, smo izdelali naˇs lasten razred z istim imenom. Razred smo definirali kot podrazred razreda webdriveriz knjiˇznice python-appium in v njem implementirali nove metode ter nadgradili nekatere ˇze obstojeˇce metode. Poleg tega smo pri naˇsem ovoj-nem razredu uporabili vzorec enojˇcek (angl. singleton), kar pomeni, da vsi ostali razredi uporabljajo isti primerek naˇsega razreda, s ˇcimer se izognemo morebitnim ponovnim ustvarjanjem sej ali nalaganjem aplikacij.

Inicializacija seje

Za kreiranje nove seje Appium moramo definirati ˇzelene zmogljivosti in URL-naslov URL-naslov streˇznika Appium. ˇZelene zmogljivosti pridobimo iz konfigu-racijske datoteke in jih prepiˇsemo v slovar. URL-naslov streˇznika Appium preberemo iz programa Appium desktop in ga zapiˇsemo v naˇsem razredu webdriver. Slovar ˇzelenih zmogljivosti in URL-naslov streˇznika vstavimo v konstruktor naˇsega razreda webdriver in s tem ustvarimo novo sejo.

Metode za pridobivanje elementov

Metode za pridobivanje elementov v poglavju 4.4.3 smo v naˇsem razredu webdrivernadgradili tako, da smo vsaki metodi dodali parameterwait, s ka-terim povemo, kako dolgo ˇzelimo ˇcakati na element, preden dobimo sporoˇcilo, da element ni bil najden. To naredimo s klicem funkcije implicitly wait,

Diplomska naloga 33 ki pove odjemalcu Appium, da poskuˇsa pridobiti element, dokler ga ne najde ali pa poteˇce podani ˇcas [13]. Kot privzeto smo nastavili, da pri iskanju ele-menta poˇcakamo najveˇc pet sekund. S tem se izognemo teˇzavam, ko se vsi elementi na strani ne naloˇzijo takoj in moramo na nekatere poˇcakati.

4.5.3 Interakcije z elementi

Interakcija z elementi je kljuˇcna funkcionalnost, brez katere ne bi mogli iz-vajati testov na mobilnih napravah. Za pridobivanje informacij o trenutnem stanju elementa uporabljamo metode, ki pridobijo atribute elementa iz tre-nutne postavitve strani (angl. layout), zapisane v obliki XML. Odjemalec Appium nam ponuja mnoˇzico funkcij za izvajanje najbolj pogosto uporablje-nih akcij nad elementi.

Pridobivanje atributov elementa

Za pridobivanje atributov elementa uporabljamo naslednje metode:

• Metoda text pridobi vidno besedilo elementa.

• Metoda name pridobi ime znaˇcke predmeta.

• Metoda get attribute pridobi vrednost podanega atributa. S to metodo bi lahko zapisali tudi vse ostale metode (npr. text bi prevedli v get attribute(”text”)).

• Metoda is selected nam pove, ali je element izbran.

• Metoda is enabled nam pove, ali je element omogoˇcen.

• Metoda is displayed nam pove, ali je element trenutno prikazan.

• Metoda location vrne koordinate elementa.

• Metoda size vrne viˇsino in ˇsirino elementa.

• Metoda rect vrne koordinate ter viˇsino in ˇsirino elementa v enem objektu.

Izvajanje akcij nad elementi

Za najbolj preproste akcije (klik na sredino elementa, vnos ˇcrk v vnosno po-lje in brisanje polja) ima odjemalec Appium ˇze definirane funkcije click, send keys in clear. Kompleksnejˇse akcije pa izvajamo s pomoˇcjo objekta TouchAction. Objekt TouchAction lahko hrani verigo dogodkov, ki jih ˇzelimo izvesti [29]. Simulacijo premikanja prsta od enega elementa do dru-gega bi zapisali na naˇcin, prikazan v izpisu 4.16.

TouchAction ( ) . p r e s s ( e l e m e n t 1 ) . moveTo ( e l e m e n t 2 ) . r e l e a s e ( )

Izpis 4.16: Primer verige dogodkov

Od dogodkov imamo na voljopritisni (angl. press), spusti (angl. release), premakni se do (angl. move to), dotakni se (angl. touch), poˇcakaj (angl.

wait), dolgi pritisk (angl. long press), prekliˇci (angl. cancel) in izvedi (angl.

perform) [29]. S temi ukazi lahko simuliramo veˇcino dogodkov, ki bi jih uporabnik izvajal na svoji mobilni napravi.