fbpx

Prečo nemám rád integračné testy

Integračné testy sú potrebné. Ale vedia ma naštvať v situácii, keď sú používané ako náhrada unit testov. Problém je v tom, že na prvý pohľad vyzerajú ako skvelá alternatíva k unit testom.

Unit testy majú tendenciu prešpecifikovať interné detaily a tak komplikujú refaktoring. A nedokážu odhaliť celú triedu problémov s integráciou a konfiguráciou.

To ale neznamená, že unit testy treba zatratiť a písať výhradne end-to-end testy alebo akúkoľvek ich alternatívu. Všetky označujem spoločným výrazom integračné testy.

Podľa mojich skúseností majú integračné testy nasledujúce nevýhody, v porovnaní s unit testami:

Poskytujú malé pokrytie

Nie je praktické pokryť dostatočne veľké množstvo ciest v aplikácii týmito testami. Tým, že testujeme oveľa dlhšie cesty, je na nich viac vetvení. A teda počet ciest v kóde rastie exponenciálne. Prvýkrát som o tomto probléme čítal u autora knihy JUnit Recipes.

(Počul som o prípade, keď vhodnou kombináciou unit testov a viacerých druhov integračných testov dosiahli na projekte neuveriteľné pokrytie. Ale cena bola vysoká.)

Integračné testy sú pomalé

Integračné testy potrebujú nainicializovať veľa komponentov (zvyčajne celú aplikáciu) a pristupujú na okolité prostredie ako databázy alebo internetové služby. To priamo obmedzuje počet testov, ktoré dokážu zbehnúť v rozumnom čase. Takže sa môže stať, že postupne, ako ich počet rastie, sa budú spúšťať zriedkavejšie. Nakoniec skončíme pri jednom spustení za noc. To znižuje ich užitočnosť, v porovnaní s rýchlymi unit testami, ktoré sa spúšťajú pri každom builde.

Pri zriedkavom spúšťaní integračných testov stihne pribudnúť viacero komitov/mergov medzi dvoma spusteniami. Takže ak testy zlyhajú, nemusí byť na prvý pohľad jasné, kto to spôsobil. To zvyšuje náklady na jeho opravu.

Samozrejmosťou je aj pomalosť pri ich vývoji. Programátor zvyčajne potrebuje viac iterácií, aby doladil detaily integračného testu a pomalé nabiehanie aplikácie, či beh testu je frustrujúci.

Čas sú peniaze platí aj pri integračných testoch.

Integračné testy sú nestabilné

Prístup k databázam, messagingu a vzdialeným službám znamená občasné výpadky.

Akékoľvek zlyhanie spôsobuje straty. Aj to z dôvodu výpadku nejakej služby. Nevadí, že je služba za 10 minút späť. Už sa asi niekto pozrel na report a začal analyzovať čo sa stalo. Možno bude nakoniec rád, že to bol len neškodný výpadok, ale adrenalín sa mu už pravdepodobne vyplavil. (Ako sa merajú straty spôsobené zbytočne vystresovaným programátorom?)

Nestabilitu môže spôsobovať aj potreba komplexných dátových štruktúr, ktoré bývajú unikátne skoro pre každý test. Čím viac unikátnych testovacích sád potrebujeme, tým bude ich údržba počas bežného vývoja a pridávaní novej funkcionality komplikovanejšia.

Nemusíte mať na projekte implementované integračné testy, aby ste vedeli posúdiť ich stabilitu. Stačí ak máte testovacie scenáre pre manuálne testovanie. Sú tieto vaše testy stabilné aj po roku vývoja? Alebo ich treba priebežne upravovať a rozširovať vstupné údaje o novo implementovanú funkcionalitu?

Nestabilita testov vedie k nebezpečnej situácii. Že si ľudia prestanú všímať, že niečo zlyhalo, lebo je to normálne.

Pred mnohými rokmi som robil na projekte, kde boli (pomocou JUnit) naprogramované integračné alebo skôr akceptačné testy. Výsledky sa premietali na displayi, tak aby ich všetci videli. Dobrý nápad bol, že sa testy vytvorili pred samotným začiatkom implementácie nových požiadaviek. Už menej dobrý nápad bol, že tieto testy sa hneď zaradili do suity medzi ostatné. To znamená, že ako celok bola testsuita skoro stále červená. Celé týždne.

Najprv som sa mi to zdalo OK. Ale jedného dňa ľudia okolo mňa začali obdivovať ako sa odrazu skokom znížil počet zlyhaných testov. Povedzme zo 83 na 66. Jeden pohľad na stacktrace prvého zlyhaného testu stačil. Tentokrát nezlyhali testy tak ako MALI ZLYHAŤ. Pre zmenu zlyhalo niečo v @BeforeClass a JUnit započítal všetky príslušné testy ako jediné zlyhanie.

Nepovedia kde je problém

Integračný test nájde problém a zlyhá. Teraz je rad na nás, prísť na to, kde je chyba. Či je to vo vstupných údajoch; niektorý komponent robí niečo zle; prípadne nejaký komponent by aj rád spravil správnu vec, ale nikto ho nezavolal. Alebo naopak, niekto ho zavolal hoci nemal. Integračný test nám zvyčajne nepomôže presne lokalizovať miesto chyby.

Dobrý unit test testuje len zlomok funkcionality testovanej integračným testom. Preto môže oveľa presnejšie lokalizovať problém. Hoci dôvody prečo zlyhá môžu byť také isté ako pri integračnom teste — dáta; chyba v komponente; nebola zavolaná správna metóda; alebo bola zavolaná nesprávne.

Záver

Mojím cieľom nebolo zatracovať integračné testy. Len som chcel poukázať na ich slabiny. A to v kontexte, keď je snaha nahradiť unit testy písaním viacerých integračných testov. Pretože ich nevedia efektívne nahradiť. Vedia ich len vhodne doplniť, tak aby nevýhody jedného prístupu boli kompenzované druhým. A preto je užitočné takto pristupovať k ich tvorbe.