Testovacia stratégia a audit

Unit, integračné a end-to-end testy: aký je rozdiel

Unit, integračný a end-to-end test sa nelíšia tým, ktorý je „lepší“, ale najmä šírkou hranice a skutočnými časťami zapojenými do behu. Čím je test užší, tým býva spätná väzba rýchlejšia a chyba sa ľahšie lokalizuje; čím je širší, tým viac reálnych prepojení môže potvrdiť, ale tým viac príčin môže mať zlyhanie. Presné rozlíšenie pomáha rozdeliť kontroly bez slepých miest a bez drahého opakovania rovnakých kombinácií na každej úrovni.

Prečo sa názvy v tímoch rozchádzajú

„Unit“ nemusí znamenať jednu metódu a „integračný“ nemusí znamenať celý systém. Pre jeden tím je test služby s reálnou databázou integračný; iný ho volá komponentový a názov integrácia si necháva pre komunikáciu medzi dvoma službami. Ani používateľské rozhranie (UI) a end-to-end (E2E) nie sú synonymá: UI možno testovať izolovane a celý koncový tok možno spustiť cez API.

Aj Practical Test Pyramid upozorňuje, že pomenovania vrstiev nie sú univerzálne a že konzistentná definícia v tíme je dôležitejšia než boj o jeden slovník. Preto sa pri každom type pýtajte na tri konkrétne veci:

  1. Čo je predmetom testu a kadiaľ doň test vstupuje?
  2. Ktoré spolupracujúce časti sú reálne a ktoré nahradené?
  3. Aký pozorovateľný výsledok test potvrdzuje?

Takýto opis odhalí skutočný rozsah aj vtedy, keď dva tímy používajú rovnaký názov odlišne. V širšej taxonómii ide o os úrovne; druhy testovania softvéru možno súčasne triediť aj podľa cieľa, spôsobu a času spustenia.

Jeden e-shop, päť možných hraníc

Použime realistický príklad. E-shop má kalkulačku ceny, ktorá pracuje s cenou položky, DPH, množstvom a kupónom. Košíkový komponent tieto pravidlá používa a pripraví požiadavku. Objednávková služba cez API uloží objednávku do databázy, požiada sklad o rezerváciu a platobnú bránu o vytvorenie platby. Webové UI umožní zákazníkovi prejsť checkoutom.

Požiadavka hovorí: kupón LETO10 zníži cenu oprávnených položiek o 10 %, zľava sa uplatní pred výpočtom DPH a výsledná suma sa zaokrúhli podľa dohodnutého pravidla. Po úspešnom odoslaní musí vzniknúť objednávka s rovnakou sumou, sklad musí rezervovať množstvo a zákazník sa má dostať na platbu.

Jedna požiadavka tak vytvára viac odlišných otázok. Vypočíta pravidlo všetky hraničné prípady? Používa košík pravidlo správne? Zapíše databázový adaptér presnú sumu? Rozumejú si objednávka a sklad? Dokáže zákazník dokončiť cestu v nasadenom systéme? Každá otázka má prirodzenú testovaciu hranicu.

Unit test: malé správanie v kontrolovaných podmienkach

Unit, teda jednotkový test, overuje malú jednotku správania bez skutočnej siete, databázy, fronty správ či iného pomalého alebo nedeterministického vonkajšieho systému. Jednotkou môže byť funkcia, trieda alebo malá skupina úzko súvisiacich objektov. Hranica nie je daná počtom riadkov kódu, ale tým, čo tím považuje za jedno ucelené správanie.

V našom príklade zavolá test kalkulačku s cenou 100 eur, oprávneným kupónom a konkrétnou sadzbou DPH. Overí presnú medzisumu, daň a konečnú cenu. Ďalšie prípady pokryjú neplatný kupón, nulové množstvo, hranicu platnosti a zaokrúhľovanie. Hodiny možno nahradiť riadeným zdrojom času, aby test nebol závislý od dnešného dátumu.

Unit test má povedať, že pravidlo je nesprávne, nie že sa nepodarilo naštartovať databázu. Preto býva rýchly, opakovateľný a vhodný na veľa kombinácií. Jeho limit je rovnako dôležitý: neoveruje mapovanie JSON, databázový typ pre sumu, konfiguráciu DPH ani to, či UI posiela kupón do správneho poľa.

Testujte pozorovateľné správanie cez verejnú hranicu jednotky. Ak test predpisuje poradie každého interného volania, neškodná refaktorizácia ho môže rozbiť bez zmeny výsledku pre používateľa.

Komponentový test: celý modul, nie celý ekosystém

