Oprava testovací sady

Testy závislé na pořadí: jak je najít a opravit

Test samostatně projde, ale v celé sadě selže. Jindy se pokazí pouze po konkrétním scénáři nebo po zapnutí paralelního běhu. Za takovým výsledkem často není náhoda, ale skrytá vazba mezi testy. Najít ji znamená oddělit dvě podobné příčiny: závislost na pořadí a kolizi při souběhu.

Když předchozí test změní výsledek dalšího

Test je závislý na pořadí, pokud jeho výsledek ovlivní stav po předchozím testu. Může očekávat, že jiný scénář nejprve vytvoří uživatele, nebo naopak zdědí účet, košík či globální nastavení, které předchůdce změnil. Problém se projeví i při jediném workeru. Stačí změnit pořadí.

Typickým příznakem je scénář, který samostatně projde na čistém prostředí, ale selže po jednom konkrétním testu. Objevit se může i opačný případ. Scénář projde pouze po „přípravném“ testu, protože si sám nevytvoří údaje, které potřebuje.

Taková vazba zhoršuje diagnostiku. Selhání se zobrazí ve druhém testu, přestože příčinu vytvořil první. Při spuštění jednoho scénáře v editoru chyba zmizí a tým začne podezírat CI nebo časování.

Závislost na pořadí není totéž jako kolize při souběhu

Při kolizi mění dva testy stejný zdroj ve stejném čase. Sériově mohou projít v libovolném pořadí, protože každý před použitím obnoví stav. Při paralelním běhu se však jejich kroky překryjí. Jeden worker smaže soubor, obsadí pevný port nebo upraví účet právě ve chvíli, kdy jej druhý používá.

Obě chyby mají společný základ, kterým je sdílený měnitelný stav. Diagnostika se však liší. Změna pořadí odhalí stav přenesený z ukončeného testu. Změna počtu workerů odhalí překryv dvou stále běžících testů. Sériový běh proto není automaticky oprava. Může kolizi jen skrýt.

Playwright ve výchozím nastavení spouští testovací soubory paralelně a testy v jednom souboru v pořadí deklarace. Jeho dokumentace současně doporučuje testy izolovat namísto vytváření vzájemně závislých sériových skupin. Pořadí mezi soubory navíc není při paralelním běhu zaručeno. Podrobnosti uvádí dokumentace k paralelnímu provádění v Playwrightu.

Příklad se společným účtem a košíkem

Představte si dva E2E scénáře, které používají účet e2e-shopper@example.test. Test A košík vyprázdní, přidá stolní lampu a ověří výslednou cenu. Po skončení položku neodstraní. Test B se přihlásí ke stejnému účtu a ověří, že prázdný košík zobrazuje odkaz na katalog.

Test B samostatně projde. Pokud však běží po testu A, najde v košíku lampu a selže. Opačné pořadí projde, protože test A košík na začátku vyčistí. Jde o závislost na pořadí. Stav z dokončeného testu A pronikl do testu B.

Po úpravě si test B na začátku také vyprázdní košík a poté přidá kancelářskou židli. Oba testy sériově projdou v libovolném pořadí. Při souběhu může B vyprázdnit košík poté, co A vložil lampu. Test A pak nevidí očekávanou položku nebo test B najde oba produkty. To je kolize při souběhu. Samotné změny pořadí ji nemusí vyvolat.

Stejný vzorec vzniká u sdíleného uživatele, objednávky, kupónu, databázového záznamu, adresáře s exportem nebo pevného portu lokální služby.

Diagnostická matice místo náhodných opakování

Před experimentem zachovejte commit, sestavení aplikace, konfiguraci, data a verze nástrojů. Potom měňte pouze způsob spuštění. Krátká matice pomůže převést neurčitý pád na konkrétní hypotézu.

Spuštění Co sledujete Pravděpodobný závěr
Podezřelý test samostatně ve známém stavu Zda potřebuje cizí přípravu nebo už selhává sám Selhání ukazuje na vlastní setup, aplikaci nebo prostředí
Podezřelý test hned po možném předchůdci Zda stav po prvním testu změní výsledek druhého Opakovatelný rozdíl podporuje závislost na pořadí
Stejná dvojice v opačném pořadí Zda problém sleduje konkrétní posloupnost Jedno chybné pořadí ukazuje, kdo stav zanechává nebo očekává
Celá cílová skupina sériově Zda selhání zmizí bez časového překryvu Zlepšení je stopa ke kolizi, ne hotová oprava
Stejná skupina s plánovaným souběhem Zda se testy střetávají o účet, soubor, port nebo záznam Pád pouze při souběhu podporuje hypotézu o kolizi

Ke každému běhu uložte první chybu a identifikátory použitých dat. U košíku zaznamenejte účet, ID běhu, worker a položky před každým rozhodujícím krokem. Snímek stránky bez těchto údajů ukáže projev, ne vlastníka změny.

Měňte jednu podmínku

Pokud současně změníte pořadí, počet workerů, účet a cleanup, zelený výsledek nic přesného nepotvrdí. Začněte jednou větou, například: „Test B selže, když test A nechá položku ve společném košíku.“ Poté nechte oba testy i aplikaci beze změn a přehoďte pouze pořadí.

U hypotézy o souběhu ponechte data i pořadí a změňte pouze počet workerů. Chcete-li potvrdit konflikt účtu, v dalším experimentu zachovejte cílový souběh a přidělte jednomu testu jiný účet. Výsledek by měl sledovat právě tuto jednu podmínku. Tento postup navazuje na širší diagnostiku situace, kdy testy lokálně projdou, ale v CI selhávají.

