Před nějakou dobou jsem se zúčastnil QA meetupu s názvem Proč nemít rád End to End testování. Téma je mi blízké i vzhledem k tomu, že jsem působil i jako tester. Navíc je to ve světě testingu vděčné téma k diskusi a i v Heurece se potýkáme ohledně End to End (E2E) testů s klasickýmy problémy, které tyto testy přinášejí.
Na meetupu Lukáš Vitala z Y Softu prezentoval case study, která popisovala evoluci testů u nich ve firmě - od rozsáhlých sad manuálních regresních testů se všemi jejich neduhy až k celistvé a zautomatizované release pipeline. Po prezentaci pak následovala neméně zajímavá debata, po které by si nezasvěcený posluchač mohl klást otázku “Jak z End to End testů nezešílet?”. Na tuhle otázku bych se rád pokusil ve článku odpovědět.
Protože budu zmiňovat konkrétní příklady od nás z Heureky, alespoň ve stručnosti nastíním, jak fungují naše produktovo-vývojové týmy:
Každý tým vlastní několik “projektů”, ze kterých se Heureka skládá. Například několik oddělených frontendů, které řeší zejména zobrazení dat:
- Homepage
- Sekce a kategorie
- Atd.
Frontendové projekty pak čerpají data z backendu - z dalších služeb, které mohou vlastnit jiné týmy, tzn. například různé služby poskytující data o produktech, obchodech atd.
Každý takový projekt je tedy nějakým týmem vlastněn - je v jeho kompetenci jej rozvíjet a současně má za něj plnou odpovědnost - od produktového a technického návrhu přes vývoj, testování až k vlastnímu provozu v duchu DevOps. Týmy jsou složeny z několika vývojářů, produkťáka a scrum mastera. Dedikované testery v Heurece nemáme a vše se odehrává přímo v týmech.
K poctivému pohledu na E2E testy si potřebujeme zodpovědět následující otázky:
- K čemu mají testy sloužit?
- Na jakých úrovních a do jaké míry kód testy pokrývat?
- Má vůbec smysl automatizovat? Jakou technologii na automatizace testů použít?
K čemu mají testy sloužit?
Čím lépe si na tuto otázku odpovíme, tím větší šance je, že zvolíme přístup k testům, který bude ve výsledku užitečný.
Pěkný je například pohled Gojko Adzice, který v rozhovoru pro podcast “You’re testing what?” říká:
“Automatické testy by nám měly pomáhat vyvíjet rychleji díky tomu, že nám poskytnou jistotu, že můžeme přestat testovat v okamžiku, kdy už potřebujeme přestat testovat.”
Pokud testy vývoj naopak komplikují a zpomalují, měli bychom se zamyslet, jestli neděláme něco špatně. To samozřejmě výsostně platí i v případě E2E testů.
Pěkně to shrnul také Lukáš Vitala na meetupu - rozhodně není efektivní, pokud tester většinu času řeší, jestli svým testům může věřit, místo toho, aby se na ně mohl spolehnout.
Testy by nám tedy měly dávat důvěru v bezchybnost kódu a současně nás nebrzdit ve vývoji.
Dobré testy:
- musí být užitečné: tzn. dávat zpětnou vazbu
- dostatečně rychle
- tak, abychom se byli schopni rychle rozhodnout, jestli produkt může do produkce
- tak, abychom byli schopni případnou chybu lokalizovat co nejrychleji
- musí být efektivní:
- dostatečně spolehlivé
- dobře udržovatelné, aby se “vyplatily” a nebrzdily vývoj
Jak jsou na tom z těchto hledisek E2E testy?
- jsou to ty nejpomalejší ze všech
- nejméně zužují prostor, kde došlo k chybě
- zahrnují nejvíce komponent, nejsložitější prostředí a nejkřehčí testovací technologie
- není triviální je psát dobře udržovatelné a spolehlivé
To vše mluví proti jejich rychlosti, spolehlivosti a ve výsledku vypovídací hodnotě.
Na jakých úrovních a do jaké míry kód testy tedy pokrývat?
Určitě souhlasím s tím, co zaznělo na meetup, a to, že je nutné mít testy na více úrovních - pokrýt i ty mezi unit a E2E testy. Výhodou je, že na čím nižší úrovni se problém zachytí, tím menší je oblast, kterou musíme zkoumat.
Další úrovně, které Lukáš v prezentaci vypíchnul:
- testy na úrovni jednotlivých komponent - kdy se komponentou myslí například běžící API
- testy integrační, testující komunikaci mezi komponentami, užitečné pro odhalování chyb v architektuře
Tento přístup odpovídá konceptu testovací pyramidy, například podle Mikea Cohna nebo Martina Fowlera. Současně je potřeba mít pro každou úroveň na paměti nejen její benefity, ale i její omezení. I proto jako obecné doporučení platí, že čím vyšší je úroveň a její komplexita, tím udržovat méně testů.
Příklad z Heureky
Na jednom projektu jsme potřebovali rychle pokrýt testy, ale jeho architektura nám neumožňovala pro ně efektivně mockovat data. Bylo proto nejjednodušší napsat dostatečně chytré a robustní E2E testy, ale ani tak jsme se nevyhnuli důsledkům typickým pro tento typ testů. Jak jejich počet vzrůstal. Přes veškerou snahu padaly už příliš často a vždy bylo nutné zkoumat, jestli je problém v nich, infrastruktuře nebo v datech, které byly mimo kontrolu našeho týmu.
Nakonec jsme se rozhodli upravit architekturu, abychom mohli data snadno namockovat a v budoucnu dostat nejdůležitější testy na tomto projektu pod plnou kontrolu, a to spolu s možností dostat testy na nižší úroveň. Počet E2E testů pak bude možné zredukovat na nejnutnější minimum.
Má vůbec smysl automatizovat? Jakou technologii na automatizace testů použít?
Má smysl investovat čas a prostředky do automatizace testů? V ideálním světě by se člověk snažil spočítat tzv. ROI (return of investment), tedy jestli se mu taková investice vyplatí. Pro začátek ale určitě lze udělat následující jednoduchou úvahu:
- Budeme potřebovat testovat často a opakovaně ty samé věci?
- Pokud ano, automatizace se nejspíš vyplatí - pokud na ni nepůjdeme vyloženě špatně.
- Pokud se jedná o jednorázový proof-of-concept, který nebudeme dále rozvíjet, tak se automatické testy nejspíš nevyplatí.
- Máme know-how a zdroje?
- Pokud ano, odpověď “ano” je poměrně jednoduchá.
- Pokud ne, je třeba počítat s tím, že získat know-how bude něco stát a že k automatizací je potřeba i dostupná a dostatečně dimenzovaná infrastruktura. V případě, že si navíc zvolíme placené nástroje, zvýší se nám náklady.
A co technologie? Nástrojů pro automatizaci je již poměrně dost, není vždy jednoduché si vybrat ten vhodný pro náš projekt a tým. Ve výsledku to vždy bude individuální volba, která závisí na konkrétním případě použití a kdo jej bude používat.
Budeme se snažit vybrat nástroj, který nám:
- smysluplně zapadne do našeho technologického stacku
- bude dávat smysl z pohledu nákladů - cena, čas potřebný k jeho ovládnutí a implementace
- bude splňovat naše technologické požadavky na testy - je potřeba dát pozor na technologická omezení nástrojů, která například Cypress ve své dokumentaci uvádí v sekci o Trade-offs.
Příklad z Heureky
Na projektu zmíněném výše se ukázalo, že námi vybraná technologie nebyla ta pravá.
Když jsem přišel do týmu, měl jsem největší zkušenosti s kombinací Python + Selenium, takže E2E testy jsme postavili v tomto duchu. Kompletně dockerizované, spouštěné v Gitlab pipeline proti Kubernetes deploymentu. Důsledně jsme používali page object model s abstrakcemi na těch správných úrovních, což se nám nesčetněkrát vyplatilo vzhledem k neustálému vývoji aplikace. Dlouhodobý plán byl, že testy bude časem schopný psát kterýkoliv člen týmu.
Zpočátku vše fungovalo krásně. Vzhledem k tomu, že jsme psali projekty i v Pythonu, byly testy zcela v rámci našeho technologického stacku.
Postupem ale došlo k následujícímu:
- V dennodenním presu jsme sklouzávali k tomu, že testy jsem updatoval stále nejčastěji já, abychom neztráceli čas. Nikdy nebyl dostatek času, aby se kolegové tuto technologii s mojí pomocí v klidu doučili a sami si s ní experimentovali.
- I proto kolegům Selenium k srdci příliš nepřirostlo, což není až tak udivující, má své mouchy a nedává kdovíjaký komfort při vývoji. Potvrdilo se mi přitom, že Selenium je mindsetem bližší testerům, narozdíl od Cypressu, který myslí i na vývojáře.
- Celý tým se technologicky výrazně posunul k JavaScriptu a TypeScriptu - Python projekty jsou porůznu nahrazovány a ve výsledku se celý tým domluvil, že primárním jazykem týmu bude JavaScript/TypeScript.
Nakonec jsme se v týmu rozhodli následovně:
- Python + Selenium opustíme a půjdeme cestou Cypressu, který je pro nás aktuálně technicky bližší a pro vývojáře stravitelnější.
- Na nových projektech budeme začínat rovnou Cypressem.
Cypress jako nástroj pro browser testy používáme na čím dál více projektech a děláme vše pro to, abychom mohli dosavadní Selenium nahradit. Souběžně přitom ještě sledujeme další trendy - aktuálně například rozvíjíme pilot visual testingu přímo v Gitlab pipeline.
Jak tedy z E2E testů nezešílet?
E2E testy mají své místo, protože se vždy nakonec najde situace, kdy chceme mít krytá záda testem, ale už nelze testovat jinak. Jako o každý nástroj i o tento se ale dá “pořezat”, pokud se nepoužije správně. Zrovna v tomto případě je nebezpečí solidně velké, proto je třeba ho používat opravdu s rozmyslem. Zejména netestovat E2E věci, které lze dobře zkontrolovat na nižších úrovních. Ideálně přitom aplikaci stavět od začátku rovnou tak, aby bylo možné na těchto nižších úrovních smysluplně testovat. A pokud to nelze, klidně i zvážit refactoring, který to umožní.
Neméně důležité je vybrat technologii, která týmu sedne. Nám se to napoprvé nepovedlo. Přestože naše Selenium testy ve své době rozhodně splnily svůj účel, jsou už nepochybně za zenitem a bude nás stát ještě dost úsilí je nahradit novými Cypress testy.
-----------------------------------
Pokud vám při psaní kódu záleží na kvalitě, testy berete jako samozřejmou součást vývoje a měli byste chuť to zkusit u nás v Heurece, ozvěte se nám na některou z aktuálně otevřených pozic ve vývoji.