Není to poprvé, co píšu o Selenium aka WebDriver. Dnes bych však chtěl mluvit více o detailech technologie. Popravdě chci spíše mluvit o tipech místo popisování WebDriveru krok za krokem.
Dostala se mi totiž do ruky kniha Selenium WebDriver Practical Guide, což je průvodce přes celé API Selenia a mnohem víc. Začne od Selenia první verze a rozdíly mezi právě první a druhou verzí. Tím také vysvětlí, proč je lepší sáhnout po druhé verzi a není zapomenuto pár poznámek o přechodu. Což je podle mne důležité. Je to takový základ k pochopení celé technologie.
Dále kniha pokračuje popisováním API od základů k pokročilým tématům. Sice není popsané vše a občas mi přijde, že je bráno více ohledu na méně důležité části, ale i tak je popis dobrý. Místy to může vypadat jako více ukecaná dokumentace, věřím však, že to začátečníkovi pomůže se rychleji zorientovat.
Někoho může vyděsit, že je důležité znát Javu. Všechny ukázky jsou v knize ukazovány v Javě. Sice mi absence jiných jazyků a odlišností v implementaci chybí, naštěstí jsou ukázky minimalistické bez JUnit či jiných testovacích nástrojů (jednoduše jsou ukázky psané jako jednorázové scripty) a tak se lze v ukázkách lehce zorientovat. I když si s Javou nerozumíte třeba jako já.
Jelikož testování pomocí Selenia se nemusí dělat ve stejném jazyce, jako samotná webová aplikace, je zvolení jazyka k výuce docela škoda. Java je totiž docela psavá a testy, kór Seleniové, moc programátory psát nebaví a ukecanost tomu rozhodně nepomůže. Školil jsem Selenium JavaScriptáře a například s Pythonem neměli žádné problémy (jaké by také mohli mít, když se to tolik podobá CoffeeScriptu). Nedovedu si však představit, kdybych je školil v Javě. Byli by chudáci vyděšení…
Po seznámení s API následuje poslední kapitola seznamující s patternem Page Objects. Pattern, díky kterému lze psát lepší a lépe udržovatelné testy. Z knihy mám však takový pocit, jakoby se tak Seleniové testy měli psát vždy. Nejsem toho názoru. Page Objects je skvělý způsob, jak si udělat mezivrstvu mezi testem a stránkou a tak snížit problémy při změně šablony na minimum. Určitě vhodné pro SPA, nemohu doporučit pro přesně opačný typ webových aplikací (maximálně na nějaké části).
Kniha celkově není vysloveně špatná, ale chybí mi v ní několik dalších praktických rad. Popíšu podle mne ty nejdůležitější.
Začnu u konfigurace – Selenium Grid umožňující pouštět testy přes několik serverů a prohlížečů pravděpodobně nepotřebujete. Začněte si stavět grid pouze, pokud potřebujete otestovat funkčnost na více prohlížečích, nebo až v době, kdy server přestane stíhat. Ušetříte si čas na začátku a zbytečně se do toho nezamotáte. Přece jen rozběhat Windows, Linux, Mac a mobilní platformy a pro každý systém různé prohlížeče není sranda.
Pokud se rozhodnete jen pro jeden prohlížeč, protože vám stačí ověřit funkčnost a nikoliv kompatibilita napříč prohlížeči, doporučuji použít Chrome. Měl jsem s ním nejméně problému a je nejrychlejší (i když instalace je o něco složitější). Tedy minimálně pod Linuxem, nevím jaká je situace jinde.
V knize se vůbec nemluví o běhu na serverech bez grafického prostředí. Samozřejmě něco takového je možné a už jsem o tom psal.
Nyní se přesunu k samotnému psaní testu, konkrétně k výjimce
StaleElementException
. Tato výjimka, co vím, strašila spoustu lidí při
seznamování se Seleniem a překvapilo mě, že se o ni nepíše. Dokonce je v knize
ukázka, kde se něco takového může stát a nijak na možný problém neupozorňuje.
Tedy o co jde – představte si hledací políčko a našeptávač. Implementaci našeptávače mějme takovou, že po zadání znaků se v určitou chvíli odešlou tyto znaky na server, server odpoví se seznamem k našeptání a ty JS zobrazí tak, že starý seznam smaže a nahradí novým. Teď se podívejme na následující test:
def test_autocomplete(self):
search = self.driver.find_element_by_id('search')
search.send_keys('sele')
first_autocomplete = self.driver.find_element_by_tag('li')
self.assertEqual(first_autocomplete.text, 'select')
search.send_keys('nium')
self.assertEqual(first_autocomplete.text, 'selenium')
U posledního řádku dostaneme právě výše zmíněnou výjimku. Proč? Protože při zaslání dalších znaků JavaScript původní element smazal a vytvořil nový. Sice takový element na stránce stále existuje, ale už to není ten samý, který jsme získali na čtvrtém řádku. Na každou proměnnou s elementem lze nahlížet jako na referenci do DOM stromu. Pokud vaše testovaná webová aplikace má k statické stránce hodně daleko, je dobrým zvykem si před prací s elementem vždy vytáhnout čerstvou referenci.
Na to bych navázal s událostí onchange
. Pokud bychom výše uvedený našeptávač
řešili (i když to je trochu blbost) pomocí této události, test nebude vůbec
fungovat. Proč? Protože metoda send_keys
po odeslání posledního znaku
nezařídí ztrátu focusu a tedy se událost onchange
nevykoná. Aby test
fungoval s touto změnou, muselo by se ještě posílat explicitně například znak
zabulátor:
search.send_keys('sele' + Keys.TAB)
Což tedy osobně řeším automaticky pomocí mého wrapperu WebDriverWrapper, díky kterému se vůbec formuláře vyplňují mnohem snadněji. Jedná se však pouze o Python.
WebDriverWrapper neřeší pouze formuláře, řeší toho mnohem víc. V naší aplikaci máme například prokliky do cizích systémů či nějaké popup okna. Stalo se nám, že se jeden test neočekávaně proklikl pryč a pak kvůli tomu selhali ostatní testy. Vyřešeno tak, že na začátku testu se zaručí běh v hlavním okně, aniž by se to muselo v každém testu dělat ručně.
Ale to už se dostávám k detailům, které zde nechci řešit. Cílem bylo zhodnotit knihu Selenium WebDriver Practical Guide pro Packt Publishing a říct důležité věci, které mi v knize chyběly. Což jsem udělal a tak jste snad zase o něco chytřejší. :-)