Komponentový test spustí väčší celok a pristupuje k nemu cez jeho verejné rozhranie. Pri frontendovom košíku môže vykresliť celý komponent, zadať kupón a overiť zobrazenú sumu, zatiaľ čo objednávkové API nahradí riadenou odpoveďou. Pri backendovej službe môže spustiť aplikáciu cez HTTP s reálnou internou logikou, ale sklad a platbu ponechať ako simulácie.

Táto vrstva odhaľuje chyby v prepojení vnútorných častí komponentu: formulár síce načíta kupón, ale stav neodovzdá kalkulačke; alebo controller nesprávne mapuje požiadavku do doménového modelu. Zostáva užšia než test celého nasadeného produktu, takže sa dá pripraviť cielenejšie a zlyhanie má menší okruh príčin.

Slovo komponent treba v projekte definovať. Môže znamenať vizuálny prvok, balík aj samostatne nasaditeľnú službu. Bez uvedenia hranice názov sám nehovorí, akú istotu test poskytuje.

Integračný test: dôkaz na skutočnej hranici

Integračný test overuje, že si dve alebo viaceré reálne časti správne odovzdajú dáta a správanie. Úzky integračný test môže zapojiť objednávkovú službu a databázu: po volaní repozitára overí sumu, menu, položky a stav uložený v skutočnej podporovanej databáze. Iný spojí producenta a reálny message broker, aby preveril názov témy, serializáciu a potvrdenie správy.

Širší integračný test môže spustiť objednávku aj testovaciu inštanciu skladu. Overí, že požiadavka na rezerváciu obsahuje správne identifikátory a že odpoveď „nedostatok zásob“ prejde do správneho stavu objednávky. Ak namiesto skladu použije simuláciu, testuje reálne HTTP správanie objednávkovej služby, nie kompatibilitu s aktuálnou implementáciou skladu.

Práve preto treba zapísať reálne závislosti. Databáza iného typu, než používa produkcia, môže byť vhodná pre časť rýchlych kontrol, no nemusí odhaliť rozdiely v typoch, transakciách alebo SQL. Naopak spustenie každej vzdialenej služby v každom teste predraží prípravu a zvýši počet nesúvisiacich zlyhaní.

Na hraniciach API dopĺňa integračné testy kontraktné testovanie. Kontrakt overuje zaznamenané očakávania klienta a poskytovateľa aj bez spoločného behu celého systému. Nenahrádza však test sieťovej konfigurácie, autentifikácie ani reálnych vedľajších účinkov.

Systémový a E2E test: celok a koncová cesta

Systémový test overuje zostavený produkt ako celok voči požiadavke. Môže ísť cez verejné API alebo UI a nemusí prechádzať ďalšími organizáciami či externými systémami. E2E test sleduje ucelený obchodný alebo používateľský tok cez relevantné hranice od spúšťača po konečný výsledok.

V e-shope môže E2E scenár vytvoriť produkt a kupón, otvoriť checkout, odoslať objednávku, prejsť testovacou platbou a overiť stav objednávky aj rezerváciu skladu. Ak platobná brána neposkytuje bezpečný sandbox, tím ju môže na kontrolovanom prostredí nahradiť. Test potom stále prechádza koncovou cestou vo vlastnom systéme, ale nepotvrdzuje reálnu integráciu s bránou; tú treba pokryť osobitným testom v povolených podmienkach.

E2E poskytuje dôkaz, že vybraná cesta drží pohromade, no zlyhanie môže spôsobiť UI, API, dáta, sieť, sklad, platba alebo prostredie. Preto cezeň neprechádzajte každú kombináciu kupónu. Jedna či niekoľko reprezentatívnych ciest potvrdí prepojenie, kým hraničné ceny patria nižšie. Praktický návrh nákupných ciest rozoberá automatizované testovanie e-shopu.

Akceptačný test nie je ďalšie synonymum. Hovorí, či je splnená podmienka prijatia; môže byť unit, komponentový, API aj E2E podľa toho, kde vznikne dostatočný dôkaz.

Test doubles, stuby, fake objekty a mocky

Test double je zastrešujúci názov pre náhradu produkčnej závislosti v teste. Terminológia knižníc sa líši, no užitočné je rozumieť úlohe náhrady:

Náhrady dávajú testu kontrolu nad chybami, časom a okrajovými stavmi. Zároveň vytvárajú riziko: test môže dokazovať iba to, že kód spolupracuje s našou predstavou cudzej služby. Čím dôležitejšia je hranica, tým viac treba simuláciu doplniť kontraktom alebo úzkym testom s reálnou implementáciou. Mockujte najmä vonkajšiu hranicu a nestavajte celý test na overovaní interných volaní, ktoré používateľ nepozoruje.