Každý test si připraví vlastní počáteční stav

Trvalá oprava začíná explicitní přípravou. Test B nemá předpokládat prázdný košík ani čekat, že jej vyčistí test A. Má si vytvořit zákazníka s prázdným košíkem nebo stav nastavit přes cílené API či fixture. Pokud je vytvoření košíku předmětem testu, použijte uživatelské rozhraní. V ostatních případech bývá přímá příprava přes testovací rozhraní kratší a přesnější.

Měnitelná data přiřaďte testu nebo workeru. Identifikátor může obsahovat ID běhu, název scénáře a index workeru, aby jej bylo možné najít v databázi i reportu. Stabilní katalog lze sdílet, pokud jej testy pouze čtou. Účet, košík nebo kupón, který scénář mění, společný zůstat nemá. Praktický návrh rozebírají testovací data pro E2E testy.

Také Selenium doporučuje nesdílet testovací data, odstranit staré údaje, které by mohl převzít další test, a vytvořit pro každý test samostatnou instanci WebDriveru. Vlastní data přitom neznamenají kopii celé databáze pro každý scénář. Oddělte pouze stav, který se mění.

Izolujte prohlížeč, soubory i porty

Nový účet nevyřeší cookies po předchozím přihlášení. Playwright vytváří pro každý test izolovaný browser context, tedy profil podobný anonymnímu oknu s vlastními cookies, lokálním úložištěm a úložištěm relace. Pokud si však tým ručně ponechá jednu stránku nebo context pro více testů, tuto hranici obejde. Čistý context zároveň neoddělí údaje ve společném backendu.

U Selenia používejte nový driver pro každý test a po běhu jej ukončete i při selhání. Dokumentace doporučuje čerstvý prohlížeč pro každý test, přičemž nová instance běžného ovladače ve výchozím nastavení začíná s novým uživatelským profilem.

Stejnou hranici potřebují zdroje mimo prohlížeč. Export ukládejte do adresáře konkrétního testu, ne do společného downloads/report.csv. Dočasný soubor pojmenujte identifikátorem běhu. Lokálním serverům přidělte port pomocí koordinovaného mechanismu nebo z rozsahu vyhrazeného pro daný běh a worker. Všechny procesy se nemohou spoléhat na stejný pevný port.

Cleanup je pojistka, ne předpoklad dalšího testu

Cleanup spouštějte i po neúspěchu a omezte jej na záznamy, které vlastní daný test nebo běh. Měl by se dát bezpečně zopakovat a jeho chyba nesmí překrýt původní selhání. Před smazáním uchovejte ID potřebná pro diagnostiku.

Následující test se přesto nesmí spoléhat na to, že cleanup předchůdce proběhl. Worker může být ukončen, služba může během teardownu přestat odpovídat a některé účinky, například odeslaný e-mail, nelze vrátit. Vlastní explicitní setup je první obranná vrstva. Cílený cleanup chrání prostředí před hromaděním dat.

Kdy sekvenční workflow patří do jednoho testu

Ne každá posloupnost kroků je chybná. Uživatel může vytvořit objednávku, zaplatit ji a poté požádat o vrácení peněz. Pokud je předmětem ověření celý tento workflow a každý krok potřebuje výsledek předchozího, zapište jej jako jeden test s jedním příběhem, stavem a výsledkem.

Rozdělení takové cesty do tří testů vytvoří řetěz, v němž nelze druhou část spolehlivě spustit samostatně. Selhání platby navíc znehodnotí výsledek testu vrácení. Kroky můžete přesunout do čitelných pomocných funkcí, ale vlastníkem životního cyklu zůstane jeden test. Samostatné testy zachovejte pro případy, které si dokážou připravit zaplacenou objednávku bez závislosti na jiném scénáři.

Jak ověřit opravu

Opravený test spusťte samostatně ve známém stavu, po původním předchůdci a v opačném pořadí. Potom zopakujte cílovou skupinu sériově i se stejným počtem workerů, jaký používá CI. Neověřujete jen zelený výsledek. Zkontrolujte také, zda každý test použil vlastní ID, adresář, port a relaci prohlížeče a zda po běhu zůstala pouze záměrně zachovaná data.

Původní chybnou podmínku si ponechte jako reprodukční experiment. Pokud dvojice se společným účtem stále spolehlivě selže a dvojice s oddělenými účty při stejném souběhu projde, je příčina podstatně lépe doložená než jedním úspěšným retry. U širší sady sledujte výsledky prvních pokusů a selhání seskupujte. Postup popisuje článek jak měřit flaky testy.

Co tím získáte

Nezávislé testy lze spustit jednotlivě, v jiném pořadí i paralelně. Výsledek pak popisuje chování aplikace ve známém stavu, ne historii košíku či adresáře po jiném scénáři. Tým může zkrátit běh bezpečným souběhem a při selhání hledá příčinu v menším prostoru.

Další krok

Vyberte dvojici, u níž jeden test samostatně projde a v sadě selhává. Projděte pět režimů z diagnostické matice a zapište příčinu jako „podmínka, mechanismus, projev“. Poté oddělte měnitelná data a zopakujte původní chybnou podmínku. Pokud podobné vazby zasahují větší část sady, ozvěte se nám. Pomůžeme je změřit, opravit a vrátit testy do pravidelného běhu v CI.

Související témata

Mohlo by vás také zajímat

Spolehlivé výsledky jsou důležitější než počet testů

Změříme nestabilitu, prověříme pravděpodobné příčiny náhodných selhání a sadu stabilizujeme v dohodnutém rozsahu.