Testování GUI RICHARD LIPKA 2.5.2016
Proč testovat Uživatel nemá radost z nefungující aplikace hledání bugů Test driven development unit testy definují jednotlivé části aplikace Testovat tam kde to má smysl a s určitým cílem Ne proto že to jde snadno testovat kde to je potřeba Ne proto že to někdo nařídil nepsat 10 denně testů kvůli nějaké metrice U GUI lze testovat Funkčnost pokud možno už při programování Lze automatizovat, alespoň částečně relativně levné Použitelnost částečně lze i při návrhu, nad prototypy i hotovou aplikací Lidská práce nenahraditelná V různých fázích vývoje různí testeři (prototyp raději s IT vzdělanějšími lidmi) Zásadní u webových a mobilních aplikací obvykle lze velmi snadno najít alternativu (SAP si může dovolit být ošklivý a nepřehledný, protože je jeden) testy nezbytnou součástí životního procesu SW http://googletesting.blogspot.cz/ Spousta zajímavých a užitečných informací o testování 2.5. 2016 UUR - TESTOVÁNÍ 2
Automatické testy Není třeba se spoléhat na testery levnější, snazší, nezapomíná se na ně tak snadno Testují jen funkcionalitu unit testy, integrační testy Závislé na technologii (na rozdíl od uživatelských testů) Testy správného nastavení GUI Testy na přítomnost požadovaných komponent Testy vlastností komponent přítomných v GUI Scénáře interakce s uživatelem Počáteční stav (může být obtížné ho navodit) Sekvence vstupů od uživatele Testování výsledků (obvykle přítomnost správného textu na správném místě) 2.5. 2016 UUR - TESTOVÁNÍ 3
Testovací nástroj Umí simulovat vstup od uživatele Jeho záznam co nejjednodušší nahrávání maker / popis scénářů Nezpůsobí problémy s časováním neběží moc rychle Má spolehlivý způsob detekce prvků GUI Souřadnice nejsou moc vhodné musí tolerovat Změny pozice komponenty Změny velikosti komponenty Změny layoutu Automaticky spouští celou sadu testů GUI testy pomalé musí simulovat uživatele nejde je moc urychlit Dokáže shromažďovat výsledky a informovat o chybě Výpis zprávy nebo výjimky je obvykle málo Hodí se screenshoty nebo záznam celého testu (video, události v aplikaci, logy, ) 2.5. 2016 UUR - TESTOVÁNÍ 4
Nástroje pro testování GUI Jubula (BREDEX GmbH) Samostatná aplikace nebo plugin do Eclipse, zdarma Tvorba testů bez nutnosti rozumět zdrojovým textům Sestavení scénářů z jednotlivých kroků, poměrně náročné Dokumentace na http://testing.bredex.de/, poměrně podrobná QF-Test Samostatná aplikace, placená (cca 2000 za jednu technologii) Podpora Swing, SWT, JavaFX, webu Stabilní, existuje přes deset let Sestavení scénářů z akcí nebo nahrávání ve stylu maker 2.5. 2016 UUR - TESTOVÁNÍ 5
Testovatelné GUI Testování lze usnadnit vhodným návrhem GUI GUI vrstva co nejtenčí Ostatní vrstvy lze snáz testovat unit testy testy GUI nemusí ověřovat správnost logiky aplikace ale jen fungování GUI Oddělení logiky od konstrukce aplikace (továren) Důsledně pojmenovávat všechny komponenty Unikátní identifikátory (fx:id) je snazší komponenty najít Metody tvořící GUI dostupné pro testy Je nezbytné aplikaci dostatečně strukturovat Často pomůže modifikátor protected testy ve stejném balíku (nebo veřejná rozhraní) Pozor na další závislosti přístupy do DB, čtení souborů, 2.5. 2016 UUR - TESTOVÁNÍ 6
Nástroje pro JavaFX - API Jemmy Vyvíjen v Oracle, poslední verze z roku 2012 nepoužitelné, neaktualizované Automaton Knihovna pro testování Java GUI původně pro Swing, upraven i pro JavaFX Udržován, poslední verze z roku 2014 Založen na groovy skriptech urychluje psaní testů TestFX Vychází z Automatonu, určen pro JavaFX Poslední verze (4.0.1) z května 2015 Aktivně vyvíjen verze se od sebe značně liší Stejní lidé jako QF-Test 2.5. 2016 UUR - TESTOVÁNÍ 7
JUnit velmi lehký úvod Automatické testování v Javě Základ pro test-driven development, pokud je žádán Psát testy na každou chybu která je objevena v ideálním případě lze po každé změně automaticky otestovat celou aplikaci Testy by měly být jednoduché každý test zaměřený na jednu vlastnost V rámci možností mohou potřebovat složité nastavení Složité získávání vstupních dat Framework zajistí automatické spouštění a sebrání výsledků Využití reflexe v Javě není třeba psát testovací main() a podobné věci Rozšířený většina nástrojů pro správu projektů je podporuje, existují klienti pro shromáždění výsledků Podpora ve vývojářských nástrojích v classpath musí být knihovna JUnit a případná rozšíření V současnosti existuje ve verzi 4 2.5. 2016 UUR - TESTOVÁNÍ 8
JUnit struktura testů Struktura projektu: src main my.package MyClass.java test my.package MyClassTest.java JUnit zajistí volání všech testů ze složky test Využívá reflexi prohledá všechny třídy a najde testové metody Po spuštění zobrazí výsledky, pokud test neprojde zobrazí i důvody selhání V classpath musí být potřebná knihovna (Eclipse ji umí přidat sám) 2.5. 2016 UUR - TESTOVÁNÍ 9
JUnit struktura testu Běžná Java třída Veřejné metody se speciálními anotacemi (balík org.junit) @BeforeClass před spuštěním testů dané třídy (inicializace globálních dat, statická) @Before před spuštěním každého testu (nastavení výchozího stavu) @Test označení jednoho testu @After po spuštění každého testu (čištění prostředí) @AfterClass po spuštění všech testů z dané třídy (statická, vracení zdrojů) Pořadí testů nedefinováno package test; import org.junit.test; public class OrderTest1 { } @Before public void init() { initialize(); } @Test public void test1() { dosomething(); } @Test public void test2() { dosomething(); } 2.5. 2016 UUR - TESTOVÁNÍ 10
JUnit - kontroly Metody které vedou k ukončení testů Aserce (porovnání které může vyvolat nesplnění testu vyhození výjimky, které JUnit loguje) asserttrue(string message, boolean condition), assertfalse() assertequals(message, expected, actual), assertequals(message, expected, actual, tolerance) assertnull(), assertnotnull() assertsame(), assertnotsame() Selhání fail(string message) 2.5. 2016 UUR - TESTOVÁNÍ 11
JUnit ukázka testu import org.junit.test; import static org.junit.assert.*; public class MyUnitTest { } @Test public void testconcatenate() { MyUnit myunit = new MyUnit(); String result = myunit.concatenate("one", "two"); assertequals("onetwo", result); } public class MyUnit { } public String concatenate(string a, String b) { return a + b; } 2.5. 2016 UUR - TESTOVÁNÍ 12
Nakládání s testy Zdrojový text jako každý jiný Při výjimkách volat fail(), neskrýt je Dodržovat konvence jazyka a projektu (i když nedělají nic užitečného ) Jmenné konvence Pravidla pro práci s cestami Pozor na práci s Locale, zvlášť při parsování dat Locale se může měnit kvli nastavením OS Verzovat, ukládat do úložiště Obvykle se zdrojovými texty Test může být platný jen do určité verze programu Udržovat při větších změnách mezi verzemi!!! Komentovat, komentovat, komentovat (test je často málo srozumitelný bez důkladné znalosti programu musí být jasné co testuje) 2.5. 2016 UUR - TESTOVÁNÍ 13
Dobrý test Izolovaný testy jsou na sobě nezávislé Jednoduchý testuje jen jednu funkci / vlastnost jedna aserce Jasná jmenná konvence co se testuje, scénář, výsledek Organizovaný Arange (Given), Act (When), Assert (Then) Rozdělené ne vždy chci spouštět všechno (integrační testy trvají dlouho) balíky testů (test suit); test GUI trvají dlouho Rozumné zprávy proč test selhal, ne co se stalo, uvést očekávané hodnoty pokud to jde Parametrizace umožňuje snazší vkládání testovacích dat, ovlivnit dobu běhu testu, 2.5. 2016 UUR - TESTOVÁNÍ 14
TestFX Testování GUI pro JUnit Umožňuje popsat akce, automaticky je provést a ověřit jejich výsledky Navržen přímo pro JavaFX Aktivně vyvíjený projekt, od autorů QF-Test Funkce Řízení ovládacích prvků (klávesnice, myš) Vyhledávání uzlů grafu scény na obrazovce CSS selektory, text který obsahují, souřadnice Testy vlastností, získání referencí na ně Získání screenshotů když test selže fluent API podobně jako u streamů lze řetězit volání 2.5. 2016 UUR - TESTOVÁNÍ 15
Závislosti Informace platné pro verzi 4.0.1 Vlastní balíky : testfx-junit testfx-core testfx-legacy Ve stejné verzi, dostupné z Maven repositářů nebo z GitHubu Potřebuje: JUnit 4.1 rozšíření Hamcrest 1.3 (balík core, podpora pro porovnávání různých objektů) Guava 18 (kolekce, nová primitiva, anotace, I/O operace, od Google) 2.5. 2016 UUR - TESTOVÁNÍ 16
TestFX ukázka testu public class SimpleFXAppTest extends ApplicationTest { @Override public void start(stage primarystage) throws Exception { Parent root = FXMLLoader.load (this.getclass().getresource("/fxml/simplefxapp.fxml")); primarystage.setscene(new Scene(root)); primarystage.show(); } @Before public void initialization() { TextField textfield = lookup("#textfield").queryfirst(); textfield.clear(); } @Test public void testhandleprocess() { String text = "Example test"; clickon("#textfield").press(keycode.delete); write(text); clickon("#upcasebutton"); verifythat(lookup("#textfield").queryfirst(), hastext("example TEST")); } } 2.5. 2016 UUR - TESTOVÁNÍ 17
Propojení s testovanou aplikací Test se musí chovat podobně jako aplikace zobrazit GUI Knihovna zajistí volání launch() nikde ho nevolejte sami Dědit od třídy ApplicationTest Metoda start(stage primarystage) Uvnitř start() totéž co by dělala aplikace při spouštění Výhodné využití FXML uvnitř start() se jen volá loader Pokud se po načtení dělá něco dalšího (obsluhy, nastavení které ve FXML nejsou), musí se provést i v testu, jinak testuji něco jiného! Testy obvykle ve stejném balíku vidí protected metody a metody bez modifikátorů, lze je využít (např. pokud tvoří části GUI) Po skončení start() musí být okno zobrazené (jinak nebude kde hledat uzly) 2.5. 2016 UUR - TESTOVÁNÍ 18
Hledání uzlů v grafu scény Porovnávač umí pracovat S textem v ovládacím prvku S CSS selektory třídami a ID (pozor, od jedné třídy je obvykle několik) nejužitečnější, důsledně používat ID! Se souřadnicemi Metoda lookup() jako parametr stačí String s CSS selektorem Vrací NodeQuery - třídu reprezentující výsledek z ní lze získat první uzel (queryfirst() ) nebo celou kolekci nalezených prvků (queryall() ) Se získanými prvky jde normálně pracovat, volat nad nimi jejich metody, zjišťovat jejich stav, lookup() prohledává celý graf, z uzlu lze získat jen jeho přímé potomky 2.5. 2016 UUR - TESTOVÁNÍ 19
Hledání uzlů v grafu - lookup lookup("#textfield").queryfirst() Najde prvek s id "textfield", vrací Node (nebo typ toho co čeho se přiřazuje pozor na výjimky) TextField field = lookup("#textfield").queryfirst() Label field = lookup("#label").queryfirst() S uzlem lze v testu dál pracovat lookup(hastext("some label")).queryfirst() Najde prvek (množinu prvků) obsahující text "Some label" lookup(haschild("text")) Najde prvek obsahující potomka ve kterém je text "text" Pozor, to nejspíš bude víc prvků třeba panel ve kterém je seznam s potomky lze dohledat podle třídy lookup(haschild("text")). select(instanceof(listview.class)).queryfirst(); 2.5. 2016 UUR - TESTOVÁNÍ 20
Ovládání aplikace Metody simulující akce uživatele provedené nad komponentou předanou v parametru nebo nad tou, která má fokus Myš Parametr je buď reference na prvek nebo přímo CSS selektor clickon klikne na zadaný prvek nebo souřadnici (volitelný druhý parametr druh tlačítka) doubleclickon dvojklikne na zadaný prvek nebo souřadnici moveto pohyb na zadané místi (absolutní) moveby posun o zadané parametry (relativní) scroll scrollování Klávesnice type simuluje stisk klávesy (KeyCode) press simuluje stisk klávesy nebo tlačítka myši write simuluje psaní řetěce erasetext mazání textu sleep pozastaví vykonávání testu 2.5. 2016 UUR - TESTOVÁNÍ 21
Ovládání aplikace - ukázka clickon("#upcasebutton") klikne na element s příslušným selektorem Button button= lookup(hastext("ok")).queryfirst(); clickon(button) klikne na tlačítko s popiskem "ok " clickon("#upcasebutton", MouseButton.MIDDLE) klikne středním tlačítkem myši String text = "text"; clickon("#tfield").press(keycode.delete).write(text) klikne na element s ID tfield, stiskne klávesu DELETE a pak napíše text Ukázka fluent API řetězení volání 2.5. 2016 UUR - TESTOVÁNÍ 22
Ověření výsledků Lze použít aserce z Unit testů Způsobí pád testu a mohou předat zprávu Neposkytnou žádnou další informaci Vlastní metoda pro testování hodnot Sada metod verifythat() Obalují aserci, kromě ukončení testu při chybě také screenshot obrazovky Ověření, že zadaný uzel (CSS selektor nebo reference na uzel) splňuje vlastnost definovanou porovnávačem 2.5. 2016 UUR - TESTOVÁNÍ 23
Ověření výsledků Matcher ověření že zadaný uzel splňuje vlastnost v porovnávači Využívá stávající porovnávače (hastext, hasitem, haschild, isenabled, isdisabled, isvisible, hasdimension) verifythat(lookup("#textfield").queryfirst(), hastext("example TEST")) Predikát Ověření že zadaný uzel splňuje logickou podmínku Zadání v podobě lambda výrazu verifythat("#textfield", (TextField field) -> { if (field.gettext().compareto("example TEST") == 0) return true; else return false; }); 2.5. 2016 UUR - TESTOVÁNÍ 24
Uživatelské testy Způsob testování se liší podle požadovaných výsledků Pro testování komplexních vlastností (uživatele potřebuji protože napsat automatický test je moc složité) Navigace skrz složitou aplikaci Ověření funkčnosti věcí, které se automaticky těžko zjišťují (např. titulky ve videu, zvuky, komunikace s periferiemi, ) Testy u zákazníka (funkčnost, soulad s firemními procesy) Regresní testy Testování použitelnosti (uživatele potřebuji, protože programuji pro ně a ne pro počítač) Přehlednost tabulek a formulářů Čitelnost textů Dostupnost používaných funkcí 2.5. 2016 UUR - TESTOVÁNÍ 25
Testové scénáře Připravené před testováním Měly by pokrývat všechny funkce aplikace někdy mapované na případy užití Obvykle existuje řada cest není reálné pokrýt všechny trasy uživatele aplikací (navíc se uživatel musí dostat do patřičného výchozího stavu) Složité regresní testování GUI se může měnit i když se nemění jádro aplikace Připravená vstupní data Scénáře by měly být opakovatelné Popis prostředí ve kterém mají být testy prováděny OS, HW, síťová konektivita, požadované služby, 2.5. 2016 UUR - TESTOVÁNÍ 26
Průzkumné testy Bez pevně daného scénáře, tester si s programem hraje Snazší a levnější příprava Rychlé nalezení kritických problémů, ale nesystematické Založené na požadavcích na aplikaci (Requirements nemusí mít formální popis) Neopakovatelné, zprávy nejsou strukturovatelné Nelze je pořádně naplánovat, není jasné jak dlouho budou trvat Nelze je dopředu analyzovat, zjišťovat pokrytí kódu a podobně Tester musí umět zacházet s nástrojem na hlášení bugů Výsledky záleží na schopnostech testera Může urychlit testování ví na co se má soustředit, nemusí projít celým balíkem testů Velmi užitečné ve všech fázích vývoje 2.5. 2016 UUR - TESTOVÁNÍ 27
Struktura scénáře Popis scénáře co vlastně testuje Ne příliš dlouhý a komplikovaný Všechny scénáře by měly testerům zabrat stejnou dobu, aby se dal odhadnout čas testování Prerekrivizity Popis všeho co musí být splněno před jeho spuštěním, nepodcenit Jednotlivé kroky scénáře Popis akcí uživatele (srozumitelný pro očekávané testery) Popis očekávaných výsledků (texty, okna, dialogy, vzniklé soubory) Se scénáři zacházet jako s jakýmkoliv jiným zdrojovým textem Verzování navíc informace o tom jaká verze scénáře k jaké verzi aplikace 2.5. 2016 UUR - TESTOVÁNÍ 28
Podpora pro testery Tabulky v Excelu časté, ale nepraktické pro větší testy (WordPad má cca 400 akcí v GUI) Hodí se pro onsite testování u zákazníka lidé s ním umí zacházet je potřeba nástroj pro automatizaci Potřebujeme: Možnost vytváření scénářů a jejich spojení s požadavky na aplikaci Popis jednotlivých kroků scénáře Volba scénářů k testování, přiřazení scénářů testerům Přehrávání scénářů testerovi Sběr výsledků testování u kterého kroku scénář selhal a jak, popis a screenshot Přehledy a statistiky Např. TestLink (GPL, webové rozhraní, integrace s Redmine, Jira, Bugzilla a dalšími nástroji) 2.5. 2016 UUR - TESTOVÁNÍ 29
Co testovat Rady hlavně pro průzkumné testy, ve scénářích je tohle obvykle v nějaké podobě obsaženo Dokončení úlohy Může uživatel dokončit požadovanou úlohu? Co v tom překáží (zbytečné dialogy, nemožnost se překliknout mezi okny, ) Čas k dokončení, efektivita Jak dlouho trvá dokončit úlohu, kolik kroků je potřeba Reakce na chyby Jak program reaguje na chybné akce uživatele, vede ho na správnou cestu? Pozná uživatel vážnost problému nebo chyby? Naučitelnost Zlepšuje se rychlost práce s časem užívání? Je ovládání aplikace konzistentní? 2.5. 2016 UUR - TESTOVÁNÍ 30
Výsledky testů Zprávy o chybách a problémech Zanášet do systémů pro řízení chyb pro další zpracování, u řady nástrojů automatizované Hodnocení z průzkumných testů Informace o tom, co je složitě dostupné, kde chybí informace, kde může dojít k poruše dat písemná zpráva Záznamy z práce testera Nahrávání obrazovky, pohybu myši, událostí v aplikaci (pokud existuje logger nebo něco podobného) lze sledovat jak uživatel vykonává zadané úkoly Nahrávání samotného uživatele např. záznam pohybu očí (spíš pro webové aplikace a pokusy se soustředěním) vím na co se uživatel dívá nejdřív a co mu může utéct 2.5. 2016 UUR - TESTOVÁNÍ 31
Užitečná pravidla pro GUI Velmi podobná pravidla jako pro použitelnost webu Desktopové aplikace není tak snadné vyměnit, uživatel má větší trpělivost Větší důraz na dodržování zvyklostí OS uživatel očekává že ovládací prvky vypadají tak, jak jsou zvyklí (záleží na cílovém publiku, jako vždy) Vynechat složitá, víceúrovňová menu Pole o něco delší než očekávaný vstup Ikony nejsou univerzální, barvy také ne Všude texty nebo alespoň tooltipy, některé piktogramy nemusí jít rozeznat Popisky nejlépe nad ovládacími prvky Vertikální scrolling je v pořádku, horizontálnímu se vyhýbat Důsledně zarovnávat, konzistentní zobrazení (velikost mezer, fontů, ) Raději předcházet chybám než vytvářet dialogy (testy vstupu!) Nabízet možnost zotavení z chyby 2.5. 2016 UUR - TESTOVÁNÍ 32
Pravidla pro přístupnost Definována hlavně pro web, ale platí pro každé GUI Vytvářena s ohledem na handicapy uživatelů zvážit co má smysl a co ne V OS asistenční technologie (lupa, čtení, rozpoznání řeči, sledování očí) usnadnit jim práci 4 hlavní zásady Vnímatelnost (Perceivability) textová alternativa pro netextové informace (dá se převést pro speciální periferie zvuk, Braille, ) Použitelnost (Operability) všechny ovládací prvky dostupné (nejlépe klávesové zkratky pro cokoliv) Srozumitelnost (Understandability) jendozančné popisy ovládacích prvků Robustnost (Robust) Systém přežije různé akce uživatelů, špatné pořadí akcí nevede k pádu aplikace (nebo ztrátu dat) 2.5. 2016 UUR - TESTOVÁNÍ 33
Děkuji za pozornost OTÁZKY? NÁZORY, PŘIPOMÍNKY? PŘÍŠTĚ: ANT, MAVEN PŘÍPRAVA APLIKACE PRO NASAZENÍ