Sem vložte zadání Vaší práce.
České vysoké učení technické v Praze Fakulta informačních technologií Katedra softwarového inženýrství
Bakalářská práce
Organizátor cvičebních plánů David Veselý
Vedoucí práce: Ing. Jiří Daněček
17. května 2013
Poděkování Děkuji svému vedoucímu práce Ing. Jiřímu Daněčkovi za bezproblémovou spolupráci. Dále bych rád poděkoval všem, kteří mi kdy pomohli, a to nejen při psaní této práce.
Prohlášení Prohlašuji, že jsem předloženou práci vypracoval samostatně a že jsem uvedl veškeré použité informační zdroje v souladu s Metodickým pokynem o etické přípravě vysokoškolských závěrečných prací. Beru na vědomí, že se na moji práci vztahují práva a povinnosti vyplývající ze zákona č. 121/2000 Sb., autorského zákona, ve znění pozdějších předpisů, zejména skutečnost, že České vysoké učení technické v Praze má právo na uzavření licenční smlouvy o užití této práce jako školního díla podle § 60 odst. 1 autorského zákona.
V Praze dne 17. května 2013
.....................
České vysoké učení technické v Praze Fakulta informačních technologií c 2013 David Veselý. Všechna práva vyhrazena.
Tato práce vznikla jako školní dílo na Českém vysokém učení technickém v Praze, Fakultě informačních technologií. Práce je chráněna právními předpisy a mezinárodními úmluvami o právu autorském a právech souvisejících s právem autorským. K jejímu užití, s výjimkou bezúplatných zákonných licencí, je nezbytný souhlas autora.
Odkaz na tuto práci Veselý, David. Organizátor cvičebních plánů. Bakalářská práce. Praha: České vysoké učení technické v Praze, Fakulta informačních technologií, 2013.
Abstract This thesis is about an analysis and implementation of a new training plan organizer for CrossFit athletes. The goal of this work is to create a functional application in which it is possible to generate trainings and to synchronize training plans. This is achieved by java frameworks, especially Spring MVC, Hibernate and RESTEasy. The synchronization of training plans is accomplished by graph theory and Dijkstra’s algorithm. The last part is an analysis and comparison of web testing frameworks. Keywords CrossFit, software, testing, Selenium, Canoo WebTest, training, movement, Spring MVC, Dijkstra’s algorithm
Abstrakt Tato práce se zabývá analýzou a implementací organizátoru cvičebních plánů pro sportovce nového odvětví fitness - CrossFit. Jejím cílem je vytvoření funkční aplikace umožňující generování jednotlivých tréninků a synchronizaci celých cvičebních plánů. Toho je dosaženo za pomoci javovských 9
frameworků, především pak Spring MVC, Hibernate a RESTEasy. Cvičební plány jsou synchronizovány na základě teorie grafů a Dijkstrova algoritmu. Součástí této práce je i analýza frameworků pro automatizaci testování webových aplikací zakončená jejich srovnáním. Klíčová slova CrossFit, software, testování, Selenium, Canoo WebTest, trénink, cvičení, Spring MVC, Dijkstrův algoritmus
10
Obsah Úvod
17
1 CrossFit
19
2 Úvod do testování softwaru 2.1 Fáze testování . . . . . . . . . . . 2.2 Testování černé skříňky . . . . . . 2.3 Testování bílé skříňky . . . . . . . 2.4 End-to-End Testování . . . . . . 2.5 Testování z pohledu programátora 2.6 Testovací styly . . . . . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
21 21 23 24 24 25 27
3 Analýza požadavků 3.1 Případy užití . . . . . . . . . . 3.2 Popis domény . . . . . . . . . . 3.3 Generování cvičebních plánů . . 3.4 Synchronizace cvičebních plánů
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
29 29 31 32 34
. . . .
39 39 44 46 47
4 Návrh a realizace 4.1 Technologie . . . . . . . . . . . 4.2 Architektura . . . . . . . . . . . 4.3 Generování cvičebních plánů . . 4.4 Synchronizace cvičebních plánů
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
5 Analýza testovacích frameworků pro webové aplikace 51 5.1 Selenium . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 5.2 Canoo WebTest . . . . . . . . . . . . . . . . . . . . . . . . . 54 11
5.3
Porovnání testovacích frameworků . . . . . . . . . . . . . . .
55
6 Testování aplikace 63 6.1 Funkční testování . . . . . . . . . . . . . . . . . . . . . . . . 63 6.2 Mazací politika . . . . . . . . . . . . . . . . . . . . . . . . . 63 6.3 Vlastní testy . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Závěr
67
Literatura
69
A Seznam použitých zkratek
71
B Obsah přiloženého CD
73
12
Seznam obrázků 2.1 2.2
V-model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Cyklus Test-Driven Development . . . . . . . . . . . . . . . . .
22 26
3.1 3.2
Případy užití . . . . . . . . . . . . . . . . . . . . . . . . . . . . Graf podobnosti . . . . . . . . . . . . . . . . . . . . . . . . . . .
30 35
4.1 4.2 4.3
Základní struktura Spring MVC ([4]) . . . . . . . . . . . . . . . Klient-server demonstrace . . . . . . . . . . . . . . . . . . . . . Relaxace hrany . . . . . . . . . . . . . . . . . . . . . . . . . . .
40 44 49
5.1 5.2 5.3 5.4
Základní architektura Selenia RC . . . . . . . . . . . . . . Sumarizace testování frameworku Canoo WebTest . . . . . Sumarizace konkrétního testu frameworku Canoo WebTest Výpis Selenium WebDriver testu . . . . . . . . . . . . . .
. . . .
53 58 59 60
6.1
Výsledek funkčního testování . . . . . . . . . . . . . . . . . . . .
64
13
. . . .
. . . .
Seznam tabulek 5.1 5.2
Znázornění doby trvání jednotlivých testů dle scénářů ze sekce 5.3 57 Shrnutí porovnání jednotlivých frameworků . . . . . . . . . . . 61
15
Úvod V této práci se budu zabývat tvorbou klient-server aplikace, která slouží k tvorbě a synchronizaci cvičebních plánů pro sportovce nového odvětví fitness - CrossFit. Ke CrossFitu jsem se poprvé dostal díky svému spolužákovi ze střední školy, který v té době uvažoval o možnosti nejen CrossFit cvičit, ale také ho trénovat. Později mi byla nabídnuta možnost vyvíjet aplikaci spojenou právě s tvorbou tréninků založených na myšlence CrossFitu. Po pár setkáních jsem si uvědomil, že celý problém převyšuje svým rozsahem rozsah bakalářské práce, a proto jsem ho zformuloval do jejího zadání. V současné době existují pro CrossFit pouze aplikace zobrazující aktuální trénink dostupný z jeho oficiálních stránek ([15]), ale chybí aplikace, které by umožňovaly sportovcům výběr cviků pro cvičení a následně trénink vygenerovaly. Proto je hlavním cílem, který jsem si stanovil, analýza problému generování a synchronizace cvičebních plánů a následná implementace za pomoci architektury klient-server. Tato architektura byla zvolena ihned bez větší analýzy, neboť v budoucnu by měl být umožněn přístup k aplikaci i prostřednictvím Android a iOS aplikací. Dalším neméně důležitým cílem je hotovou aplikaci řádně otestovat. K testování bude zapotřebí analýza testovacích frameworků pro webové aplikace a drobný úvod do problematiky testování.
17
Kapitola
CrossFit CrossFit ([15]) je nový, rapidně se rozšiřující tréninkový systém. Původně byl vyvíjen pro povolání, u nichž je nutné splňovat určitou úroveň fyzické zdatnosti (speciální vojenské jednotky, policejní jednotky, hasiči). Problém byl v tom, že nikdo z vyjmenovaných skupin nemohl přesně určit, na jaký typ výkonnosti se připravit. Bylo nutné vytvořit takový tréninkový program, který by byl maximálně univerzální pro jakoukoli fyzickou zátěž. Tudíž dalším krokem bylo definovat typy fyzické zátěže, které mohou potkat jakéhokoli člověka, jen ne v takové míře, jako člena speciální jednotky. Definice fyzické zátěže tedy znamenala definici fitness. Časem se přišlo na to, že veličiny pozorované u nemocných lidí, jako jsou krevní tlak, hladina krevního cukru, množství tuku nebo množství svaloviny, jsou veličiny, které jsou u CrossFit atletů tréninkem posouvány opačným směrem. Došlo tedy ke sloučení definice fitness a zdraví. Tím se CrossFit nestal pouze tréninkovým programem pro členy speciálních jednotek, ale stal se programem pro kohokoli, kdo chce být zdravý. CrossFit tréninky se vyznačují tím, že sportovci vykonávají funkční pohyby za vysoké intenzity. Neustálé změny funkčních pohybů zaručí připravenost na jakoukoli zátěž v jakoukoli dobu. Funkční pohyby jsou pohyby, které nám jsou dány geneticky, jsou přirozené pro naši fyziologii a jsou tedy tím nejlepším způsobem, jak se pohybovat. Vykonávání pohybů za vysoké intenzity zajistí, že tréninkový program není nutné měnit, protože se trénink nemůže stát snadným, nemůže dojít ke stagnaci výkonu. Vysoká intenzita je většinou určena výkonem podle definice: P =
W t
W = Fs 19
1
1. CrossFit kde W je práce, F je síla, s je dráha a t je čas. Doména času umožní zvyšovat intenzitu, pokud je pevně stanovena vykonaná práce. To znamená, že pokud jsou vedle sebe postaveni dva sportovci, lze přesně určit, jakou práci mají vykonat a ten, co ji vykonal rychleji, ji vykonal za větší intenzity. Má tedy větší výkon a lepší fitness výsledky, což znamená, jak bylo zmíněno výše, že je zdravější. Postupem času se z CrossFit tréninku stal sport, protože časová doména umožnila soupeře porovnávat.
20
Kapitola
Úvod do testování softwaru Pojem testování softwaru mnoha lidem asociuje představu člověka či skupiny lidí, kteří sedí nad hotovým programem a klikají do něho ve snaze zjistit, zda neobsahuje chyby. Já sám si pod těmito slovy vzpomenu na svou první programovací úlohu do školy, v níž se snažím přijít na ještě neověřené vstupy. Testování však není pouze o zkoumání hotového programu. Lze testovat i celý průběh jeho vývoje, či dokonce napsat testy dříve než jeho první řádku. Z tohoto důvodu bych tuto kapitolu rád věnoval obecnému úvodu do testování. Pro celou tuto kapitolu jsem čerpal z těchto zdrojů: [6], [7], [17], [19].
2.1
Fáze testování
Testování se z důvodu odlišnoti v každé fázi vývoje softwaru dělí do následujícíh fází: • Jednotkové testování (Unit Testing) • Integrační testování (Integration Testing) • Systémové testování (System Testing) • Akceptační testování (Acceptance Testing) Pro lepší pochopení jednotlivých testování slouží takzvaný V-model, na kterém je vidět, v jakých fázích vývoje jsou testy prováděny (viz obrázek 2.1). 21
2
2. Úvod do testování softwaru
Business požadavky
Verifikace produktu
Specifikace požadavků
Akceptační testování
Systémové a integrační testování
Návrh funkčností
Implementace
Jednotkové testování
Obrázek 2.1: V-model
2.1.1
Jednotkové testování
Jednotkové testování (tzv. „unit testing“) je tou nejzákladnější formou testování. Provádí se již při vytváření zdrojového kódu. Nejčastěji jednotkové testy tvoří samotní programátoři, ale není to pravidlem. V bližším kontextu je jednotkové testování procesem zkoumání funkčnosti co nejmenších částí kódu. Tyto části jsou poté nazývány jednotkami. V procedurálním programování mohou být jednotky samotné funkce či procedury. Naopak v objektově orientovaném programování se za jednotku nejčastěji považuje třída. Jelikož třídy bývají často provázané, nahrazují se právě netestované třídy tzv. mock objekty, které mají stejné rozhraní a metody, ale chovají se přesně, jak daný test předpokládá. Díky tomuto komfortu může být třída otestována aniž by musela zároveň testovat i třídy jiné. 22
2.2. Testování černé skříňky
2.1.2
Integrační testování
Integrační testování se snaží objevit chyby při propojení jednotlivých jednotek. Ověřuje především komunikaci mezi jednotkami, která byla v jednotkovém testování nahrazena například mock objekty. Ověřování integrace však neprobíhá pouze vnitřně mezi jednotlivými jednotkami, ale i mezi jednotkou a operačním systémem či přímo konkrétním hardwarem. Integrační testování není tím nejdůležitějším testováním a někdy se i zcela vynechává. Důvod je prostý. Integrační testy jsou svým způsobem obsahem i jiných druhů testování a všechny chyby, které objeví, by byly objeveny ve fázích testování na vyšší úrovni. Motivací pro integrační testování jsou především finance. Čím dříve je chyba nalezena, tím méně úsilí a peněz je potřeba na její odstranění.
2.1.3
Systémové testování
Systémové testování má za úkol testovat software jako celek, a proto bývá často označované za nejdůležitější. Sjednocuje dohromady více druhů testů, které potom bývají prováděny ve více kolech. Pokud jsou v jednom kole objeveny chyby, po jejich opravení se testují znovu v kole dalším. Typicky se připraví testovací scénáře, které simulují hlavní práci uživatelů s danou aplikací a tím se ověřují kritické body funkčnosti.
2.1.4
Akceptační testování
Ve chvíli, kdy má dojít k předání softwaru do rukou zákazníka, přichází na řadu akceptační testování. Akceptační testování je prováděno testery zákazníka a jeho hlavním úkolem je zjistit, zda je produkt připraven do ostrého provozu v produkčním prostředí. Někdy dochází k situaci, kdy si zákazník najme k akceptačnímu testování stejnou společnost, která software vyvýjela. Tato varianta nebývá zpravidla úspěšná, jelikož daná firma může (i když neúmyslně) „ušít“ testy na míru.
2.2
Testování černé skříňky
Testování černé skříňky, přesněji dynamické testování černé skříňky, je právě tím způsobem testování, které se pravděpodobně vybaví většině populace. Toto testování je založeno na předpokladu, že daný tester nezná zdrojový kód programu, ale pouze požadavky na jeho funkčnost. Práce takového testera tedy spočívá v kontrole, zda se program chová podle požadavků, reaguje správně na chybné vstupy nebo jestli vrací správné výsledky. 23
2. Úvod do testování softwaru Za zvláštní případ testovaní černé skříňky lze považovat testování specifikací (tzv. statické testování černé skříňky). Statické je z toho důvodu, že při průběhu neběží žádný program, ale pouze čteme dokument a hledáme či testujeme, zda jsou všechny specifikace správně definovány. Nejvíce je pak kladena pozornost na požadavky, které nejsou přesné nebo které z našeho pohledu není možné splnit.
2.3
Testování bílé skříňky
Jelikož černá a bílá jsou odjakživa uváděny jako protiklady, ani testování není výjimkou. Rozdíl spočívá ve znalosti zdrojového kódu testovaného programu. Při testování bílé skříňky tento kód známe. Jak se tedy liší přemýšlení testera bílé skříňky od testera černé skříňky? Především v hloubce kontrolovaného problému. Pokud je znám kód, je i jednodušší nalezení kritického místa, které je potřeba otestovat. Testování bílé skříňky lze rozdělit do dvou skupin stejně jako v případě testovaní černé skříňky, a to na statické a dynamické. Statické pouze zkoumá zdrojový kód a hledá možné logické chyby, chyby v odkazech na data, vstupně-výstupní chyby apod. Dynamické potom testuje funkčnost jednotlivých metod či objektů 1 za běhu programu.
2.4
End-to-End Testování
End-to-End testování je metoda používaná pro test průběhu celé aplikace od začátku do konce a k prokázání, že se aplikace chová přesně tak, jak byla navržena. Účelem takového testování je zajištění funkčnosti aplikace v „ostrém provozu“. Mezi základní aspekty, které by bezpochyby měly být zahrnuty v end-to-end testování, patří: • Testování s produkční verzí databáze. • Testování v konkrétní síti, ve které aplikace poběží. • Testování na produkčním hardwaru. Zcela určitě je potřeba testovat dodávané aplikace v produkčním prostředí. Sama praxe zažila až moc případů, kdy plně funkční vývojový kód 1
Text vychází z jazyku Java. Při testování kódu neobjektových jazyků může jít například o procedury, funkce, apod.
24
2.5. Testování z pohledu programátora selhal po dodání zákazníkovi. Jinými slovy to, že aplikace bezproblémů funguje u programátora doma neznamená, že bude fungovat i u zákazníka. Rád bych uvedl pár příkladů z minulosti, které mluví za vše: Disney 1994 ([6]) Koncem roku 1994 v Americe vydala společnost Disney svůj první program pro děti s názvem: „The Lion King Animated Storybook“. Jelikož šlo o horkou novinku toho roku, spousta rodičů nakupovala hru pro své děti pod stromeček k Vánocům. Natěšené děti se nemohly dočkat, až budou moci začít hrát, ale co se nestalo. Většině rodin se hru nepodařilo vůbec spustit. Ukázalo se, že vývojáři společnosti Disney zcela zapomněli otestovat program na domácích počítačích, které byly v té době pro americkou společnost nejběžnější. jBPM 2012 Tento příklad pojednává přímo z mé osobní praxe, kdy jsem se dostal k práci s frameworkem jBPM (javovský nástroj pro modelování a implementaci procesů pomocí notace BPMN). Jelikož se jedná o open source nástroj, je zcela normální, že se neustále vyvíjí a není v něm vše dokončené. Vyskytl se však problém při vkládání proměnné do procesu. Po krátkém hledání jsem zjistil, že nejsem zdaleka jediný, kdo tento problém musí řešit. Řešení však neexistovalo. Pouze na fóru hlavní vývojář jBPM odpověděl: „Nechápu, kde je chyba. U mě vše funguje. . . “
2.5 2.5.1
Testování z pohledu programátora Typy testů
Akceptační testy Zjišťují, zda celý systém funguje. Integrační testy Zjišťují, zda funguje kód programátora oproti kódu, který programátor neovlivní. Unit testy Zjišťují, zda objekty pracují správně, dodržují zásady objektového programování a zda je práce s nimi „pohodlná“.
2.5.2
Zásady psaní testů
• Testy by vždy měly mít výchozí bod. Například při testování webových aplikací by měl test začínat na konkrétní stránce. • Testy by neměly být žádným způsobem závislé na testech ostatních. 25
2. Úvod do testování softwaru
Napiš jednotkový test, který neprojde
Implementuj funkcionalitu tak, aby test prošel
Napiš akceptační test, který neprojde
Proveď refactoring kódu
Obrázek 2.2: Cyklus Test-Driven Development
• Testy by měly testovat pouze jednu věc (vlastnost). • Testy by po sobě měly tzv. „uklidit“.
2.5.3
Test-Driven Development
Vývoj řízený testy (z anglického Test-Driven Development) je agilní technika vývoje softwaru založená na myšlence, že by testy měly být napsány dříve než zdrojový kód testované funkcionality. Postup při využití TestDriven developlment je možné vidět na obrázku 2.2. Mnoho lidí se domnívá, že důvodem pro psaní testů v předstihu je mít nezáživné testování dříve za sebou, jelikož psaní testů po napsání funkčního kódu je únavnou záležitostí svádějící k odkladu. Nicméně, daleko důležitějším faktem je skutečnost, že pokud programátor napíše testy dříve, má možnost si přesně uvědomit a ujasnit funkcionalitu, kterou následně bude programovat. Díky tomu nebude napsán zbytečně kód, který se později nevyužije, a navíc se minimalizuje množství chyb v kódu. 26
2.6. Testovací styly Pro text o Test-Driven Development jsem se nechal inspirovat nejvíce knihou Growing Object-Oriented Software, Guided by Tests ([13]), která na mě udělala veliký dojem.
2.6
Testovací styly
Testovacích stylů bylo vyvinuto opravdu mnoho, přičemž každý z nich má odlišnou funkci a odhaluje různé typy chyb. Tato kapitola nemá za cíl je uvést a dopodrobna rozebrat všechny, ale pouze ukázat a krátce popsat alespoň jejich malou podmnožinu.
2.6.1
Funkční testování
Funkční testování (Function Testing) patří mezi nejzákladnější styly testování. Je založeno na testování každé funkce zvlášť. Správný test využívající tuto techniku by měl každou funkci testovat izolovaně od funkcí ostatních. Od testu neočekáváme chybu a pokud už se chyba vyskytne, je to z důvodu fundamentální chyby. Na funkční testování se soustředí velká část vývojářských týmů, jelikož mají pocit, že testování každé funkce zvlášť jim zajistí funkcionalitu celkovou. Naneštěstí právě kvůli izolovanosti funkcí není funkční testování příliš mocné. Je jednoduché na vyhodnocení a pomůže zjistit, zda fungují alespoň základní funkce, ale nepomůže najít složitější a více skryté chyby.
2.6.2
Doménové testování
Základem doménového testování proměnných je rozčlenění možných testovacích případů do skupin a jednotlivé skupiny do podskupin. Jednotlivé skupiny či podskupiny poté reprezentují testy, které by měly odhalit stejné chyby. Po rozčlenění je vybrán alespoň jeden reprezentant (test) z každé skupiny, a právě ten je prováděn. Za nejlepší reprezentanty jsou většinou považovány všechny mezní hodnoty. Například pro celá čísla nejsou nejvhodnějšími reprezentanty pouze minimum a maximum, ale stejně důležité mohou být i hodnoty pohybující se kolem minima a maxima. Doménové testování je považováno za účinnější než testování funkční, poněvadž dokáže odhalit složitější druhy chyb. Na druhou stranu testuje vstupy, které jsou pro běžného uživatele málo pravděpodobné a tím pádem toto testování není příliš motivující pro stakeholedery. 27
2. Úvod do testování softwaru
2.6.3
Zátěžové testování
Zátěžové testování (Stress Testing) má za úkol simulovat práci s aplikací za extrémních podmínek s cílem ji tzv. „shodit“. Ve chvíli, kdy se to podaří, je sledováno, jakým způsobem se aplikace zachová a jaké chyby nahlásí. Příkladem zátěžového testování může být otestování maximálního počtu lidí při práci s webovou aplikací v konkrétní moment. Tento styl testování je brán za velmi účinný, protože objevuje především těžko viditelné chyby týkající se především synchronizace vícevláknových aplikací.
2.6.4
Uživatelské testování
Základní a nejdůležitější vlastností uživatelského testování (User Testing) je, že je prováděno koncovými uživateli aplikace. Důležité je klást důraz na to, aby šlo opravdu o koncové uživatele a nejednalo se o žadné testery ani náhodně vybrané osoby, které uživatelskou práci pouze simulují a na uživatele si jen „hrají“. Jediná práce testerů při tomto druhu testování může být vytvoření a navrhnutí testovacích scénářů, ne však jejich provedení. To je velice důležitý bod, který je někdy vývojářskými firmami úplně vynecháván.
28
Kapitola
Analýza požadavků 3.1
Případy užití
Hlavními profily aplikace jsou sportovec a trenér. Zde je potřeba zdůraznit, že se jedná opravdu o profily a ne o typy osob, jelikož jedna osoba může být zároveň jak trenérem, tak sportovcem.
3.1.1
Sportovec
Sportovec je nejdůležitějším profilem vůbec, protože pro osoby-sportovce aplikace vlastně vzniká. Sportovec má možnost nechat si dodat aktuální trénink, který má cvičit. Aby to bylo možné, je nutné vygenerovat cvičební plán (popis cvičebního plánu a dalších použitých pojmů lze najít v sekci 3.2). Avšak k tomuto cvičebnímu plánu dle zásad CrossFitu nemá sportovec přístup. Přístup má pouze k tréninku, který je pro něj aktuální. Jako samozřejmost je bráno, že sportovec může zadávat výkony v trénincích, které odcvičil. Pokud sportovec zadává své výkony, má možnost své výsledky vidět a porovnávat. Jak už bylo hodněkrát řečeno, CrossFit obsahuje veliké množství cviků z různých odvětví sportu. Často se stává, že dané cviky či konkrétní provedení není sportovec schopný provést. Důvodů může být mnoho, těmi nejdůležitějšími však bývají fyzická zdatnost a nedostatek prostředků 2 . Z toho důvodu aplikace umožňuje sportovcům kompletně vybrat, jaké cviky a popřípadě jejich provedení se mají zahrnout do generování cvičebních plánů. Nezřídka se vyskytuje situace, kdy se skupina sportovců domluví na společném tréninku. Tudíž ke zlepšení použitelnosti nabízí aplikace mož2
Příkladem mohou být cviky prováděné na hrazdě - ne každý sportovec má k dispozici hrazdu.
29
3
3. Analýza požadavků
Obrázek 3.1: Případy užití
30
3.2. Popis domény nost synchronizace cvičebních plánů domluvených sportovců pro následující trénink. V praxi to znamená, že pokud se skupina sportovců shodne na společném následujícím tréninku, úkolem aplikace je upravit cvičební plány zúčastněních tak, aby následující trénink měli všichni sportovci stejný.
3.1.2
Trenér
Každý trenér má své svěřence (sportovce), které má „na starost“. Jeho úkolem a pravomocí v aplikaci je sledování vygenerovaných cvičebních plánů svých svěřenců, popřípadě jejich upravování, je-li to potřeba. Své svěřence si trenér může přidávat a třídit do různých skupin. V reálném použití aplikace bude nejčastěji docházet k třídění sportovců podle doby, kdy docházejí na tréninky (např. pondělí 14:30).
3.2
Popis domény
Hlavní doménové pojmy aplikace vycházejí ze základních případů užití. Aplikace by měla být převážně používána CrossFit sportovci pro vygenerování cvičebních plánů, zaznamenání a následné pozorování výsledků cvičení. Pokročilejší funkcí je možnost synchronizace cvičebních plánů pro více sportovců. Výsledný doménový diagram je možné nalézt na přiloženém CD. Cvik Cvik je základní abstrakcí aplikace. Každý cvik může mít jedno či více různých provedení. Praktickou ukázkou cviku může být například klik. Provedení Provedení se vztahuje vždy ke konkrétnímu cviku a je psáno ve tvaru: „A x B“, kde A je počet sérií daného provedení a B upřesňuje daný cvik. Jednoduchý příklad provedení: Cvik - klik, provedení 3 x 20, což pro sportovce znamená vykonání 3krát 20 kliků. Z důvodu velké univerzálnosti CrossFitu je důležité myslet na fakt, že číslo B může mít u sebe jednotku (čas, váha, vzdálenost, atd.). V praxi to lze vidět například na cviku běh, který může mít provedení 1 x 10km. Význnam tohoto zápisu je zřejmý. Trénink Trénink je posloupnost jednoho či více provedení. Tento pojem reprezentuje ta provedení, která budou sportovci nabídnuta jako konkrétní činnost pro daný den. Každý trénink má určený typ. Typ tréninku Aplikace umožňuje přiřadit tréninku právě jeden typ. Pro každý typ tréninku je vytvořena tzv. posloupnost tréninků, která určuje část cvičebního plánu. Základní typy tréninku jsou: 31
3. Analýza požadavků • Power - síla • Stamina - vytrvalost • Metcon - předem určené tréninky CrossFitu Posloupnost tréninků Posloupnost tréninků si lze představit jako řadu tréninků seřazených podle toho, jak budou v čase nabízeny sportovci na cvičení. Aplikace generuje pro každého sportovce právě tři posloupnosti tréninků (power, stamina, metcon). Cvičební plán Cvičební plán je přiřazen konkrétnímu sportovci a obsahuje pro každý typ tréninku jeho posloupnost, tudíž tři celkově. Nastavení cvičení Každý sportovec má možnost detailně nastavit, jaké cviky či konkrétně jaká provedení chce mít do vygenerovaného cvičebního plánu zahrnuty. Dále je pro každý typ tréninku možné nastavit, kolik provedení bude každý trénink obsahovat. Nemusí jít vždy o konkrétní číslo, může jít i o rozmezí, z kterého aplikace číslo při generování tréninku náhodně vybere. Skupina sportovců Skupina sportovců umožňuje třídit trenérům své svěřence do různých skupin. Tím je docíleno větší přehlednosti pro větší počet svěřenců. Přátelství Uživatelé mezi sebou mohou uzavřít tzv. přátelství. Přátelství je uzavřeno vždy právě mezi dvěma uživateli, přičemž kterýkoli z nich má právo z něho odstoupit. Důvodem zavedení přátelství je především možnost synchronizace, u které by bylo nemístné, aby ji mohl založit kdokoli bez povolení druhého.
3.3
Generování cvičebních plánů
Generování cvičebního plánu spočívá ve vytvoření tří náhodných posloupností tréninků, jelikož v systému existují tři druhy tréninku (power, stamina, metcon). Generování posloupností typu power a stamina jsou řešena stejně. Posloupnost typu metcon musí být vyřešena samostatně. Jaká konkrétní provedení typu power a stamina a jaké konkrétní tréninky typu metcon budou do generování zahrnuty si může každý sportovec samostatně nastavit. 32
3.3. Generování cvičebních plánů Následující text již nezmiňuje, že je potřeba pracovat jen s množinou vybraných provedení a tréninků z nastavení, ale bere tento fakt za samozřejmost.
3.3.1
Posloupnosti power a stamina
Ke generování posloupnosti power nebo stamina je zapotřebí přistupovat postupně. Celá posloupnost se skládá z tréninků, přičemž tyto tréninky se skládají z provedení daného typu. Jelikož konkrétní tréninky typu power nebo stamina nejsou předem dané, musejí se vždy pro konkrétní posloupnost náhodně vygenerovat. Způsob generování konkrétního tréninku je popsán v sekci 3.3.1.1. 3.3.1.1
Generování konkrétního tréninku
K vygenerování konkrétního tréninku typu power nebo stamina je nutné znát, kolik provedení má každý trénink obsahovat. Tuto skutečnost může každý sportovec samostatně zvolit ve svém nastavení. Lze zvolit buďto konkrétní počet provedení nebo interval, ve kterém se má počet provedení pohybovat. Je-li zvolen interval, počet provedení je z daného intervalu náhodně vybrán. Po vybrání počtu provedení logicky následuje vybrání oněch provedení. Ta jsou vybrána náhodně, ale pravděpodobnost zvolení konkrétního provedení nemusí být pro všechna provedení stejná. Jednotlivé pravděpodobnosti jsou rozděleny dle následujících pravidel: • Jedná-li se o první generovaný trénink, jsou všechna provedení stejně pravděpodobná. • Čím blíže v historii byl cvik daného provedení zvolen, tím má menší pravděpodobnost. Hlavním kamenem úrazu se může zdát případ, kdy jsou v rámci jednoho tréninku vygenerována provedení od rozdílných cviků, například od cviků: klik, plavání, běh. Zdá se nepřívětivé sportovci takový trénink navrhnout, ale ve skutečnosti tomu tak není. Právě nesourodost tréninků dělá CrossFit CrossFitem a sportovci by měli být schopni situace tohoto typu zvládnout.
3.3.2
Posloupnost metcon
Hlavní rozdíl v generování posloupnosti tréninků typu metcon oproti ostatním je, že není třeba samostatně generovat jednotlivé tréninky. Metcon 33
3. Analýza požadavků tréninky jsou přesně dané a není možné v nich jednotlivá provedení upravovat či zaměňovat za jiná. Tím se problém generování redukuje pouze na vygenerování náhodné posloupnosti. I přes fakt, že posloupnost má bý náhodná, nesmějí mít všechny tréninky stejnou pravděpodobnost zvolení (s výjimkou prvního generování posloupnosti). Tato pravděpodobnost je dána minulými vygenerovanými posloupnostmi a mění se s každým nově přidaným tréninkem. Pravděpodobnost přidání daného tréninku do aktuálně vytvářené posloupnosti se řídí následujícími pravidly: • Pokud je daná posloupnost generována poprvé, mají všechny tréninky stejnou pravděpodobnost zvolení. • Čím blíže v historii byl trénink zvolen, tím je pravděpodobnost jeho zvolení menší.
3.4
Synchronizace cvičebních plánů
Dle zadání zákazníka je možné, že se spolu sportovci domluví na společném cvičení. Úkolem aplikace je v tomto případě upravit cvičební plány (respektive zvolené posloupnosti tréninků) sportovců takovým způsobem, aby na začátku fronty všech synchronizovaných posloupností byl nejvíce podobný trénink nebo v nejlepším případě trénink úplně stejný.
3.4.1
Synchronizace posloupností power a stamina
Pro pochopení problému synchronizace posloupností power a stamina je zapotřebí definovat následující pojmy3 : Definice 1 (Podobnost provedení) Mějme provedení P1 od cviku C1 a provedení P2 od cviku C2 , pak podobnost provedení p(P1 , P2 ) je funkce vracející číslo n ∈ {0, 1, 2} dle následujícího klíče:
p(P1 , P2 ) =
2 pokud P1 = P2 V 1 pokud P1 6= P2 C1 = C2 0 jinak
(3.1)
Definice 2 (Graf podobnosti) Mějme tréninky T1 , T2 , . . . , Tn pro n ≥ 2. Dále nechť každé provedení P ∈ Ti pro i = 1, 2, . . . , n reprezentuje právě 3
34
Grafové pojmy vycházejí ze skript Teoretická informatika ([8]).
3.4. Synchronizace cvičebních plánů jeden uzel u ∈ Ui obyčejného orientovaného grafu, ve kterém pro každou hranu h platí: • ρ(h) = [u, v], u ∈ Ui
V
v ∈ Ui+1
• w(h) = p(Pu , Pv )2 , kde Pu resp. Pv je provedení reprezentované uzlem u resp. v Pak takovýto graf je grafem podobnosti. Ukázku grafu podobnosti lze vidět na obrázku 3.2.
T1
T2
Tn
...
Obrázek 3.2: Graf podobnosti
Definice 3 (Úplný graf podobnosti) Úplným grafem podobnosti je graf podobnosti, který obsahuje všechny hrany, které lze vygenerovat na základě daných pravidel grafu podobnosti. Definice 4 (Ideální graf podobnosti) Ideální graf podobnosti je takový graf podobnosti, který vznikl odebráním hran z úplného grafu podobnosti tak, aby zároveň platilo: • Každý uzel je počátečním uzlem maximálně jedné hrany. • Každý uzel je koncovým uzlem maximálně jedné hrany. 35
3. Analýza požadavků • Neexistuje jiný podgraf úplného grafu podobnosti, který by měl větší součet ohodnocení všech hran a zároveň splňoval dvě pravidla uvedená výše. Definice 5 (Podobnost tréninků) Nechť G = hH, U, ρi je ideálním grafem podobnosti, který vznikl z tréninků T1 , T2 , . . . , Tn pro n ≥ 2. Dále nechť každé Ui ⊂ U pro i ∈ 1, 2, ..., n je podmnožina uzlů reprezentující provedení tréninku Ti . Pak podobnost tréninků T1 , T2 , . . . , Tn je reálné číslo Pt získané vzorcem: P|H|
Pt = 3.4.1.1
w(hk ) 4max(|U1 |, |U2 |, ..., |Un |)(n − 1) k=1
Problém synchronizace posloupností
Jak už bylo řečeno dříve, synchronizace posloupností typu power nebo stamina obnáší upravení posloupností takovým způsobem, aby na prvním místě byly co nejpodobnější tréninky. Pro K posloupností to znamená nalézt K tréninků (z každé posloupnosti jeden) tak, aby neexistovala jiná K − tice tréninků, v které by si byly tréninky na základě definice podobnosti tréninků podobnější. Pseudoalgoritmus 3.1 ukazuje, jak tuto K − tici získat, přičemž po doběhnutí algoritmu je výsledná K−tice reprezentována tréninky T 1, T 2, ..., T k. Čtenáři se omlouvám za nepěkné „tečky“ v algoritmu, které mají pouze naznačit postupné zanořování jednotlivých foreach cyklů. Je zřejmé, že pro reálnou implementaci bude zapotřebí využít rekurze, bohužel její rozepsání do textu je přibližně dvakrát tak obsáhlé. Doufám tedy, že algoritmus 3.1 je pro názornou představu k do sebe vnořených foreach cyklů dostačující. 3.4.1.2
Problém výpočtu podobnosti tréninků
Výpočet podobnosti tréninků je problémem sám o sobě, neboť z definice 5 je zřejmé, že k výpočtu podobnosti tréninků je potřeba znát ideální graf podobnosti. Ten ale v době výpočtu znám není a právě jeho hledání je onen problém. Jako řešení se nabízí postupné hledání nejdelších cest z uzlů u ∈ U1 do uzlů v ∈ Un (za použití pojmů a proměnných z definice 2). V každém kroku vybereme nejdelší cestu a odebereme uzly, které jsou její součástí. Z grafu jsou samozřejmě odebrány i všechny hrany, jejichž počátečním nebo koncovým uzlem byl jeden z odebraných uzlů. Kompletní postup je vidět na pseudoalgoritmu 3.2. 36
3.4. Synchronizace cvičebních plánů
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
k = pocetPosloupnostiSynchronizace ; ptMax = -1; Trenink T1 , T2 ,... , Tk = NULL ; foreach ( Trenink t_1 in Posloupnost1 ) { foreach ( Trenink t_2 in Posloupnost2 ) { . . . foreach ( Trenink t_k in Posloupnost_k ) { pt = po dobnos tTren inku ( t_1 , t_2 , ... , t_k ) ; if ( pt > ptMax ) { ptMax = pt ; T1 = t_1 ; T2 = t_2 ; . . . Tk = t_k ; } } . . . } }
Listing 3.1: Hledání nejpodobnějších tréninků
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Graf G_idealni = initGraf () ; Graf G_uplny = uplnyGraf ( T1 , T2 ,... , Tn ) ; while ( existuje cesta z U1 do Un ) { nejdelsiCesty = nejdelsi cesty z U1 do Un ; cesta = nejdelsiZeVsech ( nejdelsiCesty ) ; // prida vsechny uzly a hrany cesty G_idealni . pridejCestu ( cesta ) ;
// zaroven odebere vsechny hrany souvisejici // s odebiranymi uzly G_uplny . odeberUzly ( cesta . uzly ) ; }
Listing 3.2: Idealizace úplného grafu podobnosti
37
3. Analýza požadavků
3.4.2
Synchronizace metcon posloupností
V případě posloupností typu metcon je synchronizace velice snadná. Nezajímají nás jednotlivá provedení, nýbrž tréninky jako celek. Zjednodušeně řečeno musíme pouze najít stejné tréninky ve všech posloupnostech. Abychom se vyhnuli procházení všech možností, je vybrán první stejný trénink. Kompletními pravidly k výběru tréninků pro synchronizaci jsou: • Pokud jsou v čele posloupnosti stejné tréninky, je synchronizace hotova. • Pokud mají posloupnosti více stejných tréninků, pak je z nich jeden náhodně vybrán podle pravidel generování metcon posloupností (viz. 3.3.2). • Synchronizace se neprovádí, nemají-li posloupnosti žádný společný trénink.
38
Kapitola
Návrh a realizace 4.1
Technologie
4.1.1
Spring MVC
Spring MVC ([4], [9]) je jeden z mnoha javovských frameworků pro tvorbu webových stránek. Jelikož jde o součást opensource nástroje Spring, je i pro Spring MVC opensource samozřejmostí. Jeho základní funkcionalitu lze vidět na obrázku 4.1. Framework nejdříve přijme požadavek skrze tzv. FrontController. Tento controller pouze předá požadavek controlleru, který je schopen daný požadavek vyřídit. Typicky jde o třídu s anotací @Controller napsanou programátorem webu. Controller po zpracování požadavku vrátí FrontControlleru model (data) a informaci, jaké view má daný model zobrazit. V poslední fázi FrontController zavolá view, které zobrazí model a předá kontrolu opět FrontControlleru, který vrátí odpověď. Je možné, že pojem view se může zdát někomu zavádějící, jelikož Spring MVC žádné své vlastní view neimplementuje. Ve skutečnosti je na programátorovi, jaké view si zvolí. Může jít například o jednoduché JSP stránky nebo o nějaké šablony typu Velocity a FreeMarker. Pro většinu možných view Spring MVC implementuje různá zjednodušení. Příkladem je speciální knihovna tagů pro JSP či speciální makra pro Velocity. Výběr tohoto frameworku neprošel z mé strany žádnou analýzou, jelikož používání právě Springu MCV je součástí obsahu zadání mé bakalářské práce. Jako view bylo zvoleno Velocity a až na drobné problémy se ukázalo být dobrou volbou. 39
4
4. Návrh a realizace
Obrázek 4.1: Základní struktura Spring MVC ([4])
4.1.2
Spring Security
Jak je ze samotného názvu patrné, Spring Security ([10]) je frameworkem zabývajícím se bezpečností, konkrétně zabezpečením webových aplikací pomocí autentizace a autorizace. Tak jako u všech springovských aplikací, je i zde zapotřebí základní konfigurační soubor psaný v XML. V tomto souboru se definuje athenticationmanager, který zajišťuje celý mechanismus autentizace. Je možné definovat uživatele přímo v konfiguračním XML souboru, ale častějším případem z praxe je vlastní implementace autentizace pomocí databáze. Další velmi důležitou součástí konfiguračního souboru jsou definice chování při přístupu na jednotlivé URL. Přístup je možné definovat následujícím způsobem: • permitAll - přístup povolen všem • fullyAuthenticated - je nutné přihlášení • denyAll - přístup odepřen všem • výčet rolí s povoleným přístupem 40
4.1. Technologie 1 < security : http use - expressions = " true " > 2 < security : intercept - url pattern = " / login * " access = " permitAll " / > 3 4 < security : intercept - url pattern = " / user /** " 5 access = " hasAnyRole ( ’ ROLE_ATHLETE ’,’ ROLE_COACH ’) " / > 6 7 < security : intercept - url pattern = " /** " access = " denyAll " / > 8
Listing 4.1: Ukázka autorizace v Spring Security
Autorizace je řešena pomocí výše zmíněných rolí a definic chování při přístupu k jednotlivým URL. Názvy rolí nejsou nijak specifikovány, ale je zvykem používat prefixu ROLE. Ukázka 4.1 znázorňuje, jak by mohlo vypadat jednoduché definování přístupu v Spring Security. Spring Security framework byl zvolen už jen na základě skutečnosti, že webové aplikace jsou psány za pomocí Spring MVC. I převážná většina literatury o Spring MVC zároveň referuje Spring Security jako vhodné řešení bezpečnosti. Důvodem je samozřejmě fakt, že jde v obou případech o Spring, však po bližším prozkoumání Spring Security jsem došel k závěru, že jde o komplexní nástroj obsahující vše potřebné a z toho důvodu nebylo ani nutné hledat dál.
4.1.3
Hibernate
Hibernate ([3]) je opensource nástroj od firmy JBoss, který implementuje standard JPA (Java Persistence API - [11]). JPA standardizuje tzv. objectrelational mapping (ORM). Hlavní myšlenkou JPA a celého ORM je zjednodušení práce s relační databází tím, že se jednotlivé tabulky namapují na objekty a je možno s nimi pracovat bez použití SQL. Hlavní využití Hibernate v aplikaci je pro snadnou správu DAO objektů pomocí entity manageru. Dotazování se nad databází je v největší míře realizováno pomocí Criteria API namísto Java Persistance query language. Často jsem se setkával s kritikou, proč používám právě Criteria API, když to samé lze napsat pomocí Java Persistance query language na jednu řádku. Já však zastávám názor, že psaní dotazů pomocí Criterií je více čitelné. Navíc dotazování pomocí Criteria API je převážně prováděno pomocí objektů, čímž se minimalizuje možnost napsání chyby v obyčejném stringu. 41
4. Návrh a realizace
4.1.4
RESTEasy
RESTEasy ([12]) je další opensource framework od firmy JBoss. Implementuje standard JAX-RS pro restové služby. Díky JAX-RS standardu je v javě velice jednoduché dosáhnout restové komunikace pouze pomocí pár anotací. Mezi nejdůležitější anotace patří:
@GET, @POST, @PUT, @DELETE Anotace reprezentující jednotlivé HTTP požadavky.
@Path Reprezentuje relativní cestu, pod kterou je daný požadavek dostupný.
@PathParam Reprezentuje parameter uvedený v @Path.
@Consumes/@Produces Udává, jaký typ obsahu služba očekává/produkuje.
Nejlépe osvědčený způsob práce s RESTEasy je vytvořit množinu rozhraní, která reprezentují naši webovou službu, tato rozhraní opatřit pomocí JAX-RS anotací a až poté jednotlivá rozhraní implementovat na serveru. RESTEasy kromě serverové části nabízí i přívětivý způsob práce s jednotlivými rozhraními na straně klienta. Framework pomocí ProxyFactory vytvoří implementaci konkrétního rozhraní, která zaštiťuje síťovou komunikaci a volá konkrétní službu. Pak je jedinou prací programátora používat jednotlivé metody rozhraní. Právě tato klientská část je důvodem, proč se doporučuje restová rozhraní napsat zcela odděleně (např. samostatný Maven projekt) od serveru i od klienta. To samé rozhraní je totiž možné využít jak na serverové, tak na klientské straně. Volba RESTEasy frameworku byla provedena na základě doporučení a prostudování knihy RESTful Java with JAX-RS ([14]). Vyšlo najevo, že tento framework má slušně implementovánu i klientskou část, což jsem bral za rozhodující fakt. Z mé strany šlo o úplně první implementaci restové služby, tudíž jsem nemohl reálně posoudit, který framework je nejvhodnější. Toto posouzení by bylo možné jen po vyzkoušení všech frameworků, což ale není předmětem této práce. 42
4.1. Technologie
4.1.5
Maven
Maven ([18]) je prostředek pro správu projektů a v dnešní době nahrazuje starší buildovací systém Ant. Alfou a omegou Maven projektu je tzv. POM (Project Object Model), což je XML soubor popisující daný projekt. Každý POM musí minimálně obsahovat: • kořenový element <project> • modelVersion, nebo-li verzi POMu • koordináty Mezi koordináty patří groupId, artifactId, version a package, přičemž dohromady jednoznačně určují identitu projektu v rámci úložiště. Velká výhoda Mavenu je v možnosti přidání závislostí na jednotlivé projekty. Jednak můžeme docílit srozumitelnějšího dělení kódu tím, že ho rozdělíme do více projektů, druhak je možné přidávat závislosti i na externí knihovny (napsané jako Maven projekty) aniž by programátor musel sám chtěné JAR soubory stahovat a přidávat do build path. Maven se o vše po zadání závislosti postará sám. Maven jako buildovací systém byl zvolen na základě dřívější zkušenosti, nehledě na fakt, že je to dle mého názoru v dnešní době jeden z nejpoužívanějších systémů pro správu projektů. Díky tomu je možné přidávat externí knihovny pouze pomocí závislostí, které automaticky zařídí, aby knihovny byly staženy a přidány k aplikaci.
4.1.6
JGraphT
JGraphT ([2]) je opensource knihovna napsaná v jazyce Java, kterou je možné použít pro zjednodušení práce s grafy. Knihovna obsahuje implementace základních neorientovaných i orientovaných grafů. Samozřejmostí jsou rozhraní a základní implementace objektů reprezentující uzly a hrany. Hlavním pozitivem této knihovny je, že dává k dispozici vlastní implementace grafových algoritmů, jakými jsou například hledání nejkratších cest, minimální kostry apod. JGraphT knihovna byla vybráno na základě potřeb vycházejících z analýzy. Je zapotřebí pracovat s grafy při synchronizaci cvičebních plánů a JGraphT v tomto ohledu ušetří mnoho práce. Zejména je možné odložit vlastní implementaci hledání nejkratších cest a místo toho použít Dijkstrova algoritmu z této knihovny. 43
4. Návrh a realizace
Server
REST
?
?Klient Android?
Klient web
?Klient iOS?
?
Obrázek 4.2: Klient-server demonstrace
4.2
Architektura
Po konzultacích se zákazníkem vyšlo jasně najevo, že je nutné celou aplikaci rozdělit na klientskou a serverovou část. Hlavním důvodem je zákazníkův budoucí záměr rošířit své působení (kromě webové aplikace) a nabízet své služby i pro Android a iOS. Je zřejmé, že právě architektura klient-server umožní tyto záměry vyplnit s co možná nejmenší námahou a úsilím.
4.2.1
Server
Jak už to tak bývá u klient-server aplikací, je to právě server, který poskytuje všechny důležité informace. Ani tato aplikace není výjimkou. Veškeré důležité požadavky a funkce jsou klientovi nabízeny pomocí jednoduchého restového rozhraní. Samotný server má pro celou aplikaci dvojí význam. Za prvé, poskytuje restové rozhraní pro všechny důležité funkce a je na něm uložena veškerá bussines logika - mezi tyto funkce patří především generování a synchronizace cvičebních plánů, poskytování dat o uživatelích atd. 44
4.2. Architektura Druhým významem je administrace databáze. Databázi lze spravovat pomocí jednoduchého webového rozhraní. Jde především o možnoti administrátora spravovat nabízené cviky, provedení, tréninky a předdefinovaná nastavení cvičení.
4.2.2
Klient
Na první pohled se po spuštění aplikace může zdát, že právě klientská část je ta, která poskytuje veškerou funkcionalitu, ale není tomu tak. Ve skutečnosti se klient pouze dotazuje na data serveru, která chce uživatel vidět a poté je zobrazí. Dotazy na server jsou realizovány pomocí restového rozhraní nabízeného serverem.
4.2.3
Maven projekty aplikace
Aplikace je rozdělena celkem do následujících sedmi projektů: crossfit-model-jpa Model obsahuje objekty reprezentující doménové pojmy, které je zároveň potřeba ukládat do databáze. crossfit-dao Crossfit-dao je projekt obsahující rozhraní pro práci s databází. crossfit-hibernate-dao-impl Tento projekt implementuje rozhraní z crossfitdao za pomoci frameworku Hibernate. crossfit-rest Crossfit-rest obsahuje rozhraní opatřená anotacemi JAXRS. Díky frameworku RESTEasy je možné tato rozhraní využívat pro komunikaci mezi klientem a serverem. crossfit-tvorba-treninku Jak samotný název napovídá, tento projekt obsahuje logiku generování a synchronizace tréninků. CrossfitAppServer Tento projekt zaštiťuje webovou aplikaci pro administraci databáze a servervou implementaci restového rozhraní pomocí RESTEasy frameworku. WebClient WebClient je projektem pro samotnou webovou aplikaci, která bude přístupná uživatelům. Pro komunikaci se serverem využívá framework RESTEasy a rozhraní z projektu crossfit-rest. 45
4. Návrh a realizace Jednotlivé závislosti mezi projekty lze nalézt na přiloženém CD.
4.3
Generování cvičebních plánů
Generování cvičebního plánu sportovce je od daného sportovce úplně odstíněno. Sportovec si pouze volí, jakého typu by měl být jeho následující trénink, ale neví, zda je potřeba jeho plán teprve vygenerovat či už je dávno vygenerovaný. Jediné, co ho zajímá, je následující trénink a ten také dostane. Ve skutečnosti aplikace funguje následovně. Pokud sportovec požádá o další trénink daného typu, snaží se mu za každou cenu vyhovět. V případě, že je posloupnost žádaného typu prázdná, je na serveru vygenerována nová. Z této nové posloupnosti je pak sportovci vrácen jako další trénink první trénink nové posloupnosti.
4.3.1
Rozdělení pravděpodobností a výběr pohybu
V případě generování posloupností typu power či stamina je třeba rozdělit pravděpodobnosti mezi provedení, která se postupně generují do jednotlivých tréninků. Generování posloupností typu metcon potřebuje zase rozdělit pravděpodobnosti zvolení jednotlivých metcon tréninků. Obě rozdělení jsou velice podobná (viz. 3.3) a lze je zobecnit do rozdělení pravděpodobností zvolení jednotlivých pohybů. Mějme seřazenou kolekci pohybů P0 , P1 , ..., Pn−1 podle času, kdy byl daný pohyb naposledy použit, kde n je počet prvků kolekce, přičemž P0 je pohyb použitý nejblíže v historii a pohyb Pn−1 použitý v historii nejdále. Dále si každý pohyb u sebe drží hodnoty: intervalStart, intervalEnd, které reprezentují počátek a konec uzavřeného intervalu celých čísel. Následující algoritmus přiřadí každému pohybu Pi takový uzavřený interval, aby při zvolení náhodného čísla x ∈ hP0 .intervalStart, Pn−1 .intervalEndi byla pravděpodobnost, že x ∈ hPi .intervalStart, Pi .intervalEndi, v souladu s pravidly uvedenými v sekci 3.3. Vybrat náhodně pohyb již není nic těžkého. Stačí zvolit náhodné číslo x ∈ hP0 .intervalStart, Pn−1 .intervalEndi a poté vybrat právě ten pohyb Pi , pro který platí x ∈ hPi .intervalStart, Pi .intervalEndi. 46
4.4. Synchronizace cvičebních plánů 1 2 3 4 5 6 7 8 9 10 11 12
vel ikostI nterva lu = 1; lastIntervalEnd = -1; for ( i = 0 to n -1) { P_i . intervalStart = lastIntervalEnd +1; P_i . intervalEnd = P_i . intervalStart + velik ostIn terval u ; lastIntervalEnd = P_i . intervalEnd ; if ( P_i a P_ { i +1} nemaji stejny cas posledniho pouziti ) { vel ikostI nterva lu = 2* ve likost Interv alu ; } }
Listing 4.2: Výběr provedení s určitou pravděpodobností
4.4 4.4.1
Synchronizace cvičebních plánů Dijkstrův algoritmus
Dijkstrův algoritmus, popsaný nizozemským informatikem Edsgerem Dijkstrou, je algoritmus pro nalezení nejkratší cesty v grafu G = hU, H, ρi z uzlu s ∈ U do všech uzlů grafu. Po bližším prozkoumání lze říci, že jde vlastně o určitou formu prohledávání grafu do šířky, jelikož jde o postupné přidávání objevených uzlů z uzlu počátečního do prioritní fronty. Při použití Dijkstrova algoritmu je nesmíme zapomenout na skutečnost, že Dijkstra předpokládá pouze kladné ohodnocení hran. Samotný algoritmus lze vidět na obrázku 4.3. K popisu algoritmu bylo převážně použito skript Teoretická Informatika ([8]). Algoritmus využívá známých ohodnocení hran grafu G = hU, H, ρi pomocí funkce w(u, v), kde u, v ∈ U . Dále je pro každý uzel ukládána hodnota (d[u]) doposud nejkratší cesty z počátečního uzlu s a jeho předek (p[u]) na této cestě. Výsledná nejkratší cesta je poté reprezentována postupným procházením předků, dokud nenarazíme na uzel počáteční. Prvním krokem algoritmu je inicializovat cesty grafu jednoduchým prohlášením, že každý uzel grafu je nekonečně vzdálen od uzlu počátečního a vzdálenost počátečního uzlu od sebe samého je 0. Poté je každý uzel grafu vložen do prioritní fronty, ze které jsou uzly postupně vybírány a jsou s nimi prováděny následující operace. Pro každého souseda v uzlu u z prioritní fronty je provedena tzv. relaxace hrany [u, v]. Relaxace hrany není nic jiného než otestování, zda právě procházená cesta není kratší než poslední uložená. Pokud kratší je, tak se uloží její hodnota d[u] a nový předek p[u]. Obrázek 4.3 relaxaci názorně 47
4. Návrh a realizace
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
init_paths (G ,s , w ) { for ( každý uzel u z U ) { d [ u ] = nekonečno ; p [ u ] = NULL ; } d [ s ] = 0; } relax (u ,v , w ) { if ( d [ v ] > d [ u ] + w (u , v ) ) { d [ v ] = d [ u ] + w (u , v ) ; p[v] = u } } dijkstra (G ,s , w ) { init_paths (G , s ) ; S = prázdná množina ; init_queue ( Q ) ; for ( každý uzel u z U ) { enqueue (Q , u ) ; } while (! isEmpty ( Q ) ) { u = extract_min ( Q ) ; S = S ~ sjednoceno s ~{ u }; for ( každý uzel v prvkem Adj [ u ]) { relax (u ,v , w ) ; } } }
Listing 4.3: Dijkstrův algoritmus ([8])
48
4.4. Synchronizace cvičebních plánů
u 3
v 5
6
relax(u,v,w) u 3
v 5
u 3
6
v 2
6
relax(u,v,w) u 3
v 2
5
Obrázek 4.3: Relaxace hrany
demonstruje, přičemž do hodnot v uzlech jsou vepsány právě hodnoty d[u].
4.4.2
Řešení problému synchronizace
Jak již bylo řečeno v sekci 3.4, hlavním problémem synchronizace je hledání nejpodobnějších tréninků z různých posloupností tak, aby mohly být dány na počátek posloupnosti. Pro výpočet podobnosti tréninků je potřeba znát ideální graf podobnosti, který vznikl z grafu úplného4 . V algoritmu 3.2 je zmíněno, že k získání ideálního grafu je zapotřebí hledání nejdelších cest mezi uzly a k tomuto výpočtu nejlépe poslouží právě výše zmíněný Dijkstrův algoritmus. Nicméně, jelikož Dijkstrův algoritmus hledá cesty nejkratší a ne nejdelší, musíme problém trochu poupravit. První možná úprava je doslova zaměnit znaky „<“ a „>“, což by ale vyžadovalo implementaci celého algoritmu a to je zbytečná práce navíc vzhledem k možnosti použití knihovny jGraphT(4.1.6). Nezbývá tedy než použít druhé možnosti, kterou je přehodnocení hran grafu. 4
Definice jednotlivých grafů lze najít v sekci 3.4
49
4. Návrh a realizace Přehodnotit hrany není žádný problém, neboť dle definice 2 jsou hrany grafu ohodnoceny druhou mocninou podobností provedení. Podobnost provedení nabývá pouze hodnot z množiny {0, 1, 2}, a tudíž ohodnocení hrany může být pouze z množiny {0, 1, 4}. Je zřejmé, že stačí hrany přehodnotit podle následujícího klíče:
0 pokud w(h) = 4 w (h) = 3 pokud w(h) = 1 4 pokud w(h) = 0 0
(4.1)
Nyní už je možné použít Dijkstrova algoritmu a po jeho dokončení pouze přehodnotit hrany zpět podle stejného klíče. Z výše uvedených algoritmů (3.1, 3.2) je zřejmé, že složitost výpočtu bude velice vysoká. Obecně je potřeba spočítat T −krát podobnost tréninků, Q|P osl| kde T = i=1 |T P osli |, |P osl| je počet posloupností a |T P osli | je počet tréninků v i-té posloupnosti. Za předpokladu, že posloupnosti vstupující do synchronizace budou mít v průměru 15 tréninků, je složitost synchronizace O(15|P osl| )O(vypocetP odobnostiT reninku). Složitost výpočtu podobnosti tréninků je závislá na počtu provedení v každém tréninku, který do výpočtu vstupuje. Nejvíce pozornosti si zaslouží složitost idealizace úplného grafu podobnosti (viz. algoritmus 3.2). Celý while cyklus proběhne celkem C − krát, pro C = min(|U1 |, ..., |Un |), jelikož právě tolik cest je potřeba celkem objevit. V každém průběhu cyklem se musí objevit nejkratší cesty (po přehodnocení hran) z uzlů s ∈ U1 do uzlů v ∈ Un k čemuž slouží Dijkstrův algoritmus. Dijkstrův algoritmus má složitost O(|U |2 ) a provádí se |U1 | − krát. Ze složitosti synchronizace je patrné, že pro větší množství synchronizovaných posloupností je potřebná heuristika. Ta však není součástí této práce, což má za následek, že pro účely ukázky synchronizace byl maximální počet synchronizovaných posloupností experimentálně určen na 4.
50
Kapitola
Analýza testovacích frameworků pro webové aplikace 5.1
Selenium
Selenium ([5], [16]) je sada open source nástrojů pro tvorbu automatizovaných testů. Tyto testy je pak možné spouštět v řadě prohlížečů. Selenium není framework, který by podporoval pouze Javu. Kromě Javy je možné psát v Seleniu testy také v jazycích C#, Perl, Ruby a Python.
5.1.1
Selenium IDE
Selenium IDE je plugin pro internetový prohlížeč Mozilla Firefox vytvořený pro snadné využití samotného jádra Selenia (tzv. Selenium Core). Hlavní výhodou IDE je možnost použít Selenium Core aniž by musel být nakopírován na serveru. Veškeré testy jsou rozčleněny pomocí tabulky do tří částí: • příkaz (Command) • cíl (Target) • hodnota (Value) Příkaz určuje, jaká akce bude provedena. Mezi takové akce patří např.: click, doubleClick, dragAndDrop, refresh, goBack a spousta dalších. Další důležité akce jsou akce typu assert a verify, které přináší velkou škálu možností k testování. Příkladem mohou být akce: assertElementPresent (verifyElementPresent) pro zjištění, zda je přítomný určitý element (tlačítko 51
5
5. Analýza testovacích frameworků pro webové aplikace atd.) nebo assertVisible (verifyVisible) pro zjištění, zda je určitý element viditelný. Rozdíl mezi assert a verify akcemi je pouze v chování při nesplnění dané aserce. Assert akce ukončí celý test, ale akce typu verify pouze označí chybu a nechají celý test proběhnout až do úplného konce. Cíl identifikuje element, pro který se má daná akce vykonat. Element je možné najít pomocí lokátorů jakými jsou id, name, link a další. Pomocí tlačítka Find je možné zkontrolovat, zda se element na stránce vyskytuje. Typickým příkladem pro využití hodnoty (Value) je akce type, kdy hodnotou je text, který bude automaticky napsán do elementu. Selenium IDE je vývojáři používáno především pro možnost jednoduchého nahrávání testů. Stačí pouze zvolit počáteční URL (tzv. Base URL), na které bude daný test začínat a poté stisknout tlačítko record. Po stisku tlačítka je možné v prohlížeči Mozilla Firefox doslova „naklikat“ celý průchod stránkou, kterou chceme testovat.
5.1.2
Selenium RC
Jelikož je Selenium IDE pouze pluginem pro internetový prohlížeč Firefox, je nadmíru jasné, že pro celkové testování webových aplikací je naprosto nedostačující. Nelze přepokládat, že lidé používají pouze jeden internetový prohlížeč a z toho důvodu programátoři a testeři potřebují testovat své aplikace alespoň na prohlížečích, které jsou používány nejčastěji. V tuto chvíli přichází na pomoc Selenium RC (Remote Control). Selenium Remote Control se skládá ze dvou hlavních částí: • Remote Control serveru • klientských knihoven Základní architekturu Selenia RC je možné vidět na obrázku 5.1. Obrázek ukazuje, že klientské knihovny komunikují s RC serverem tak, že mu předají Selenium příkaz ze Selenia Core pomocí http protokolu. Následně je RC server předá prohlížeči jako javascriptovou funkci a vrátí výsledek klientovi. Remote Control server slouží pro práci s danými prohlížeči. Je navržený jako proxy server mezi testovanou aplikací a testovacími scripty, čímž opět umožňuje používat Selenium Core bez nutnosti jeho instalace na server, na kterém je aplikace spuštěna. 5 5
V odstavci jsou zmíněny dva servery, jejichž významy jsou naprosto odlišné. Remote Control server je součástí Selenia RC. Druhým serverem je server, na kterém běží webová aplikace, kterou testujeme.
52
5.1. Selenium
Testovaná aplikace
RC server HTTP
Vlastní testy (klientské knihovny)
Obrázek 5.1: Základní architektura Selenia RC
Klientské knihovny poskytují možnost použít ve svých testech příkazy (commands) ze Selenia Core, přičemž každý programovací jazyk má svou klientskou knihovnu. Jelikož komunikace mezi klientem a RC serverem probíhá pouze na bázi jednoduchých http GET a POST požadavků, je možné testy napsat v jakémkoli programovacím jazyce.
5.1.3
Selenium Webdriver
Selenium Webdriver je víceméně následníkem Selenia RC. Hlavní změnou prošel způsob, jakým se nahlíželo na Remote Control server. Pokud jsou testy a webový prohlížeč spuštěny na stejném stroji, není již zapotřebí mít spuštěný i RC server. Dále Selenium Webdriver nepředává prohlížečům příkazy pomocí javascriptových funkcí, ale využívá vlastní podporu pro automatizaci u samotných prohlížečů pomocí prohlížečových driverů. Pozitivní stránkou věci je, že díky indivudálnímu přístupu mohou být drivery ušity takřka na míru prohlížečům. Na druhou stranu driver musí být napsán pro 53
5. Analýza testovacích frameworků pro webové aplikace každý prohlížeč, který by bylo zapotřebí použít, což může být zdrojem chyb.
5.1.4
Selenium Grid
Selenium Grid je pokročilý nástroj frameworku Selenium. Umožňuje spouštět testy paralelně ve více prohlížečích a na více strojích (virtuálních či fyzických). Nezbytnou součástí k použití Selenia Grid je RC server, který se spustí buďto v režimu „hub“, nebo v režimu „node“. Hub obdrží testy a informace o prohlížečích a platformách, na kterých mají být testy spuštěny. Dále hub uchovává informaci o všech svých registrovaných nodech. Pomocí informací zvolí nody s požadovanou kombinací prohlížeč-platforma. Node pak spustí prohlížeč s jednotlivými selenovskými příkazy.
5.2
Canoo WebTest
Canoo WebTest ([1]) je další open source nástroj zaměřený na automatizované testování webových aplikací. Svou funkcionalitu má založenou na javovském buildovacím systému Ant tím, že definuje speciální antovské tasky. Testy jsou tudíž psané pomocí XML (lze je však psát i pomocí Groovy), kde je možné tyto tasky využívat. K samotnému spuštění testů není zapotřebí žádného reálného prohlížeče, jelikož testy jsou simulovány na anonymním prohlížeči HtmlUnit (dříve HttpUnit). HtmlUnit je fiktivní prohlížeč bez uživatelského rozhraní pro javovské programy, který modeluje HTML a poskytuje API pro práci s webovými stránkami (klikání na tlačítka, vyplňování formulářů atp.).
5.2.1
Psaní testů pomocí Canoo WebTest
Psaní testů pomocí Canoo WebTest je velice snadné. Já osobně preferuji XML před Groovy, a tak pouze stačí osvojit si základní tasky, kterými mohou být například: •
vyvolání stránky pomocí URL •
kliknutí na tlačítko •
ověření textu • <setInputField/> vložení hodnoty do textfieldu • <setSelectedField/> vybrání možnosti ze selectboxu 54
5.3. Porovnání testovacích frameworků 1 2 3 4 5 < project default = " test " > 6 < import file = " ../ definitions . xml " / > 7 < target name = " test " depends = " wt . defineMacros " > 8 < webtest name = " Otestuj zda gmail . com odmitne pri prihlaseni neznama data . " > 9 < invoke url = " http :// www . gmail . com / " description = " Prejdi na stranku gmail . com " / > 10 < verifyTitle text = " Gmail : Email from Google " / > 11 < setInputField forLabel = " Username " value = " bla . bla " / > 12 < setInputField forLabel = " Password " value = " hesloBlablaHeslo " / > 13 < clickButton label = " Sign in " / > 14 < verifyText text = " The username or password you entered is incorrect . " / > 15 16 17
Listing 5.1: Ukázka psaní testů pomocí Canoo WebTest
Na 5.1 je možné vidět ukázku jednoduchého testu, který má za úkol zjistit, zda přihlášení ke službě Gmail bude neúspěšné po zadání nejspíše nesmyslných dat.
5.2.1.1
Testování PDF dokumentů
Jednou z příjemných vlastností pro programátory může být možnost testování PDF dokumentů referencovaných z webových stránek, zejména pak PDF dokumentů, které jsou dynamicky aplikací generovány. Canoo WebTest tuto možnost přináší v podobě podobné jako pro webové stránky. Je možné ověřovat text, nadpis, ale navíc i třeba počet stránek dokumentu či použitý font písma.
5.3
Porovnání testovacích frameworků
Po analýze jednotlivých framoworků pro testování webových aplikací přichází logicky na řadu jejich porovnání. Ze Selenium frameworku byl k bližšímu testování vybrán Selenium WebDriver na úkor Selenia RC, protože jde 55
5. Analýza testovacích frameworků pro webové aplikace o pokračování Selenia RC, a tudíž má větší budoucnost. Frameworky jsou hodnoceny dle následujících kritérií: • Rychlost provádění testů • Sumarizace testu • Možnost optimalizačních testů pro prohlížeče • Rychlost naučení se s frameworkem • Dokumentace Každému z frameworků je pak přiděleno 0 - 5 bodů, kde 0 znamená nevyhovující a 5 excelentní.
5.3.1
Rychlost provádění testů
Pro zjištění rychlosti jednotlivých frameworků jsem vytvořil dva jednoduché testovací scénáře, které zároveň testují i výslednou webovou aplikaci. Testovací scénář 1 - změna uživatelských údajů 1. Uživatel jde na počáteční URL aplikace a přihlásí se. 2. Uživatel klikne na odkaz User. 3. Uživatel klikne na odkaz Settings. 4. Uživatel změní své údaje. 5. Uživatel potvrdí formulář kliknutím na tlačítko Save. 6. Test zkontroluje, zda byly údaje změněny. 7. Test navrátí aplikaci do původního stavu před svým počátkem. Testovací scénář 2 - změna hesla 1. Uživatel jde na počáteční URL aplikace a přihlásí se. 2. Uživatel klikne na odkaz User. 3. Uživatel klikne na odkaz Change password. 4. Uživatel zadá nové heslo (i potrvrzení hesla) do formuláře. 56
5.3. Porovnání testovacích frameworků
Selenium WebDriver Canoo WebTest
Scénář 1 18-22s 6-7s
Scénář 2 19-20s 6-7s
Scénáře zároveň 25-26s 7-8s
Tabulka 5.1: Znázornění doby trvání jednotlivých testů dle scénářů ze sekce 5.3 5. Uživatel potvrdí změnu hesla kliknutím na tlačítko Change. 6. Uživatel se odhlásí a pokusí se přihlásit pomocí nového hesla. 7. Test zkontroluje, zda se přihlášení podařilo. 8. Test navrátí aplikaci do původního stavu před svým počátkem. Oba dva výše uvedené scénáře byly naimplementovány pomocí každého frameworku. Dále byl desetkrát zaznamenán čas provedení každého z nich zvlášť a obou současně. Čas je počítán od spuštění prvního testu do skončení testování, je v něm tedy započítána i doba inicializace, kterou daný framework potřebuje. Výsledek experimentu můžeme vidět v tabulce 5.1. Z tabulky 5.1 je zřejmé, že v testu rychlosti nekompromisně vítězí Canoo WebTest nad Seleniem 2 (WebDriver), jelikož je přibližně 2krát až 3krát rychlejší. Z tohoto důvodu si z tohoto testu zaslouží plných 5 bodů. Naopak Selenium díky o poznání horším výsledkům hodnotím 0 body.
5.3.2
Sumarizace testu
Kritérium, jakým způsobem je zobrazen výsledek testu, považuji za jedno z nejdůležitějších - zvláště pak sumarizaci testu, který neprošel. Takový test má pro mě (a předpokládám, že i pro další programátory/testery) velkou hodnotu, jelikož testování není pouhá validace funkčnosti, ale také snaha objevit chyby. Sumarizace neprůchozího testu by tedy měla pomoci co nejdříve v aplikaci objevit přesné místo chyby a ne jen poukázat na její existenci. Pro demonstraci výpisu jsem vymyslel následující fiktivní scénář s fiktivní chybou: 1. Uživatel jde na počáteční URL aplikace. 2. Uživatel vyplní přihlašovací údaje a potvrdí formulář kliknutí na tlačítko Login. 3. Test ověří, zda je uživatel přihlášen. 57
5. Analýza testovacích frameworků pro webové aplikace
Obrázek 5.2: Sumarizace testování frameworku Canoo WebTest 4. Test navrátí aplikaci do původního stavu před svým počátkem. Pouze pro názornost výpisu jsem upravil kód aplikace tak, aby nebylo možné se přihlásit, a tudíž aby test skončil s chybou. Dále jsem s chybujícím testem zároveň spustil testy průchozí, zmíněné v 5.3.1. Z obrázků 5.2 a 5.3 je patrné, že výpis z Canoo WebTest nabízí spoustu užitečných informací. Nejen že je zde vidět ucelená sumarizace celého testování, nýbrž je možné jednotlivé testy rozkliknout a podívat se, jak dopadly jednotlivé kroky daného testu. Pokud test neprojde, je testerovi přesně ukázáno, při jakém kroku test „spadl“ a s jakou chybou. Velmi příjemným překvapením pro mě byla možnost zobrazit obrázek poslední HTML stránky při neúspěšném testu. Sumarizace testů v Seleniu je limitována skutečností, že se jedná (v mém případě) o JUnit test. Z obrázku 5.4 je zřejmé, že výpis Selenia nedosahuje ani zdaleka vlastností, které má výpis Canoo framework. Z toho důvodu dávám Canoo WebTestu plných 5 bodů a Seleniu pouhé 2 body.
5.3.3
Možnost optimalizačních testů pro prohlížeče
Už jen z podstaty obou frameworků mluví toto kritérium jasně pro Selenium, jelikož Selenium spouští testy v reálném prohlížeči a umožňuje tedy vytvořit automatizované testy pro jednotlivé prohlížeče. Opakem je Canoo WebTest, který spouští testy na fiktivním prohlížeči HtmlUnit. Sice je možné v konfiguraci testu nastavit, aby byl daný test simulován na různých verzích Firefoxu či Internet Exploreru, ale nikdy nepůjde o nic více než 58
5.3. Porovnání testovacích frameworků
Obrázek 5.3: Sumarizace konkrétního testu frameworku Canoo WebTest o simulaci. Hodnocení je tedy zřejmé. Selenium dostává 5 bodů a Canoo WebTest žádný.
5.3.4
Rychlost naučení se s frameworkem
Jako nováček při práci s oběma frameworky mohu objektivně prohlásit, že naučit se pracovat na primitivní úrovni se Seleniem je daleko snažší než s frameworkem Canoo WebTest. Hlavním důvodem je nástroj Selenium IDE, který proces pochopení a hlavně rychlost napsání a spuštění vůbec prvního testu značně urychlí. Krása IDE spočívá především v možnosti celý test doslova naklikat a pak snadno extrahovat do zvoleného jazyka a formátu (v mém případě šlo o Javu a formát pro WebDriver). Za tuto vlastnost si Selenium zaslouží plných 5 bodů. Vytvoření ukázkového testu v Canoo WebTest frameworku také není nic těžkého, avšak neobejde se to bez příkazové řádky. Nejsem odpůrcem příkazové řádky, ale ani jejím zarytým fanouškem, proto Canoo WebTestu v porovnání se Seleniem nemohu dát více než 3 body.
5.3.5
Dokumentace
Dokumentace Canoo WebTestu ([1]) není nikterak rozsáhlá, ale přijde mi zcela dostačující. Obzvláště oceňuji abecedně seřazené a zdokumentované všechny úlohy, které je možné použít. Nicméně nadšenci pro jazyk Groovy, 59
5. Analýza testovacích frameworků pro webové aplikace
Obrázek 5.4: Výpis Selenium WebDriver testu
kteří odmítají psát testy pomocí XML, mohou být zklamaní. Psaní testů v Groovy je věnováno velice málo a všechny podstatné ukázky jsou psány v XML. Důvodem je pravděpodobně to, že rozdíl psaní v Goovy a XML není nijak markantní a lze jednoduše převést jeden na druhý. Na druhou stranu, pokud někdo preferuje čtení v Groovy před XML, musí se prozatím smířit s faktem, že dokumentaci Canoo WebTestu bude studovat v XML. Protože já sám preferuji XML, byl jsem s dokumentací relativně spokojen a dávám Canoo WebTestu 4 body. Dokumentace Selenia ([5]) je od dokumentace Canoo WebTestu poměrně dost odlišná. Jelikož se Selenium skládá z více samostatných částí, je každé části věnována zvláštní sekce. Každá sekce je podle mého názoru opravdu hezky napsaná a nepopisuje pouze, jak framework používat, ale také jak samotný framework funguje. Dalším kladem dokumentace Selenia je, že její text je doprovázen obrázky a tím se pro mne stala daleko přehlednější. Největším momentálním záporem dokumentace Selenia je následující věta v sekci WebDriver: „We’re currently working on documenting these sections.“ V tomto případě to neznamená, že by dokumentace k WebDri60
5.3. Porovnání testovacích frameworků veru nebyla žádná, ale vývojáři otevřeně přiznávají, že uvedené informace nemusí být aktuální. Ještě větší mínus přináší fakt, že jsem dokumentaci prohlížel přibližně od srpna 2012 do května 2013 a nezaregistroval jsem žádnou změnu. Z tohoto důvodu dávám Seleniu pouhé 3 body, neboť zrovna dokumentace WebDriveru byla největším bodem mého zájmu.
5.3.6
Shrnutí porovnání
Dle tabulky 5.2 je výsledek porovnání frameworků téměř nerozhodný. Je však potřeba vzít v úvahu důležitost jednotlivých kritérií. Pro mne osobně jsou nejdůležitějšími kritérii rychlost a sumarizace, protože právě sumarizace umožňuje rychle opravit chyby a rychlost dělá poměrně nezáživné testování o něco snesitelnějším. V obou preferovaných kritériích je jednoznačně lepší Canoo WebTest, tudíž právě Canoo WebTest je zvolen pro testování aplikace.
Rychlost Sumarizace testu Prohlížeče Učení Dokumentace Celkem
Selenium WebDriver 0 2 5 5 3 15
Canoo WebTest 5 5 0 3 4 17
Tabulka 5.2: Shrnutí porovnání jednotlivých frameworků
61
Kapitola
6
Testování aplikace Každou součást aplikace bylo samozřejmě zapotřebí otestovat. Vzhledem k rozsahu aplikace však nebylo testování úplně jednoduché, proto jsem ho rozdělil do následujících základních částí:
6.1
Funkční testování
Jak již bylo řečeno v kapitole 2.6.1, funkční testování se zabývá testováním fundamentálních funkcí aplikace, které byly součástí zadání aplikace. V rámci testování CrossFit aplikace byly vytvořeny testy kontrolující, zda bylo zadání dodrženo. K psaní těchto testů, které pokrývají většinu případů užití, bylo použito frameworku Canoo WebTest (vybraného v kapitole 5). Dále testují jednotlivé formuláře aplikace nejtypičtější špatné vstupy. Vzhledem k potřebám serveru jsou testy mířeny především na nutnost vyplnění povinných údajů. Canoo WebTest testy lze nalézt na přiloženém CD a výstup testování lze zhlédnout na obrázku 6.1. Každý test má u sebe v komentáři vysvětleny všeobecné předpoklady, které musí být splněny, aby měl test význam.
6.2
Mazací politika
CrossFit aplikace má mnoho součástí silně provázaných, tudíž je musíme brát zřetel na mazaní jednotlivých částí v administrační části serveru. Jako ukázka důležitosti mazací politiky může posloužit mazání provedení. Smazáním provedení, které je součástí nějakého vygenerovaného tréninku, bychom tuto posloupnost poškodili, a tudíž je nutné smazání takového provedení zakázat. 63
6. Testování aplikace
Obrázek 6.1: Výsledek funkčního testování
Pro kontrolu mazací politiky byly vytvořeny jednotlivé JUnit testy, které jsou součástí zdrojového kódu na přiloženém CD. Jde především o následůjící testy DAO objektů implementovaných pomocí Hibernate: • CvikDAOMazaciPolitikaTest • PreddefinovaneNastaveniDAOMazaciPolitikaTest • ProvedeniDAOMazaciPolitkaTest • TreninkDAOMazaciPolitikaTest
6.3
Vlastní testy
V průběhu vývoje aplikace jsem aplikaci postupně testoval. Především jsem se soustředil na otestování generování tréninků a synchronizaci cvičebních 64
6.3. Vlastní testy plánů. Otestování generování tréninků bylo velice složité, jelikož jde o proces, v němž hraje velkou roli náhoda. Tudíž jsem postupně nechal generovat cvičební plány a sledoval, jaké posloupnosti tréninků z generovaní vystupovaly. Podobně obtížné bylo testování synchronizace posloupností. Zde sice nešlo o náhodu, ale o algoritmus s vysokou složitostí. Testování jednoduchých posloupností je možné pouze za předpokladu, že algoritmu předložíme jednoduché posloupnosti, u kterých známe výsledek a ten je poté porovnán. Nicméně testování synchronizace v reálném měřítku (cca 4 posloupnosti, každá cca o 30 trénincích) je opět nemožné, protože k validaci výsledku by bylo zapotřebí použít právě testovaného algoritmu. Je tedy zřejmé, že takové testování nemá smysl. Z toho důvodu byly synchronizace z reálného použití testovány „ručně“.
65
Závěr Cílem této práce bylo analyzovat a následně implementovat klient-server aplikaci, která vytváří a synchronizuje cvičební plány CrossFit sportovců. Už samo zadání mi umožnilo vyzkoušet si na vlastní kůži průběh softwarového vývoje a poskytlo mi příležitost naučit se mnoha novým a velmi zajímavým věcem. Především si vážím příležitosti vyzkoušet si komunikaci s potenciálním zákazníkem, neboť ta mi nejvíce otevřela oči v oblasti realizace vývoje softwaru na zakázku. Největší překážkou v implementační části pro mne byla synchronizace cvičebních plánů, neboť bylo zapotřebí navrhnout řešení unikátního problému hledání podobnosti tréninků pomocí teorie grafů. Nicméně doufám a věřím, že se mi podařilo tuto i další překážky úspěšně překonat. Poslední částí této práce je zpracovaná analýza testovacích frameworků pro webové aplikace, díky které jsem měl možnost ponořit se více do problematiky testování. Závěrem bych rád dodal, že v aplikaci je samozřejmě spousta prostoru pro zlepšení do budoucna. Mé plány pro další vývoj jsou především konzultace s potenciálním zákazníkem a s jeho pomocí dokončení projektu CrossFit aplikace až k samotnému nasazení.
67
Literatura c 2002-2008, [cit. 2013-05-05]. Dostupné [1] Canoo WebTest [online]. z: http://webtest.canoo.com/webtest/manual/manualOverview. html c 2003-2011, [cit. 2013-05-09]. Dostupné z: http: [2] JGraphT [online]. //jgrapht.org/ c 2004, [cit. 2013[3] Hibernate Getting Started Guide [online]. 05-08]. Dostupné z: http://docs.jboss.org/hibernate/orm/4.1/ quickstart/en-US/html_single/ c 2004-2012, [cit. 2013-05-08]. Do[4] Web MVC framework [online]. stupné z: http://static.springsource.org/spring/docs/3.1.x/ spring-framework-reference/html/mvc.html c 2008-2012, [cit. 2013[5] Selenium - Web Browser Automation [online]. 05-05]. Dostupné z: http://docs.seleniumhq.org [6] Testování softwaru. Praha, Česká republika: COMPUTER PRESS, 2002, ISBN 80-7226-636-5. [7] What Is a Good Test Case? [online]. 2003, [cit. 2013-03-05]. Dostupné z: http://www.kaner.com/pdfs/GoodTest.pdf [8] Teoretická informatika. Praha: Vydavatelství ČVUT, 2004, ISBN 80900853-8-5. [9] Expert Spring MVC and Web Flow. Berkeley, Calif, USA: Apress, 2005, ISBN 978-1-59059-584-8. 69
Literatura [10] Spring Security [online]. 2005-2012, [cit. 2013-05-08]. Dostupné z: http://static.springsource.org/spring-security/site/docs/ 3.1.x/reference/introduction.html [11] The Java Persistence API - A Simpler Programming Model for Entity Persistence [online]. 2006, [cit. 2013-05-08]. Dostupné z: http://www. oracle.com/technetwork/articles/javaee/jpa-137156.html [12] RESTEasy JAX-RS [online]. 2006, [cit. 2013-05-09]. Dostupné z: http://docs.jboss.org/resteasy/docs/2.3.6.Final/userguide/ html/index.html [13] Growing Object-Oriented Software, Guided by Tests. Crawfordsville, Indiana, USA: Pearson Education, Inc, 2009, ISBN 978-0-321-50362-6. [14] "RESTful Java with JAX-RS". Sebastopol, CA, USA: "O’Reilly Media", "2009", ISBN 978-0-569-15804-0. [15] CrossFit [online]. Červen 2010, [cit. 2013-04-02]. Dostupné z: http: //www.crossfit.com [16] Selenium 1.0 Testing Tools. Birmingham, UK: Packt Publishing Ltd., 2010, ISBN 978-1-849510-26-4. [17] The seductive and dangerous V Model [online]. Červen 2012, [cit. 201304-05]. Dostupné z: http://www.clarotesting.com/page11.htm [18] Maven [online]. 2013, [cit. 2013-05-09]. Dostupné z: http://maven. apache.org/ [19] Havlíčková, M. A.: Testování softwaru [online]. Červen 2009, [cit. 201304-05]. Dostupné z: http://www.testovanisoftwaru.blogspot.cz
70
Příloha
Seznam použitých zkratek DAO - Data Access Object HTML - HyperText Markup Language JPA - Java Persistence API JSP - JavaServer Pages MVC - Model View Controller ORM - Object-relational mapping PDF - Portable Document Format POM - Project Object Model TDD - Test Driven Development URL - Uniform Resource Locator XML - Extensible Markup Language
71
A
Příloha
Obsah přiloženého CD
readme.txt ................................ stručný popis obsahu CD img ...................................... použité a zmíněné obrázky src canooTests...............vytvořené testy pomocí Canoo WebTest mvnProjects........jednotlivé Maven projekty se zdrojovými kódy thesis....................zdrojová forma práce ve formátu LATEX text.....................................................text práce BP_Vesely_David_2013.pdf...........text práce ve formátu PDF BP_Vesely_David_2013.ps..............text práce ve formátu PS war ...................... adresář se soubory připravenými k nasazení 73
B