Píšete unit testy? Pokud ano, přemýšleli jste nad tím co vám přináší? Já ano a čím dál tím víc začínám zastávat názor, že unit testy tu nejsou od toho, aby hledaly chyby v kódu.
Účelem unit testů je totiž hledání chyb v návrhu. Je to takový rychlý detektor. Zkusíte napsat unit test na kus kódu a když to jde špatně, tak je ten kód špatně navržený. Tečka. Platí totiž jednoduché pravidlo:
Pokud jde kód špatně otestovat, je špatně navržený.
Nevím jak bych vám to dokázal, ale když se nad tím zamyslíte, tak je to evidentní. Když mám stořádkovou metodu, tak přeci nemůžu napsat jednoduchý test, který pořádně otestuje všech sto řádků. Pokud mám třídu, která dělá několik věcí současně, tak ani nebudu vědět, kde s testováním začít. Na a když mám třídu, která má hromadu závislostí, tak se zblázním z mockování.
Takže pokud vám připadá, že psaní a udržování unit testů je hromada ošklivé práce, tak není chyba v testech, ale v kódu, který se snažíte testovat.
Jediné co vám mohu doporučit je TDD. Když začnu psát testy před kódem, tak dojde k takovému kouzlu. Nebál bych se použít i slovo zázrak. I patlal jako já najednou začne psát jasný a jednoduchý kód. Když procházím svůj starší kód, na první pohled poznám, který kód jsem psal pomocí TDD a který klasicky. Když mám testy hotové před tím, než začnu kazit kód, tak mě udrží v mezích a nenechají mě překomplikovat návrh a psát špagetykód. Když si nechávám testy na potom, tak je ten kód prostě mnohem ošklivější. A to je podle mě největší přínos unit testů. Žádné hledání chyb, ale nástroj, který vás dovede ke správnému návrhu.
Takže, pokud už to tedy dávno neděláte, tak opravdu zkuste psát testy před kódem. Je to kouzlo, které když nezkusíte tak o hodně přijdete.
Poznámka: Tento blog jsem napsal proto, že jsem hledal něco podobného v češtině a nic nenašel. Přišlo mi to škoda. Jsou i lidé, kteří tvrdí, že TDD je největší změna v našem odvětví za posledních deset let. Nebo tak nějak (nedaří se mi najít zdroj). Jinak pěkný článek o tom k čemu jsou unit testy najdete tady.
Při hledání podkladů, jsem narazil na tento svůj zápisek a hlavě dokument z něj odlinkovaný, na který jsem úplně zapomněl a který mě úžasně pobavil. Doporučuji.
Po letech psaní unit testů, si 100% stojím za názorem, že největším benefitem kvalitních unit testů je (minimálně) dobrý (až kvalitní) design.
Druhým (až třetím) benefitem je, že mám nutný základ pro refactoring a regresní testy. Což spolu hodně úzce souvisí.
Ohledně rozpoznání kódu, který byl testován a který ne, mám podobnou zkušenost. Byť se nehrabu ve svém starém kódu, dost často se hrabu v cizím – ať už v rámci code review, nebo v kódu (Java) kandidátů, kteří jdou na pohovor. Výsledek je podobný – je na první pohled poznat, co bylo napsaný s ohledem na testy a co ne (a většinou ne :-/
Trochu jinou zkušenost mám s TDD. Myslím si, že stejně dobrého designu se dá dosáhnout i metodou “code first” + test + refactoring. Ono TDD se nedá vždy použít. Já třeba dost často prototypuju a tam je psaní testů zbytečné až kontraproduktivní.
„Pokud jde kód špatně otestovat, je špatně navržený,“ tak pod to se podepisuju!
Pingback: Blog - Václav Makeš » Testování kódu
Díky Lukáši, za podnětný článek. 🙂 Trochu mě to inspirovalo http://rarous.net/weblog/429-test-driven-developemt-pribeh-nezbedneho-vyvojare.aspx
Také plně věřím, že lepší návrh je ještě větším přínosem než vlastní prověření implementace (a záchytná síť pro budoucí refaktorování). I když testy přímo nepomáhají tvořit lepší návrh, ale, jak Kent Beck sám někde poznamenal, jen umožňují naplno zakusit bolestivost špatného návrhu.
Guido má pravdu, že jsou případy, kdy se TDD nehodí (jako právě prototypování), i když lidé ho zpravidla používájí mnohem méně, než by bylo dobré.
Kent měl nedávno dobré krátké zamyšlení nad hlubší podstatou a přínosem testování v “Functional TDD: A Clash of Cultures” (https://m.facebook.com/note.php?note_id=472392329460303) – mj. dvojitá verifikace kódu (které lze samozřejmě dosáhnout i jinak, než testy), dekompozice problému (testy nám určují rámec, umožňují zoom na podproblém a zároveň nám zaručují, že jeho řešení je stále funkční), automatická kontrola korektnosti, návrh “zvenku dovnitř”, tzn. nejdřív rozhraní a až pak jeho implementace.