Spomínam si na svoje začiatky s Test-Driven Development (TDD). Rozhodovanie, aký test mám napísať ako prvý, prípadne aký má nasledovať potom bol jeden z najväčších problémov čo som mal. Každú chvíľu som musel pomerne dlho rozmýšľať nad tým, aký test má nasledovať.
Dosť skoro som si totiž začal uvedomovať, že to aký test napíšem teraz ovplyvní produkčný kód, ktorý napíšem o chvíľu. Ovplyvní to aj to, aký test bude nasledovať. Čo má zase vplyv na budúci kód. To ma paralyzovalo.
Vhodnou voľbou a poradím testov vieme ovplyvniť dobu potrebnú na dokončenie vývoja a potenciálne aj to aký bude výsledok. (Tu predpokladám, že dizajn a detaily produkčného kódu nemáme premyslené do najmenších detailov, lebo TDD je myslený aj ako dizajnový nástroj.)
Takže ako si zvolím prvý test, keď mám ešte najväčšiu slobodu výberu? Ako prekonať syndróm prázdnej obrazovky?
Závisí to aj od skúseností, od pochopenia zadania a znalosti technológií použitých v komponente. Ale aj od toho či je rozhranie pevne definované alebo si ho môžeme zvoliť.
Prvý krok
Ja zvyčajne začínam od niečoho jednoduchého, tak aby som sa niekam posunul, prípadne sa o vznikajúcom komponente niečo naučil. Keď programujem dátovú štruktúru1, tak má zmysel zamyslieť sa nad tým, ako sa správa keď je prázdna. A napíšem test, ktorý špecifikuje čo sa má stať pri zavolaní niektorej metódy na prázdnej štruktúre.
Ďalší krok
Spomenul som, že test a jeho ozelenenie má výrazný vplyv na nasledujúci test. Typická situácia nastane, keď sme riešenie sfalšovali prázdnou implementáciou alebo s natvrdo nastavenou návratovou hodnotou (Fake it). Vtedy nie je o čom rozmýšľať — ďalší test nám musí pomôcť opraviť tento „nedostatok”.
Čo ďalej?
Je celkom bežné, že počas programovania alebo rozmýšľania o teste či komponente dostaneme nejaký nápad, čo ešte treba urobiť. Je rozumné si napísať krátku poznámku, aby sme nezabudli. Zabúdame totiž stále, aj keď si myslíme, že toto nezabudneme. Ale kým je aktuálna úloha hotová, prebehli nám hlavou desiatky iných myšlienok a rozhodnutí a to, na čo sme sa práve nesústredili je preč. Je ďaleko jednoduchšie si vybrať zo zoznamu nápadov, ako po každom TDD cykle rozmýšľať čo ďalej.
Toto sa mi teraz nechce
Často sa nám stane, že sa nám práve „nechce” implementovať nejakú funkcionalitu. Ak to nie je priamo biznis logika daného komponentu, tak máme šťastie —identifikovali sme čosi, čo síce potrebujeme, ale pravdepodobne to nie je hlavná zodpovednosť komponentu. Takže to treba implementovať ako samostatný komponent. A ešte väčšie šťastie je v tom, že máme možnosť objaviť ideálne rozhranie pre tento pomocný komponent.
Vytvoríme interface
a postupne dopĺňame metódy ako ich vyvíjaný komponent potrebuje. A máme slobodu preskakovať medzi TDD-čkovaním jedného alebo druhého komponentu ako nám vyhovuje (čo ale neznamená, že by sme mali).
Už mi nič nenapadá
Toto sa stane aj skúsenému TDD-čkárovi. Vyskúšajte niečo z nasledujúceho zoznamu:
- Máme už kompletnú implementáciu? Ak áno, môžeme prejsť na integráciu komponentu do klientského komponentu. Pri integrácii možno prídeme na chýbajúcu funkciu alebo scenár.
- zamyslime sa, či nám nechýba test na nejaký scenár. Pozrime na zoznam metód v teste. Prečítajme si ich mená a možno nám niečo napadne. Preto sú čitateľné názvy metód také dôležité.
- ak máme v testoch mockované rozhranie, ku ktorému ešte neexistuje žiadna implementácia, môžeme prejsť na programovanie tej implementácie. Samozrejme pomocou TDD. Je pravdepodobné, že nám pri tom napadne, čo ešte chýba v pôvodnom komponente. Zapíšeme si poznámku, aby sme nezabudli.
Záver
Rozhodovanie sa o tom, akým testom máme pokračovať nie je pre začiatočníka jednoduché. Ale dá sa to naučiť. Podľa mojej skúsenosti to ani netrvá veľmi dlho. Dôležité je nevzdať sa a čoskoro sa to rozhodovanie zjednoduší a pôjde skoro automaticky.
Ak máte ten istý problém — strach, aby vás ďalší test neodviedol nesprávnym smerom, tak ho skúste ignorovať a nechať sa viesť testami. Ak chcete väčší stupeň bezpečia, tak komitujte po každom zelenom teste. Takto sa kedykoľvek viete vrátiť niekoľko krokov späť. Určite to nie je strata času, lebo aj tým zavrhnutým krokom ste sa niečo naučili o riešení, na ktorom pracujete.
- Dátové štruktúry robím asi častejšie ako iní programátori, lebo rád schovávam kolekcie do vlastnej triedy. Tej môžem vymyslieť rozhranie čo dáva zmysel v doméne. Okrem toho to umožňuje pridávať nové metódy priamo do dátovej štruktúry namiesto toho aby boli roztrúsené po celej aplikácii. ↩
„Vďaka mojim dlhoročným skúsenostiam s tvorbou unit testov a refaktoringom pomáham programátorom zmeniť ich postoj z musím na oveľa lepší — baví ma a dokážem.”