E2E tesztelés Angular 2-ben A nullától a hősig (utolsó rész)
Kedves Angular 2 E2E tesztelés leendő mesterei.
Ez az. Ennek a leckének a végén végre minden eszközzel rendelkezni fogsz ahhoz, hogy funkcionális teszteket készíts az Angular 2 alkalmazásaidhoz. Nincs több kifogás: Megkaptad a hatalmat!
Először a Locatorokkal ismerkedünk meg, majd meglátjuk, milyen fantasztikusak lehetnek az Oldalobjektumok, ezt követi az aszinkronitás kezelése, végül pedig a legegyszerűbb rész, az Actions kiváltása.
Ha nem ismered az alapokat, akkor irány oda, különben egy kicsit elveszett leszel.
Locators
Az egyik, ha nem a legfontosabb dolog az E2E tesztelésben, hogy megtaláld a nézetedben azokat az elemeket, amelyeket tesztelni szeretnél. Legtöbbször fel fogod tenni magadnak a kérdést: “Miért nem találom ezt a **** elemet?”, amit egy “oooohhhhh” követ.”
Ezekre sokféleképpen van lehetőséged. Ezek többsége az alkalmazásodtól függ. Ahhoz, hogy megtaláld az elemeidet, a Locatorok egy sorát fogod használni. Legtöbbször a következőkkel találhatod meg az elemeidet:
- Class name.
- Id.
- Model.
- Binding.
A következő tesztekhez ezt a sablont fogjuk használni.html:
<div class="parent2"> <div class="parent1"> <div class="nested-class" style="color:blue;"> I am a nested element </div> </div></div>
Fókuszáljunk a nested-class-ra és a nested-id-re.
By Class:
Megragadjuk itt az elemünket az element(by.css(selector)), majd teszteljük, hogy jelen van-e vagy sem.
By Id:
it("should find the nested id", () => { let elem = element(by.id("nested-id")); expect(elem.getText()).toBe("I am a nested element");});
Megragadjuk itt az elemünket az element(by.id(elem-id)) segítségével, majd teszteljük, hogy jelen van-e vagy sem.
A következő lokátorok nagyon hasznosak az AngularJS-ben, de még nem implementálva az Angular 2-ben, ezért egyelőre tartsuk őket félre.
By Model:
it("should find the model", () => { let elem = element(by.model("modelToFind")); expect(elem.isPresent()).toBeTruthy();});
By Bindings:
it("should find the binding", () => { let elem = element(by.model("bindingToFind")); expect(elem.isPresent()).toBeTruthy();});
A tesztek hibakeresése érdekében egyszerűen hozzáadhatjuk a “browser.pause()”-t a tesztünkhöz, így az összes előző utasítást lefuttathatjuk és megállíthatjuk, ahol akarjuk.
Mihelyt eléri a szünetet, egy ehhez hasonló képernyő jelenik meg:
Amint ezen a képen is látszik, ahhoz, hogy a vezetőülésbe kerülj, be kell írnod a repl-t.
Tegyük fel, hogy nincs semmilyen teszted, és csak játszani szeretnél a Protractorral. Csak beírhatod a terminálodba:
protractor --elementExplorer
Ha valami gond van az útvonaladdal, akkor beírhatod:
./node_modules/protractor/bin/elementexplorer.js
Ezúttal nem kell repl-t beírnod, csak használd a böngészőobjektumot, és máris hajózhatsz!
Lapobjektumok
Mi van, ha vannak tesztjeid, amelyek ugyanazt a forgatókönyvet használják? Mindenhol copy paste-elni fogod a kódodat? Mi van, ha ez a forgatókönyv megváltozik? Most minden fájlt át kell nézned, és el kell végezned a módosításokat.
Ez az a pont, ahol az Oldalobjektumok nagyon hasznosak lesznek. Írj egyszer, oszd meg mindenhol!
A Page Object egy olyan objektum, amely egy oldalra vonatkozó elemeket és forgatókönyveket tartalmaz.
Először egy nagyon egyszerű Page Object:
export class HomePage { nestedClass; constructor() { this.nestedClass = element(by.css(".nested-class")); }}
Aztán használjuk a tesztünkben:
Importáljuk a Page Objectet, létrehozunk egy példányt, majd használjuk a tulajdonságát.
Aszinkron kalandok
Most barátaim, elérhetjük az oldalunk bármely elemét! Mármint majdnem :).
Lesz néhány speciális eset.
Ha voltál olyan (nem)szerencsés, hogy jQuery-vel dolgoztál, akkor bizonyára ismered a document.ready() funkciót.
A JavaScript aszinkron természetéből adódóan lesznek olyan esetek, amikor megpróbálsz hozzáférni egy elemhez, mielőtt az még megjelenne az oldalon.
Ezek kezelésére a Protractor egyik funkcióját kell használnunk, hogy megvárjuk, amíg az elem készen áll, mielőtt megkeresnénk.
Itt egy példa egy gomb megjelenítésére az időkorlát lejárta után.
Először az osztály, amely tartalmazza az időtúllépést:
export class Home { isHidden = true; triggerTimeOut = ((){ setTimeout(() => this.isHidden = false, 2250) })}
Majd a template.html:
Itt van egy gombunk, amely kiváltja az időtúllépésünket, az időtúllépés lejárta után megjelenik a szöveg.
Itt vannak a tesztek.
Megtaláljuk a gombunkat, rákattintunk, megpróbáljuk megtalálni a szövegünket, DE elvárjuk, hogy ne legyen jelen.
És itt van, hogyan kezeljük ezt az esetet ;).
A “browser.wait” kombinálva a “browser.isElementPresent”-el teszteljük a Locatorunkat. Az 5 másodperc elteltével a kód többi része végrehajtásra kerül. Ne felejts el ide időzítőt tenni, különben a tesztjeid örökre blokkolva maradnak!
Ha tehát az egyik elemednek itt kellene lennie, de nem tudod megszerezni, akkor a megérzésednek azt kell mondania, hogy emlékezz arra, amit itt olvastál.
Actions
Most, hogy megvan az értékes elemed, a munka 90%-át elvégezted!
Ha nem találod, akkor vagy az alkalmazásod nem úgy működik, ahogy kellene (ezért csinálunk teszteket), vagy jobbá kell válnod a tesztelésben, és kevesebb időt kell Pokemon GO-val töltened, hogy hajnali 1-kor egy folyó mellett dratinikra vadászol (mindannyian voltunk már így…).
Folytassuk tovább az akciókkal, amelyeket egy elemen használhatsz. Itt vannak:
A Protractort használjuk, amely a WebDriverre támaszkodik. Ha több fantáziadús akcióra van szükséged, megnézheted, hogy mi áll rendelkezésedre itt.
Teszteljünk néhányat közülük.
A template.html esetében:
<input type="text" />
Játszunk egy kicsit a szövegbevitellel. Gyors kvíz, mit csinál ez a teszt (ne olvassuk el a leírást)?
Megoldás: Megkapjuk a bemenetünket, beírjuk bele “Some text”, teszteljük, hogy megkaptuk a beállított értéket, töröljük, és végül teszteljük, hogy az érték üres.
Legvégül megkérdezhetjük magunktól, hogy mi a legjobb módja az akciók kiváltásának? Ez a link itt mutatja be a WebDriver helyett a JavaScript használatának egyik hibáját.
Sajnos a JavaScriptben való írás sokkal kompaktabb, de ez némi kockázattal jár!
Az elemmel bármit megtehetsz, amit csak akarsz. A legjobb módja a tesztelésnek a rendelkezésre álló matcherek használata. Miért? Mert elegánsak és közel állnak az emberi nyelvhez, példa:
expect(apples.length !== 0).toBe(true);
expect(apples).not.toBeEmpty();
Következtetés
Ez volt a sorozat utolsó bejegyzése, most már 90%-ban birtokában vagy az Angular 2 alkalmazások teszteléséhez szükséges ismereteknek. A maradék 10%-ot tapasztalat útján fogod megszerezni. Ne feledd, először a Locators segítségével szerezd meg az elemeidet, majd az esetlegesen replikálódó elemet tedd be egy Page Objectbe, ha nem találod az elemedet, és biztos vagy benne, hogy itt van, akkor lehet, hogy azért, mert még nem jelent meg, és kezelni kell az aszinkronitást. Végül tesztelje a **** ki az elemeit az Actions.
segítségével.