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 package test; import org.junit.Test;
Běžná Java třída Veřejné metody se speciálními anotacemi (balík org.junit)
public class OrderTest1 {
◦ @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
2.5. 2016
@Before public void init() { initialize(); } @Test public void test1() { doSomething(); }
}
UUR - TESTOVÁNÍ
@Test public void test2() { doSomething(); }
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Í