Porovnanie bez falošnej hierarchie

Typ Typická hranica Reálne závislosti Silná stránka Hlavný limit
Unit malé pravidlo alebo objekt spravidla bez siete a databázy rýchle kombinácie, presná diagnóza nepotvrdí prepojenia
Komponent modul, UI komponent alebo služba vnútro reálne, okolie často nahradené správanie celku cez verejnú hranicu pojem potrebuje lokálnu definíciu
Integrácia jedna alebo viac technických hraníc vybrané susedné časti reálne schémy, protokoly, databázy, konfigurácia náročnejšia príprava a izolácia
Systém zostavený produkt väčšina vlastných častí reálna požiadavky na správanie celku širší okruh príčin zlyhania
E2E celá vybraná cesta relevantný reťazec podľa deklarovaného rozsahu dôvera v kritický tok pomalší beh, dáta a diagnostika

Tabuľka neurčuje poradie dôležitosti. Unit test nezastúpi integráciu a E2E test nenahradí presné pokrytie pravidla. Každý odpovedá na inú otázku.

Ako zvoliť úroveň pre konkrétne riziko

Najprv napíšte tvrdenie, ktoré má test dokázať. Potom zvoľte najnižšiu hranicu, na ktorej je toto tvrdenie ešte pravdivé:

Potom odstráňte zbytočné opakovanie. Ak dvadsať kombinácií ceny spoľahlivo overujú unit testy, E2E stačí na reprezentatívnu cenu a správny prenos výsledku. Neodstraňujte však kontrolu hranice len preto, že pravidlo je pokryté nižšie.

Testovacia pyramída je v tomto užitočná ako smerovanie k viacerým úzkym a menšiemu počtu širokých testov, nie ako povinný pomer. Produkt s množstvom vlastnej logiky bude mať iné rozloženie než integračná aplikácia nad cudzími službami. Rozhodujte podľa architektúry, následku chyby, rýchlosti spätnej väzby a ceny údržby.

Na čo si dať pozor v reálnej sade

Veľa mockov môže vytvoriť rýchlu zelenú sadu, ktorá nevidí chybnú schému ani konfiguráciu. Veľa širokých testov zasa predĺži beh a pri spoločných dátach spôsobí nestabilitu. Test, ktorý prejde iba v určitom poradí, neposkytuje spoľahlivý dôkaz; pomáha, keď si scenár pripraví vlastné nezávislé testovacie dáta a po sebe ich kontrolovane uprace.

Pozor aj na nejasný report. Názov „checkout works“ nepovie, či zlyhal výpočet, HTTP kontrakt alebo zobrazenie. Zachovajte viditeľnú hranicu testu, vstup, očakávanie a diagnostické údaje. Keď širší test zlyhá, úzke testy majú pomôcť zúžiť príčinu, nie iba zopakovať rovnaký scenár iným nástrojom.

Rozdelenie behov prispôsobte spätnej väzbe. Rýchle unit a komponentové testy môžu bežať pri každej zmene, vybrané integrácie podľa dotknutej oblasti a malá kritická E2E sada po nasadení. Širšiu regresiu možno spustiť v ďalšej fáze; konkrétne možnosti sumarizuje článok o automatizovaných testoch v CI/CD.

Čo vhodné rozloženie prinesie

Vrstvená sada dáva tímu rýchlu informáciu o chybnom pravidle aj samostatný dôkaz, že kľúčové hranice fungujú. Znižuje potrebu prechádzať každú kombináciu cez drahú koncovú cestu a zároveň nepredstiera, že izolované mocky potvrdili reálne nasadenie. Pri zlyhaní sa ľahšie určí vlastník a pri zmene architektúry je viditeľné, ktoré hranice treba prehodnotiť.

Ďalší krok

Vyberte desať kritických scenárov a pri každom vypíšte jednotlivé tvrdenia, ktoré dnes testujete. Ku každému doplňte hranicu, reálne závislosti, použité test doubles, čas behu a typické príčiny zlyhania. Označte tvrdenia, ktoré sa zbytočne opakujú v E2E, aj hranice, ktoré nie sú reálne overené nikde. Následne presuňte jednu skupinu kombinácií na užšiu úroveň a ponechajte jeden reprezentatívny koncový scenár ako dôkaz celého toku.

Súvisiace témy

Mohlo by vás zaujímať

Ujasníme si, kde má automatizácia najväčší očakávaný prínos

Posúdime váš testovací proces a navrhneme, čo automatizovať, čo ponechať manuálne a čím začať.