Automatizované testování JavaScriptu

Testy, které se krkolomně spouští, zobrazují nepřehledně výsledky nebo běží pomalu, budete spouštět málo a nakonec je přestanete psát. V článku pojednáme o tom, jak dosáhnout přesného opaku pomocí programu JsTestDriver. Ten umožní, aby se vaše javascriptové testy spouštěly snadno (třeba při každém uložení souboru v IDE), běžely rychle a navíc v několika prohlížečích najednou.
Nálepky:
Cíl
Představme si, že jsme se rozhodli testovat náš javascriptový kód a nyní stojíme před problémem, jak tyto testy zautomatizovat při samotném vývoji a při integračních buildech.
Nejprve si definujme, jaké požadavky na testování v JavaScriptu máme. Ve zbytku článku vám potom podrobně ukážeme jednu z cest, jak tohoto cíle dosáhnout.
- Testy chceme spouštět při každém uložení změn v kódu a nechceme přitom opouštět prostředí IDE. Výsledky testů chceme také vidět přímo v IDE.
- Chceme, aby se testy spouštěly a vyhodnocovaly při každém automatickém buildu na integračním serveru.
- Ať už pracujeme stylem TDD nebo ne, musíme testy rádi spouštět. To znamená, že testy musí proběhnout rychle (do 1 sekundy).
- Prostředí, ve kterém testujeme, musí mít dostupné javascriptové API prohlížeče. Nelze tedy jako běhové prostředí použít Node.js.
- Požadujeme maximálně jednoduchou konfiguraci pro celou sadu testů.
Překážky u většiny testovacích frameworků
Existuje spousta testovacích frameworků v JavaScriptu, které se liší svým jazykem a frameworkem mocků a stubů, málokterý však řeší uvedené první dva požadavky.
mock – objekt, který simuluje chování skutečného objektu a zná očekávaná volání.
stub – simuluje či nahrazuje chování části testovaného kódu (v JavaScriptu zpravidla funkce).
spy – monitoruje volání funkce (počet, parametry, návratové hodnoty).
Mnoho z nich spouští testy přímo v okně prohlížeče, čímž zajistí kromě prostředí pro běh samotného JavaScriptu i API prohlížeče. Má to však podstatné nevýhody:
- Kromě samotných testů totiž musíme vytvořit HTML soubor, který načte do prohlížeče veškerý testovaný kód.
- Při spouštění testů se vývojář musí přepnout do prohlížeče, obnovit stránku a počkat na výsledky.
- Zautomatizovat takové testy pro continuous integration bude obtížné například proto, že výsledky zobrazené v prohlížeči jsou dobře čitelné pro člověka, ale ne pro stroj, navíc se k nim nelze přímočaře dostat.
Další nevýhodou je, že během vývoje testujeme jen v jednom prohlížeči na jedné platformě a o chybách v jiných prohlížečích (platformách) se dozvíme až při automatickém buildu na integračním serveru, a musíme se tak vracet k již odladěnému kódu.
Při každém uložení změn kódu v IDE chceme okamžitě vědět, zda testy procházejí. To znamená, že prohlížeč(e) musí být již spuštěné a nesmíme se zdržovat přepínáním do nich a obnovováním stránky s testy, což je pomalé, protože se musí znovu načíst vykonat všechen produkční kód. Nemluvě o tom, pokud máte pro každý test case samostatný HTML soubor. Pouze výjimečně svědomitý vývojář bude takové testy spouštět.
Řešení
Stejné problémy řešili před několika lety vývojáři v Google a napsali program JsTestDriver, který se je snaží univerzálně řešit. Existují i další nástroje, například pro Mocha framework existuje projekt mocha-phantomjs, který umožňuje pouštět Mocha testy v PhantomJS, což je WebKit jádro s kompletním javascriptovým API.
Hledáme PHP a javascriptové vývojáře pro naše projekty. Kontakt michal.illich.cz.
Jak funguje JsTestDriver
JsTestDriver je malý program napsaný v Javě, který otevře HTTP službu na určitém portě (budeme jí dále říkat server). K němu se po startu připojíte z libovolně mnoha prohlížečů z libovolných platforem včetně mobilních. Můžete rovněž JsTestDriver nakonfigurovat, aby si prohlížeče otevíral sám.

