Jste zde

Proč rozlišovat jednotkové a integrační testy

Krátké zamyšlení na téma, proč je dobré odlišovat jednotkové testy od integračních.

Terminologie

Jednotkové testy (angl. unit tests) testují zvolenou komponentu (funkce, třída, modul) v izolaci. Pokud komponenta komunikuje s jinými komponentami (čili na nich závisí), tak se většinou místo nich používají náhražky, jako stubs a mocks (obojí bez překladu). Důvodem je, že v jednotkových testech nás zajímá testování pouze jedné komponenty, kdy předpokládáme, že ostatní komponenty, s nimiž ta naše interaguje, fungují korektně. Nemusíme tak řešit chyby jiných komponent. Typickým příkladem je třída využívající připojení k databázi. Místo toho, aby se využívalo reálné připojení, se použije náhražka (např. mock). O jednotkových testech jsem zde již psal.

Pro testování více komponent dohromady slouží integrační testy. Jak již jejich název napovídá, testuje se v nich interakce komponent, čili to, že dokáží spolupracovat. Pro výše zmíněnou třídu by to znamenalo, že se použije reálné připojení k databázi.

Proč je rozlišovat?

Asi každého, kdo se s těmito druhy testů setká poprvé, napadne následující otázka: Proč místo skutečných závislostí používat náhražky? Proč nepsat rovnou všechny testy jako integrační? Důvodem je, že každý z testů se hodí na něco jiného a má svá pro a proti.

  • Rychlost. Jednotkové testy bývají řádově rychlejší, než integrační testy. Pokud opravdu testujete jednotky v izolaci, tak není problém mít desítky tisíc testů, které poběží v řádu sekund. Oproti tomu integrační testy bývají pomalé a může trvat např. minutu, než proběhne 100 testů. Stačí si uvědomit, že pokud v testech pracujete se souborovým systémem či sítí, tak tyto testy nutně musí být pomalé. U jednoho testu se sice rozdíl mezi 0.001s a 0.1 s může zdát zanedbatelný, ale pokud takových testů máte tisíc, tak už je to znát. A věřte, že testů bude stále přibývat. To je pak velmi cítit při vývoji. Tam je potřeba mít co nejrychlejší odezvu, zda jsou provedené úpravy korektní. Čím dříve chybu odhalíte, tím urychlíte vývoj.
  • Determinismus. Tím, že jednotkové testy fungují v izolaci, nám zaručují determinismus. Při spolupráci komponent či využívaní externích zdrojů (např. zasílání HTTP dotazů přes síť) může docházet k tomu, že test občas neprojde (např. se nezdaří spojení k serveru), ale když je spustíte znovu, tak projdou. To opět zdržuje, protože při analýze pádu testu hledáte duchy..
  • Simulace chybových stavů. Jednotkové testy jsou typicky psané na nižší úrovni, než integrační testy. Lze pak v nich mnohem jednodušeji simulovat různé chybové stavy, např. když selže připojení při provádění dotazu v databázi. To by u reálné databáze bylo složitější. A jelikož chceme, aby naše aplikace byla robustní a odolná vůči chybám, musíme testovat i chybové stavy.
  • Nezávislý vývoj. Pomocí jednotkových testů lze vyvíjet dvě na sobě závislé komponenty nezávisle. Stačí využít náhražek, jako jsou mocky. Pokud bychom využívali jen integrační testy a v jedné z komponent by byla chyba, která by nám znemožňovala testování (a tudíž i vývoj), museli bychom počkat, až bude chyba opravena. S využitím jednotkových testů lze dokonce vyvíjet komponentu, která závisí na jiné komponentě, která ještě ani neexistuje!

Je tedy velmi žádoucí odlišovat jednotkové testy od integračních. Zároveň je dobré využívat oba tyto typy testů, protože každý se hodí na něco jiného a odhalí nám jiné typy chyb. Pokud bychom psali pouze jednotkové testy, tak třídy by samy o sobě fungovaly, ale celá aplikace dohromady by nemusela fungovat tak, jak si myslíme, protože jsme neotestovali komunikaci jednotek.

Přidat komentář