Javascriptaření: nejen jQuery živ je JavaScriptař

Po poměrně urputném odporu JS vývojářů proti jakýmkoli cizím knihovnám (ještě před několika lety) se situace pomalu obrací a jQuery dnes naleznete téměř na každém webu. Ovšem jQuery není jediná JS knihovna, která může ušetřit práci. Ukažme si některé další, které poměrně úspěšně táhnou světem.
Seriál: Javascriptaření (9 dílů)
- Javascriptaření: hrajte si s funkcemi! 31. 1. 2011
- ECMAScript Strict mode ve Firefoxu 4 8. 2. 2011
- Javascriptaření: nejen jQuery živ je JavaScriptař 8. 3. 2011
- Javascriptaření: fyzika, grafika a společenská konverzace 23. 3. 2011
- JavaScriptaření: drátujeme, překládáme, spojujeme 31. 3. 2011
- Javascriptaření: ukažte mi, označte mě, opravte mě 13. 4. 2011
- Kontrola JavaScriptu s JSLint a JSHint 14. 7. 2011
- Základní vzory pro vytváření jmenných prostorů v JavaScriptu 10. 10. 2011
- Javascriptaření: překladače, pakovače 9. 11. 2011
Nálepky:
V tomto Javascriptaření vynecháme velké frameworky a knihovny jako YUI či Closure a zaměříme se na menší, ale nikoli méně zajímavé. Pokud sledujete zahraniční zdroje, jistě vám neuniklo, že se o nich v poslední době píše nejen jako o zajímavostech, ale čím dál častěji v souvislostech jako „v nové webové aplikaci jsme použili knihovnu XYZ, a ušetřilo nám to spoustu práce…“
Pojďme si tedy představit ty nejznámější knihovny a říct si, k čemu je můžete použít.
Backbone.js
Pokud je řeč o webových aplikacích běžících v prohlížeči, nelze začít jinou knihovnou než právě touto. Backbone.js (název „páteř“ je zvolen velmi přiléhavě) je knihovna, která by měla tvořit základ celé aplikace, resp. její JS části. Zajišťuje práci s modely (modely jsou provázány s akcemi UI), nabízí práci s kolekcemi, umožňuje zpracování #fragmentů URL pomocí metod připomínající kontroléry a routování, obsahuje základ pro vytváření pohledů, a usnadňuje navázání celé klientské aplikace na existující serverové rozhraní (AJAJ/RESTful). To vše v cca 10 kB minifikovaného kódu.
Autoři knihovny píší: Když pracujete na webové aplikaci, která hojně využívá JavaScript, první věc, kterou se musíte odnaučit, je snaha spojovat data s DOMem. Je velmi snadné napsat JS aplikaci jako hromadu zašmodrchaných jQuery selektorů a callbacků, které se zběsile snaží udržet synchronizaci mezi daty v HTML/DOMu, v proměnných JS a v databázi na serveru. Pokud má být klientská aplikace opravdu „rich“, pomůže strukturovanější přístup. S Backbone popisujete svá data pomocí modelů, které mohou být vytvářeny, ověřovány, rušeny či ukládány na server. Když požaduje UI změnu některého atributu, spustí model událost „change“, což mimo jiné způsobí, že všechny pohledy, které zobrazují data daného modelu, budou vědět o změně a mohou se překreslit. Nemusíte psát spojovací kód, který bude sledovat DOM, v něm najde konkrétní element se zadaným ID a upraví ručně HTML: když se změní model, pohledy se jednoduše překreslí samy.
Knihovna je navržena tak, aby mohla spolupracovat s dalšími knihovnami, např. s jQuery/Zepto či s Underscore. Zdrojové kódy Backbone jsou k dispozici na GitHubu pod volnou BSD-like licencí.
Underscore
Knihovna Underscore je uvozena sloganem: je-li jQuery váš oblek do společnosti, je Underscore vázankou. Tato knihovna nedělá vlastně nic „přímo viditelného“, jen zjednodušuje práci v některých oblastech, které by šlo zahrnout mezi „výrazové prostředky jazyka“ – například práci s kolekcemi, s poli, s objekty a funkcemi.
Některé funkce, které Underscore nabízí (např. map a reduce – více viz minulé Javascriptaření) jsou už v novějších interpretech JavaScriptu implementovány. Underscore v takovém případě nevymýšlí kolo a přenechá práci nativní implementaci. Výhodou je jednotná práce s těmito funkcemi bez ohledu na konkrétní verzi prohlížeče či JS engine.
Underscore nabízí, jak jsme si už řekli, řadu funkcí pro práci s kolekcemi, poli a dalšími prvky jazyka. Mezi ně patří např. funkce map, reduce, each, select, max, min, select, reject
a další pro práci s kolekcemi, zip, flatten, first, rest
nebo last
pro pole, keys, values
či extend
pro objekty, a v neposlední řadě bind, memoize
či defer
pro funkce (výčet možností samozřejmě není kompletní). Pokud vám chybí v JavaScriptu nějaký výrazový prostředek pro práci s datovými strukturami, je pravděpodobné, že jej v Underscore naleznete.
Underscore nabízí okolo 60 funkcí, které zahrnují jak pomůcky pro funkcionální programování, tak obecné utility a speciální pomůcky pro JavaScript, jako jsou šablony či binding. Funkce knihovny Underscore lze volat jak funkcionálním, tak objektovým způsobem – následující řádky jsou tedy ekvivalentní:
_.map([1, 2, 3], function(n){ return n * 2; }); _([1, 2, 3]).map(function(n){ return n * 2; });
Existuje implementace Underscore pro jazyk Lua i Underscore.coffee (původně demo možností CoffeeScriptu). Pro samotnou knihovnu je k dispozici i plugin pro práci s řetězci Underscore.strings. K dispozici je i dokumentovaný zdrojový kód a kompletní sada testů a benchmarků.
Netestujete? Proč?
Když jsem vybíral z přehršle možných knihoven těch několik, které dát do tohoto článku, byly první dvě jednoznačné – o nich se hovoří, píše, jsou zkrátka hot. Ale kterou vybrat dál? Dát grafické Processing.js či EaselJS? Nebo vybrat spíš komunikační utility jako Socket.IO? Nakonec zvítězila trojice nástrojů, které jsou spíš nenápadné, přesto by se měly stát trendem roku 2011, byť ne tak spektakulárně jako grafické knihovny či různé mobilní frameworky.
Naši trojici tvoří QUnit, FireUnit a JSUnit. Jak už názvy napovídají, jedná se o nástroje k jednotkovému (unit) testování, volně odvozené z nástroje JUnit.
Princip jednotkového testování snad není potřeba na těchto stránkách podrobněji rozepisovat. V zásadě se jedná o to, že ze speciálního kódu („testu“) zkusíme zavolat všechny funkce v nějaké jednotce (soubor, knihovna, unit, …) a otestovat, zda na správné vstupy dají správné výstupy, a také zda na nesprávné vstupy korektně zareagují (výjimkou, speciálním návratovým kódem apod.) Výhoda jednotkového testování je v tom, že testy pokrývají oblasti, které kód dělat musí, i oblasti, které kód dělat nesmí. Pokud kód později upravíme, např. přidáme novou funkci, snadno pomocí existujících testů zjistíme, zda jsme si nerozbili něco, co už dřív fungovalo (což je funkce k nezaplacení).
Jednotkové testování můžeme použít pro každý moderní jazyk; některé mají testovací nástroje přímo ve standardní knihovně. Běžný klientský JavaScript, který především obsluhuje události, je pro automatizované strojové testování poměrně nepraktický – nástroje, kterými bychom automaticky testovali správnou reakci na kliknutí nebo (např.) to, zda se po najetí myši správně změní barva, jsou zatím v plenkách. Pro testování UI je vhodné např. Selenium. Ale přesto je spousta kódu, knihoven, utilit a helperů, které jsou jako stvořené pro automatické testování nějakým unit testem.
JSUnit je silně inspirován JUnitem. Umožňuje vytvářet testy v JavaScriptu, testovat jejich běh v prohlížeči a dokonce umožňuje získané protokoly posílat na server. Můžeme tak zařídit distribuované testování mezi uživateli, v různých prohlížečích a systémech.
FireUnit je, jak už název napovídá, určen pro prohlížeč Firefox, resp. pro nástroj Firebug. Přidává do panelu Firebugu záložku „Testy“, ze které můžete spouštět připravené testy a kontrolovat jejich výsledek.
QUnit vytvořil tým kolem jQuery právě pro testování tohoto frameworku. Opět vychází ideově z nástroje JUnit a usnadňuje strojové testování JS kódu přímo v prohlížeči. Hezký návod jak začít s testováním v QUnit nabízí NetTuts+.
K testování též: ScriptJunkie – Unit Testing 101
Kuriozitka na konec
Roli zvířátka na závěr Televizních novin tentokrát převezme Emscripten. Tento nástroj je zatím možná kuriozitou, hlavně kvůli rychlosti provádění a objemu kódu, ale boří hranice mezi prohlížečem a operačním systémem. Nesimuluje žádné běhové prostředí, ale překládá kód pro LLVM do JavaScriptu.
LLVM je virtuální běhové prostředí (obdoba JVM či .NET Runtime). Princip práce s LLVM je podobný práci např. s JVM – překladač z vyššího jazyka vytvoří bajtkód, který je prováděn výkonným jádrem LLVM. Umožňuje to snadnou přenositelnost takového bajtkódu mezi platformami, kde je LLVM implementované. Pro LLVM existuje řada překladačů, optimalizátorů a dalších nástrojů…
Emscripten vezme přeložený bajtkód (např. z překladače llvm-gcc) a tento bajtkód přeloží do JavaScriptu (není to tedy interpret LLVM, ale obdoba JIT kompilace). Výsledek lze spustit přímo v prohlížeči. Znamená to tedy, že můžete vzít hotové programy v C/C++/ObjC a dalších jazycích, pro které je LLVM překladač, a „přechroupat“ je pro prohlížeč.
Výsledná rychlost není nijak ohromující, což je pochopitelné. Rozhodně se tedy nejedná o nástroj, vhodný pro produkční nasazení. Jeho současné možnosti ukazuje třeba ukázkový Python. Jde o zdrojové kódy Pythonu, přeložené pomocí překladače do LLVM bajtkódu a Emscriptenem překonvertované do JavaScriptu. Načítání nějakou dobu trvá, ale výsledkem je – inu, Python, jak jej známe, ale běží v prohlížeči.
Dnes je to kuriozita, časem se možná dočkáme zabudovaného LLVM engine přímo v prohlížeči, kdoví?
Příště…
Příště si představíme další JavaScriptové knihovny – co byste řekli třeba fyzikálnímu engine či nadstavbě nad WebGL, která usnadní psaní 3D akcelerovaných grafických aplikací?
Pěkné shrnutí. Backbone vypadá zajímavě, v nejbližší době ho vyzkouším. Akorát místo underscore bych spíš doporučil jLinq(http://www.hugoware.net/Projects/jLinq) – je o dost propracovanější a pokud někdo umí linq, tak práce s jLinq pro něj bude hračka. Co se týče testů, tak ty se hodí spíš na středně velké až velké projekty, u těch menších asi většina lidí odpoví, že je to zbytečně zdržuje(a podle mě oprávněně). No a emscripten mi přijde jako nouzovka, osobně bych pomocí něj aplikace určitě nedělal, to je radši přepíšu ručně.
Underscore a Linq nejsou moc příbuzné. Takříkajíc skoro vůbec ne. jLinq řeší výběr dat a la Linq, Underscore je servisní knihovna pro *obecné operace* s datovými strukturami a funkcemi(!). Tedy každé je určeno pro něco trošku jiného, a od toho se odvíjí i použití. Rozhodně to není „místo Underscore jLinq“.
S tím testováním myslím, že nemáte pravdu. I stořádková knihovní funkce se vytváří líp s testem, nehledě na to, že se líp upravuje, když k ní za tři roky přijdete, ve chvíli, kdy ji máte narvanou v deseti webech, a potřebujete „jen lehce něco přidat…“ Zase to neberte jako binární možnost: netestovat nic vs testovat všechno. Když si napíšu jednorázový ad hoc kód, na testy kašlu, ale když počítám s tím, že bych některé části mohl použít v dalších projektech (a takové jsou i u malých projektů), tak by sada testů měla být samozřejmostí.
Emscripten není nouzovka, rozhodně bych v něm nedělal nic. Je to kuriozita; zajímavost, hříčka… Takové to tvrzení o JS coby webovém assembleru, dotažené do důsledků. :) Víc v tom nehledejte
No při pohledu na seznam funkcí jsem našel jenom pár, co by nebyly právě v jLinq nebo přímo v jQuery. Navíc underscore má celkem hnusný zápis, osobně se bez něj obejdu(tím netvrdím, že je k ničemu, někdo pro něj určitě využití najde). Testování jako binární věc neberu, jen mi přijde zbytečné dvě hodiny psát test pro aplikaci, která se dá ručně otestovat za dvě minuty, u větších aplikací už to opodstatnění má. Jinak pokud mám stejnou funkci na deseti různých webech, tak se dá taky očekávat, že jeho změna může mít na každém z nich různé důsledky z hlediska webu jako celku, takže by se testy stejně musely po nasazení doladit(pokud nejde o deset identických webů).
„jen mi přijde zbytečné dvě hodiny psát test pro aplikaci, která se dá ručně otestovat za dvě minuty“ – psal jste někdy testy, nebo jen „máte dojem“, že „to je nějak takto“? Protože – nezlobte se, ale nevěřím tomuto poměru.
Popíšu to znovu a použiju váš příklad: Pokud mám stejnou funkci na deseti různých webech, tak když ji píšu poprvé, napíšu ji jako knihovnu (řekněme převod geolokačních souřadnic z desetinného zápisu stupňů na stupně+hodiny+ vteřiny). Tuhle knihovnu pokryju testama, které ověří, že knihovna dělá přesně to, co dělat má, a nemá jiné postranní projevy. V tu chvíli je to černá skříňka, která dělá přesně jednu věc (převádí jednotky). Mohu ji tedy použít na deseti webech, a na všech bude dělat tutéž věc.
(Ba co víc: pokud mám testy napsané dobře, tak teoreticky mohu použít jakoukoli „černou skříňku“, která jimi projde!)
Hypoteticky pak přidám, kvůli webu 11, převod na nějaké interní souřadnice. Dopíšu do testů (jsou inrementální!) testování pro tyto souřadnice a otestuju opět celou knihovnu. Pokud testy projdou naprosto stejně, bude se knihovna dál chovat i na předchozích deseti webech stejně. Pokud bude mít taková změna někde „důsledky z hlediska webu jako celku“, tak jsem něco udělal špatně v tom webu, pravděpodobně jsem spoléhal na to, že knihovna má nějaký vedlejší efekt, to znamená že jsem ji špatně otestoval.
Jednotkové testování testuje jednotky (knihovny), nikoli případy použití (jejich fungování v aplikaci).
Máte pravdu, kapitolu o testování jsem přeskočil, myslel jsem, že vám jde o testování aplikace jako celku.
„Pokud testy projdou naprosto stejně, bude se knihovna dál chovat i na předchozích deseti webech stejně.“
To záleží na okolnostech – jak moc je daná knihovna univerzální, jestli spolu s ní uživatel nepoužije knihovnu, která ovlivní funkci té mojí(nebo rovnou základní prvky jazyka), atd. Sama o sobě může fungovat skvěle, jako součást celé aplikace už ale fungovat nemusí, spoléhat na jednotkové testy bez prověření celé aplikace taky není zrovna výhra.
To je pravda – pokud si „rozbiju stroj“, tj. použiju něco, co „rozšteluje“ základní prvky jazyka, tak mi opravdu není pomoci :) Jednotkové testování není všespásné, to určitě ne; na druhou stranu používat něco, co ovlivní fungování „blackboxed“ knihoven (tedy razantně zasáhne do „předpokladů“), je ryzí hazardérství. (Na druhou stranu lze takový případ zpětně zabudovat do testů a udělat svou knihovnu odolnější i vůči takovým věcem…)
> „jen mi přijde zbytečné dvě hodiny psát test pro aplikaci, která se dá ručně
> otestovat za dvě minuty“ – psal jste někdy testy, nebo jen „máte dojem“, že „to
> je nějak takto“? Protože – nezlobte se, ale nevěřím tomuto poměru.
Podle popisu bych tipoval, že se někdy pokoušel v praxi použít testování, protože to přesně tak je :-D Ano, občas jsou věci typu konverze geolokačních souřadnic, typu „pár čísel tam, pár ven, žádný vnitřní stav“. A ty jsou pro automatizované testu velmi vhodné, jenže v praxi (alespoň té mojí) tvoří naprostý zlomek funkcí.
Naopak spousta funkcí nemá zdaleka tak jednoduchý výstup a hlavně závisí na velmi rozsáhlém stavu (databáze). Takže člověk hodinu píše funkci a pak dvě hodiny definuje stav databáze a kritéria, podle kterých se pozná, že funkce proběhla správně. No a pak přijde nějaká změna v zadání a může to definovat celé znova…
Jestli ony to nebyly takové ty praktické zkušenosti „trvalo nám to dlouho, tak jsme se na to vykašlali“ – tam chybí jen dodat „trvalo vám to dlouho, protože jste to ještě neuměli a/nebo jste to dělali blbě“, ovšem to odborníci neradi slyší, tak vymýšlí „dobré důvody“.
Když dovolíte, tu vaši „výtku“ poupravím:
– nejprve byste měl definovat vstupní stavy a očekávané výsledky
– nezapomeňte testovat nejen to, že funkce proběhla správně, ale i to, že dopadne špatně, když špatně dopadnout má! (nejčastější chyba – to, že funkce nedělá co má, to vidí každý, ale to, že dělá když nemá, vidět na první pohled není!)
– pak teprve píšete funkci.
Automatické testování vám usnadní i například to úvodní uvedení databáze do požadovaného stavu.
Tedy mezi testováním „vaší“ funkce nebo jednoduchého přepočtu není principiální rozdíl. Ovšem pokud „testujete“ tak jak jste naznačil, tj. že nejdřív smolíte funkci a pak se obtěžujete s psaním testů… :)
A teď zpátky k tomu, s čím nesouhlasíte: Můžete mi uvést příklad, kdy trvá řádné napsání testů dvě hodiny, A ZÁROVEŇ je možné vše, co testují tyto testy, otestovat „ručně během dvou minut“? (protože to je to, s čím nesouhlasím) Váš příklad to zjevně nebude – nastavit „velmi rozsáhlý stav databáze“ a zkontrolovat, zda vše proběhlo jak má, asi nebude práce na dvě minuty…
To já věřím tomu, že existuje funkce, pro kterou trvá test napsat 2 hodiny (i více). A to proto, že je ona funkce blbě napsaná.
Není třeba hned psát nejprve testy a až pak kód (TDD puristi, klidně si mě sežerte), stačí mít trošku disciplíny a při implementaci myslet na to, že se pro to bude muset napsat test. To přirozeně vede k tomu, že funkce bude mít minimum závislostí, takže testování bude snadné, a navíc bude aplikace krásně decoupled (jednotlivé části pěkně oddělené).
Jenže ty závislosti často vyplývají ze zadání / povahy věci. Takže můžete mít skvěle otestovanou funkci – která ale tvoří jen část kódu a závislosti otestované nemáte. A přitom v nich bývá nejvíc problémů.
Pokud je součástí zadání špatný design aplikace, pak může být testování skutečně utrpení…
Testují se samozřejmě i závislosti – na to jsou integrační testy.
Jen krátce: Ručně víte že je DB OK, takže vyplníte formulář, odešlete, ono to zahlásí požadovaný výsledek. Automaticky musíte řešit, jestli je DB v požadovaném stavu (jsou tam objekty co tam být mají, nejsou ty, co tam být nemají).
Další problémy vyplývají z toho, že v praxi máte nějaký proces s X kroky, ale aby to bylo rozumně testovatelné, musíte testovat dílčí kroky. A jelikož jednotlivé testy jsou na sobě nezávislé, tak musíte definovat přesně stav DB v jednotlivých mezikrocích… Přitom při ručním testování prostě jen vyplníte pár formulářů. A to nemluvím o případu, kdy se něco změní a všechno tohle musíte definovat znovu, zatímco ručně to prostě zadáte trošku jinak.
Prostě, šedivá je teorie, zelený strom praxe, asi tak.
Neříkám, že automatické testování je úplně nanic, ale praxe není zdaleka tak růžová, jako v pečlivě vybraných učebnicových příkladech, to jsem tím chtěl říct :-)
Nejsem TDD purista, takže mi nedělá problém v popisovaném případě naplnit databázi do správného iniciálního stavu a otestovat jednotlivé kroky v jednom testu.
Upřímně – přijde mi to, že máš hokej v tom, co jsou unit-testy, integrační testy, testy uživatelského rozhraní, akceptační testy, …
jak píše Michal:
„máš hokej v tom, co jsou unit-testy, integrační testy, testy uživatelského rozhraní, akceptační testy“
protože unittest používající databázi není unittest, musíš v něm pracovat výhradně s podvrženejma ( => předem známejma) datama
Ad „Můžete mi uvést příklad, kdy trvá řádné napsání testů dvě hodiny, A ZÁROVEŇ je možné vše, co testují tyto testy, otestovat „ručně během dvou minut“?“
Třeba takové generování grafu. Úplně primitivní graf, klidně sloupcový, dva sloupečky, dva vstupní parametry (hodnoty), na výstupu obrázek – ať už SVG/XML nebo třeba PNG.
Ručně otestovat se to dá během těch dvou minut hodně krát – stihnou se vyzkoušet krajní možnosti, nesmyslné hodnoty i běžné/průměrné hodnoty. Prostě několikrát „kouknu a vidím“.
S automatizovaným testem je to o dost horší – pokud má fungovat obecně a nebýt závislý na konkrétní implementaci (tzn. nezadrátuji tam přímo to jedno výstupní XML nebo pole bajtů PNG dat – protože kdybych to dělal, tak stačí zmrazit ten kód a říct, že na něj nikdo nemá sahat). Test by měl být obecný a fungovat, i když se změní implementace a graf najednou bude mít jiný odstín zelené nebo tlustší čáry. Tohle neotestuješ ani za dva dny, natož za dvě hodiny :-)
To byl trochu zvrhlý příklad, protože tam figuruje GUI, ale pracné testy můžou být i jinde. Stačí něco víc než jen obyčejné funkce (jednoduchý vstup/výstup), trochu toho OOP. Objekty mají vnitřní stav, může záležet na pořadí metod, např. při pořadí volání metod a,b,c,d bude chování objektu správné, ale při volání v pořadí b,c,a,d se už objekt bude chovat jinak než má. Nebo parametry metod – i taková „drobnost“ jako že některé parametry jsou null – z toho plyne velké množství kombinací, které by se měly teoreticky otestovat. A nemusí to být jen null, k chybě může docházet i při jiné kombinaci hodnot… A ani při 100% pokrytí (při testech se vykonají všechny řádky kódu) nemusíme otestovat všechny kombinace, které můžou nastat a způsobit chybu.
Někdy mám pocit, že někteří diskutující mají binární uvažování: Buď všechno, nebo nic. Jejich argumentace extrémními případy je občas úsměvná, ale po delší době spíš jen únavná.
Takže Franto: Budu-li mít knihovnu pro kreslení grafů, tak použiju unit testy na to, abych ověřil, že knihovna dokáže přijmout sady hodnot, že odmítne hodnoty špatné, že správně přijme barvu „red“, ale vyhodí barvu „světlemeruňkovou“, že pro trojrozměrný graf přijme právě a pouze dvojrozměrné pole hodnot… atakdál. To jsou věci, co jaksi nespadají do tvého „kouknu a vidím“, resp. je mnohem jednodušší a rychlejší, když „koukne a vidí“ stroj.
Samosebou nebudu testovat STROJOVĚ to, co okem uvidím rychleji, takže se podívám až na výsledky té sady testů a uvidím, jestli se nakreslilo to, co se nakreslit mělo. POKUD strávíš čas tím, že budeš v testech implementovat rozpoznávání obrazců, tak nejsi programátor, ale jsi tupý demagog.
Dtto druhý příklad: Stěžuješ si na to, že je spousta možností, které „bys měl“ otestovat. Ano, je jich spousta, a ano, od toho máš stroj, aby je vyzkoušel za tebe a ověřil. Remcat, že „to testy neodhalí“ je chabá výmluva – tak to do nich napiš! mimochodem testy nejsou od toho, aby odhalovaly něco, o čem ty sám nevíš, testy jsou od toho, aby sis jima kryl vlastní postup, aby se ti nějakou banalitou nezřítilo to, cos už postavil.
Ad „Budu-li mít knihovnu pro kreslení grafů, tak použiju unit testy na to, abych ověřil, že knihovna dokáže přijmout sady hodnot,…“
Pokud testujeme program tak, že nám stačí, aby nespadl, ale výsledek může vrátit libovolný, tak bych se to netroufal nazývat jednotkovým testem.
Ad „POKUD strávíš čas tím, že budeš v testech implementovat rozpoznávání obrazců, tak nejsi programátor, ale jsi tupý demagog.“
Kdybys napsal „hlupák“, tak bych tu větu chápal, ale demagoga v této souvislosti nechápu. Samozřejmě že v testech nerozpoznávám obrázky.
Ad „Stěžuješ si na to, že je spousta možností, které „bys měl“ otestovat.“
Já si nestěžuji :-) Jen jsem chtěl říct, že v praxi to není zdaleka tak růžové a skvělé jako v učebnicových příkladech (kde se testuje jednoduchá funkce, třeba sčítání nebo převod souřadnic). Tahle diskuse se rozvinula pod větou: „Protože – nezlobte se, ale nevěřím tomuto poměru.“ A ono to tak skutečně může být. Teď zrovna tu mám třídu s implementací s 553 řádky a k tomu test s 643 řádky a pořád by ještě šlo otestovat některé další kombinace.
Ad „testy nejsou od toho, aby odhalovaly něco, o čem ty sám nevíš, testy jsou od toho, aby sis jima kryl vlastní postup, aby se ti nějakou banalitou nezřítilo to, cos už postavil.“
To co sám vím, si můžu sám opravit a nemusím to testovat. Jasně že testy mají zkontrolovat to, co mne nenapadlo (jinak bych to opravil sám bez nich). Navíc v TDD se píší před implementací a taky je může/má psát někdo jiný než implementátor — takže při psaní nevíš, jak to druhá strana (nebo ty později) zprasí a jaké chyby udělá, nejde se spoléhat na to, že to bude dělat správně (to bychom nemuseli testovat).
Aby to nevyznělo špatně, nejsem proti jednotkovým testům. Teď zrovna jsem na projektu, kde se unit-testuje opravdu všechno a věřím tomu, že to má smysl. Ale nelze zastírat tu druhou stranu mince — vynaložený čas (a tím pádem peníze). Rozhodně si to nelze představovat tak, že budu X hodin programovat a pak za půl hodiny spíchnu testy, do kterých napíšu, že 1+1 má dát výsledek 2 a hotovo, jdu domů — není to takhle zadarmo. A dost dobře si dovedu přestavit projekty, kde dává ekonomický smysl nepoužívat jednotkové testy, bouřlivě se vyvíjí a mění zadání a nakonec se to utáhne pomocí ručních testů nebo nějakých automatických ale komplexních — netestovat malé jednotky, ale celé komponenty, části systému, z jednoho konce na druhý. Záleží na druhu projektu, TDD není nějaká svatá kráva, ale jedna z mnoha metodik.
ackoliv jste oba totalne offtopic, rozjela se zde velmi zajimava diskuze na tema unit testu… tak ja to zkusim s krizkem po funuse
martine, franta je zvykly na argumentaci ad absurdum http://encyclopediadramatica.com/Strawman v obci programatorske celkem bezna vec.
jsou ale pripady kdy testy zaberou extremne hodne casu, konkretne jedna-li se o mix closed/open kodu (extenduje se nejaka komplexni closed trida s mizernou/outofdate dokumentaci).
v takovem pripade je nutne napsat jeji mockup ekvivalent _a_ k tomu funkcni unit test, ktery nepozna rozdil mezi nativni a mock implementaci.
pote lze inkrementalne extendovat mock a unit test a vsechny 3 veci udrzet pohromade. to vse jenom aby se odladila nejaka odnoz pridrzle closed tridy.
v takovychto pripadech kazdy normalni clovek to nejdriv naprasi co to de a k vyse uvedenemu se uchyli az kdyz se nakupi jemne bugy jez uz nejdou resit hackama na schovani nasledku, ale je potreba najit priciny.
(priklad takove hruzy – pro Flexare http://opensource.adobe.com/svn/opensource/osmf/trunk/libs/testing/NetMocker/org/osmf/netmocker/MockNetStream.as)
Pod to bych se podepsal. My anonymové jsme totiž nejchytřejší.
Převod souřadnic je krásný příklad – jednoduchá funkce, vstup, výstup, hotovo. Tohle je radost testovat. Ale zdaleka ne vždy je to tak jednoduché – někdy můžou být testy větší než samotná implementace (co do počtu řádek i času stráveného jejich psaním), když už se má tedy testovat všechno…
Na to je jediná odpověď: No a? Pokud ti vadí, že komplexní testy komplexních knihoven píšeš dlouho, jdi si sednout ke kase v supermarketu, tam testování spočívá v sečtení peněz v kase.
8. Je to dražší než dodat chybový kód / Chyby nám nevadí.
Máte ji tam :)
Testovat je hloupé, protože když odevzdám chybný kód a klient si toho nevšimne a podepíše akceptační protokol, tak až si chyby všimne, naúčtuju mu to jako vícepráce!
Něco jako silničáři v ČR. K čemu je silnice, která vydrží neporušená deset let, když se to může firma opravovat jednou za tři měsíce a jednou za dva roky frézovat a dělat komplet nový povrch?
Takže má výmluva: „Testování snižuje HDP!“. Prosím přidat.
co je mi do HDP? když ti někdo přebere zákazníka, protože ve stejným čase (takže klidně i za stejný prachy) mu dodá kód s menší chybovostí, tak ti taky bude HDP ukradený
To je blbost. Software má také záruku a klasické chyby funkčnosti jsou řešeny jako záruční opravy a zdarma (alespoň by mělo). Neznám zákazníka, který by nerazil hlavní požadavek, a to že „software má fungovat“. Odírání zákazníka za vlastní (vývojářovu) blbost je hnus. Ještě pochopím, když se u každé chyby ohodnotí závažnost a ty středně vážné (ovlivňují funkčnost) a horší se opraví, zatímco lehké (kosmetické) se neopravují.
V anketě mi chybí odpověď: „Netestujeme, protože když jsme si udělali podrobnou analýzu chyb reportovaných od zákazníka, zjistili jsme, že žádnou z nich by neodhalil jednotkový test.“ Čímž rozhodně nechci nijak snižovat význam jednotkových testů, minimálně z pohledu kvality návrhu (loose coupling) nebo náročnosti případných úprav. Jen takové povzdechnutí z praxe.
Připomnělo mi to: „Nebudu používat sluneční brýle, protože mě neochrání před rakovinou kůže!“ ;)
Nic ve zlém, ale jednotkové testování slouží k něčemu jinému než k „odhalování chyb, co reportuje zákazník“. Tento argument je na stejné úrovni jako říct „Nepoužíváme verzování zdrojáků, protože zákazníci dostávají vždy nejnovější verzi.“ Jednotkové testování přeci není pro zákazníky, ale pro vývojáře!
S tím naprosto souhlasím. Nevyjádřil jsem se dobře – v praxi jsem se setkal s odmítáním jednotkových testů s argumentací „Chyby které jsme tam nasekali, jednotkové testy stejně neodhalí.“ Proto mi ta varianta v anketě chybí. Osobně proti jednotkovým testům nejsem, naopak.
Aha, takhle… OK, to máte pravdu, tak už si rozumíme. Aneb „Naši programátoři jsou tak kreativní, že jejich chyby ani unit testy neodhalí“ :)
Jen upřesnění k LLVM: nejedná se o žádné virtuální běhové prostředí (nic jako JVM), ale o modulární překladač. Zdroják (obvykle v C/C++) se překládá do mezikódu nezávislého na architektuře, který je vhodný pro optimalizace. Z toho se potom generuje kód pro cílovou platformu. Napsáním vhodného generátoru (backendu) lze tedy generovat jak kód pro libovolný procesor, tak i zmíněný javascript. Spouštění mezikódu není primárním účelem, i když nějaké experimenty v tomto směru existují.
Velmi zajímavá knihovna je Head JS (http://headjs.com/), která má ambice být ještě nad jakýmkoliv jiným frameworkem a nabízí velmi zajímavé funkce. Myslím, že by si v článku místo zasloužila a to i přesto, že je tak trochu někde jinde.
Pro produkční nasazení se nehodí, protože je tam ještě řada bugů, které fakt ztrpčí život.
Stálo by se za to zmínit i o http://www.smartclient.com
– jak to vypada s rychlosti (velikost knihoven)?
– rychlost pro generovani treba 50 edit-elementu, 10 buttonu …ca 400 elementu
– jak to vypada, kdyz chci delat data-handling ve vlastni rezii bez tech jejich prostredku.
– priklad nejake aplikace
– licence je LGPL , jak si to vyklada isomorphic, jaky vsechen objektovy kod musim k me aplikaci pribalit?
Knihovny jsou dělené samostatně v souborech, použijete co potřebujete, pro komplexní web aplikaci cca 700 KB.
Rychlost okamžitá i pro stovky elementů.
Data handling ve vlastní režii je samozřejmostí, na výběr je několik možností.
Maji na webu bohate demo priklady i aplikace.
Nic se nemusi pribalovat, staci ty JS knihovny.