Stránka otevřená v prohlížeči se stává „otrokem“ serveru, který do ní nahrává potřebný javascriptový kód (při jejich pozdější změně, pak už nahrává jen změněné soubory). Testy se spouští jednoduše z příkazové řádky, JsTestDriver obstará spuštění testů paralelně ve všech prohlížečích najednou. Prohlížeče následně odešlou výsledky testů zpátky serveru a ten vám je pak zobrazí na standardním výstupu nebo je uloží do souboru (v XML JUnit formátu). Kromě toho si můžete nechat zobrazovat i výstup konzole prohlížeče.
Vzhledem k tomu, že se při jednom běhu testů většina kódu nemusí ani parsovat a že javascriptové API je neblokující, jsou testy velmi rychlé, JsTestDriver vykoná řádově stovky testů na sekundu.
Díky jednoduchému rozhraní není problém spouštění testů v JsTestDriveru integrovat do vašeho IDE (pro Eclipse existuje i plugin) nebo do automatických buildů.
Jako konfigurace stačí seznam souborů, které se mají načíst, ve formátu YAML. Například:
load:
- lib/jasmine/jasmine.js
- lib/jstestdriver/JasmineAdapter.js
- src-js/jQuery/*.js
- src-js/app/*.js
test:
- tests/js/unit/*.js
Podívejte se, jak JsTestDriver vypadá v akci.
Z vlastní zkušenosti mohu potvrdit, že nasazení JsTestDriver pro automatické testování na našem integračním serveru bylo snadné, přestože testy nepouštíme v klasickém prohlížeči, ale v PhantomJS. Výstup výsledků v XML JUnit formátu, podporuje snad každý (i náš) integrační server.
Další výhody
JsTestDriver není další asertovací framework, můžete klidně zůstat u svého, pouze spouští vaše testy a reportuje výsledky. Nicméně, aby pochopil výstup vašeho frameworku, potřebujete použít adapter. Takové adaptery existují pro:
- Jasmine – github.com/ibolmo/jasmine-jstd-adapter
- Mocha – github.com/wikidi/mocha-jstd-adapter
V neposlední řadě JsTestDriver umožňuje pomocí pluginu generovat report o code coverage.
Shrnutí
Ukázali jsme, jak je možné zautomatizovat testy pomocí JsTestDriveru.
- JsTestDriver umožňuje spouštění testů nad farmou prohlížečů různých platforem.
- Testy jsou velmi rychlé, protože běží paralelně.
- Můžete i nadále používat svoji oblíbenou knihovnu na unit či scenario testy.
- Snadno se konfiguruje a umí i generovat code coverage report.
Cíl splněn. Pokud to děláte jinak, budeme rádi, když to sdělíte v diskusi.
Zdroje
- JsTestDriver Project
- Yet Another JavaScript Testing Framework. Miško Hevery, 23.5.2009
- There are lots of ways to tests your JavaScript, but there is only one JsTestDriver. Miško Hevery, 4.12.2009
….
Dakujem. … naozaj velmi zaujimave, vidim prvykrat. Urcite vyskusam.
Jelikoz mame integracni testy a vselijake dalsi testy v Selenium Grid 2 tak nase UT psane v Jasmine spoustime pres Selenium Grid a automatizaci resime pomoci CI serveru Jenkins.
Pěkné, a článek bys o tom napsat nechtěl? 8-)
Poslední dobou jsem dělal docela dost věcí v AngularJS a lidi z AngularJS týmu měli s JSTD nějaké problémy, tak si napsali vlastní alternativu jménem Testacular (kterou i angular-seed začal používat místo JsTestDriveru). V zásadě je to podobné jako JSTD, akorát je to postavené na Node.js a Socket.io. Na http://vojtajina.github.com/testacular/ je i celkem pěkné video, myslím že stojí za to na to mrknout.
Zajímalo by mě, jaké přesně měly s JSTD problémy. Má jistě rezervy v reportování, také píší o stabilitě. Na Node.js (oproti Javě) se mi libí, že spouštět testy a přistupovat k API serveru mohu v javascriptu, tedy ve stejném jazyce jako testovaná aplikace.
Vím ještě o jednom novém projektu, který vychází ze stejné myšlenky a je napsaný v Node.js – Buster.JS.