15. května 2008

Na unit testy si vždy čas udělám ...

Přečetl jsem si příspěvek Máte čas na unit testy? od Petra Jůzy a po dlouhé době, mě nějaký text přiměl k reakci (Kde je dagi se svými kontroverzními tematy).

Přiznám se, že s testováním jsem začínal nějakým 8 let zpátky za pomocí jUnit knihovny a měl jsem dobrý pocit. Spíš mě to ale zdržovalo. Postupem času jsem se naučil (alespoň si to myslím) testy psát, začal jsem používat Coberturu a přešel jsem na TestNG.

Nedokážu si představit, že bych neměl unit testy. Proč? Jak píšu kód, píšu testy, kterými ověřím, že to celé funguje ještě předtím, než začnu integrovat komponenty dohromady. Jak to dělají ti, co testy nepíšou netuším. Pokud si vše otestuju, pak v návazných objektech používám mock implementaci téhož (díky EasyMock knihovně) a testuju dál. Nejednou jsem kód měnil, abych ho dokázal otestovat a nejednou jsem se setkal s tím, že se mi taková změna v budoucnu vyplatila.

Psát testy stojí čas, ale i když testy nepíšete, nějak musíte testovat a to také stojí čas. Pokud dojde na nějaké úpravy v budoucnu, pak jsou testy k nezaplacení, protože vzpomenout si, jak jsem to vlastně před půl rokem testoval, to už chce sakra dobrou paměť. Při opravě chyb je to podobné, testy opět pomůžou.

Psát testy až po odladění aplikace je zvěrstvo a plýtvání časem. Má to význam pouze pokud chceme opravit chybu nebo udělat změnu. Pak se může vyplatit napsat na ni testy a teprve poté se pustit do změn.

Nepoužívám TDD a tudíž testy píšu až po napsání výkonného kódu. Nějak na tuto myšlenku nejsem ještě připraven.

A co my testy přinášejí především? Jistotu ...

9 komentářů:

Anonymní řekl(a)...

Ahoj, já používám test first, ne test parallel (tzn. že skutečně píšu test na dosud neexistující třídu).

Mj. proto, že díky tomu se mi to v IDE podtrhá červeně a já mohu snadno použít Quick fix - pro vytvoření nové třídy, metody v této třídě s již správně odhadnutými parametry atp.
To je pro mě úspora času.

Vyjímkou je stav, kdy nejprve napíšu prázdnou novou Java třídu bez testu, ale to jen kvůli pěknýmu wizardu Eclipsu na vytvoření jUnit testu z otevřené třídy (předvyplní package, doplní Test atp).

Anonymní řekl(a)...

Delal jsem na projektu kde jsme museli mit 80 % pokryti testy (serverova aplikace v J2SE). 80 % je tak akorat pokryti vykonnyho kodu, zbytek je handlovani vyjimek....
Mam z toho jednu velkou zkusenost - v kazdy casti kodu kterou jsem pokrejval jsem objevil alespon malinkou chybu, takze kazdej test se mi bohate vyplatil. Od ty doby pisu testy okamzite, protoze dokad nemam pokrytej kod tak si nejsem proste jistej ze ten kod neni ok.
Jedna poznamka - to co jsme delali (pokrejvani aby bylo pokryti) mozna bylo nanic, ale naucilo me psat testy (hlavne myslet pri psani kodu na to jak ho napsat aby sel dobre testovat)

Jan Novotný řekl(a)...

Poslední příspěvěk je velmi zajímavý. Zajímalo by mě jaké procento pokrytí mají ostatní čtenáři.

Osobně jsem udělal zkušenost, že i když se nesnažím o dosažení jakéhokoliv procenta pokrytí testy, ale testy píšu jen tak, abych si byl slušně jistý, že tam není chyba, dosahuji něco málo přes 60% pokrytí.

Jira řekl(a)...

Těch 80% už je docela slušných, ale samozřejmě to nelze brát paušálně, protože jsou třídy kde stačí velmi malé pokrytí (klasicky nějaké value objekty) a jsou třídy, kde je potřeba pokrytí velké, protože se jedná o mission critical části systému.

Řekl bych, že hon na určité procento pokrytí je nesmysl a nemá cenu coverage nástroje s tímto záměrem používat.

Co se našeho velkého projektu týče, pak máme package, kde nám stačí 50% pokrytí, obecně se držíme okolo 80% pokrytí, ale jsou části, kde se pokrytí skoro blíží 100% (pokud pomíjím logovací kód).

Anonymní řekl(a)...

Já jsem na posledním projektu zkoušel dělat TDD. Neuměl jsem si to představil, ale docela to jde a je to úplně jiný pocit, než když se ty testy píší až potom. Jenom to chce disciplínu. Ubčas jsem skoulznul k tomu paralelnímu testování a občas až k testování ex post. Je ale hodně těžké určit si míru. Měl jsem dobře otestovaný kód, ale hůře otestovanou konfiguraci (integrační testy). Byl to projekt, kde byla konfigurace docela důležitá (propojování nezávislých pluginů do flow). Nakonec většina chyb, které se dostaly až k testerům byla způsobena právě špatnou konfigurací (zapomenutý nebo špatně nakonfigurovaný plugin).

Upozorňuji, že test coverage je jenom orientační hodnota. Jakmile je pod 60% tak vím, že to mám otestováno špatně. Jakmile je ale nad těch 60% nevím skoro nic. Jenom to, že tam nějaké testy jsou. Jak jsou kvalitní už mi to neřekne.

Anonymní řekl(a)...

Těch 80% považuju za dost dobré číslo. Většinou jsem se svým pokrytím někde 70-80%, to zahrnuje i integrační testy. Můj odhad je, že dalších 15-20% spadá na "plochý kód", který většinou explicitně netestuju (gettery a settery, ploché kontrolery, které jenom předávají data z aplikační vrstvy, atp.). Zbytek bohužel spadá do šedého prostoru mezi, kde bych testovat měl, ale nedělám to, dokud se v tom neobjeví bug. To je hlavně testování vyhození výjimek, některé okrajové případy, testování generovaných equals a hashCode, atp.

Určitě je nesmysl brát nějaké číslo za absolutní ukazatel kvality testů. Už proto, že nic neříká o tom, jestli se kontrolují výstupní hodnoty. Spíš jsem si zvykl to brát za relativní ukazatel, jestli jsem si třeba od začátku na projektu polepšil nebo pohoršil.

Unknown řekl(a)...

Můžete mi prosím vás popostrčit k nějakým informacím, kde je popsáno jak "správně" psát testy? Kde by měli být testovací třídy, kolikrát testovat danou funkci, atd...

Anonymní řekl(a)...

2franc: Pro začátek zkus knížku "Test Driven Development by Example" od Becka. Bohužel knížek, které by opravdu obsahovali nějaké použitelné "best practices" moc není (nebo jsem špatně hledal). Co vím, tak většina knížek má spíš styl "kuchařky". Zaměřují se na konkrétní technologie a příklady, ne na principy, což mě osobně až tak moc nevyhovuje.

Jira řekl(a)...

Kdysi mi hodně pomohlo Pragmatic Unit Testing, ale už to bude trochu zastaralé. Zase se nechá stáhnout PDF verze za pár dolarů ...