Testovací data pro E2E testy: jak dosáhnout nezávislých a opakovatelných běhů
End-to-end (E2E) test ověřuje celou uživatelskou cestu přes rozhraní a propojené části systému. I dobře napsaný scénář však selže, pokud očekává objednávku, kterou jiný test změnil, nebo účet, jenž zůstal zablokovaný po předchozím běhu. Spolehlivá sada proto potřebuje návrh testovacích dat stejně jako návrh samotných kroků.
Cílem není po každém testu bezpodmínečně vymazat celou databázi. Cílem je, aby každý scénář znal svůj počáteční stav, nevytvářel konflikt se souběžným testem a při selhání zanechal srozumitelnou stopu.
Proč čistý prohlížeč nestačí
Moderní testovací nástroj může pro každý test otevřít nový profil bez cookies a lokálního úložiště. Playwright například používá pro jednotlivé testy izolované browser contexty. Tato izolace však končí na straně prohlížeče. Dvě relace stále mohou měnit stejného uživatele, košík, skladovou položku nebo nastavení ve společném backendu.
Problém se často skrývá, dokud sada běží sériově. Po zapnutí paralelních workerů oba testy vytvoří zákazníka se stejným e-mailem, spotřebují stejný kupón nebo jeden smaže záznam druhému. Pořadí testovacích souborů navíc nemá být smlouvou o datech. Scénář, který projde pouze po „přípravném“ scénáři, není nezávislý.
Realistický příklad: dva checkouty a jeden kupón
Sada obsahuje test úspěšné objednávky a test zamítnutí neplatné platby. Oba používají zákazníka buyer@example.test, produkt SKU-100 s posledními dvěma kusy a jednorázový kupón E2E10. Při sériovém běhu setup obnoví stav před každým testem a vše vypadá spolehlivě. Při dvou workerech oba scénáře načtou stejnou zásobu a pokusí se uplatnit tentýž kupón.
První test sníží sklad a spotřebuje kupón. Druhý pak může selhat na jiném místě, než měl: místo zamítnuté platby vidí neplatný kupón nebo nedostupný produkt. Retry po skončení prvního workeru projde, takže report označí scénář jako flaky. Příčinou však není pomalé UI, ale datová smlouva, která neuvedla, že kupón a sklad jsou měnitelné zdroje.
Oprava oddělí tři druhy dat. Katalog produktu může zůstat společný pouze ke čtení, ale každý worker dostane vlastní skladovou položku nebo rezervaci. Factory vytvoří kupón s ID běhu a testovací účet patří konkrétnímu workeru. Cleanup neboli úklid dat po testu vyhledá jen záznamy s daným ID. Když test selže, identifikátor v objednávce spojí databázový stav s konkrétním CI reportem.
Definujte datovou smlouvu každého scénáře
Ke kritickému E2E testu si zapište čtyři věci:
- Výchozí stav: jaké účty, role, produkty a nastavení musí najít.
- Vytvořené změny: které záznamy test přidá, upraví nebo odešle do externího systému.
- Rozsah vlastnictví: která data patří pouze tomuto testu, workeru nebo celému běhu.
- Ukončení životního cyklu: co se smaže, resetuje, nechá expirovat nebo záměrně zachová pro diagnostiku.
Tato krátká smlouva odhalí skrytý předpoklad dříve než náhodný pád. Zároveň určí, zda test potřebuje nový účet pro každý scénář, účet pro jeden worker nebo stabilní referenční katalog pouze ke čtení.
Seed, factory nebo příprava přes API
Seed je předem definovaný základ dat, který vzniká při vytvoření prostředí nebo databáze. Hodí se pro malé množství stabilních referencí, například země, role a produkty určené pouze ke čtení. Seed musí být verzovaný spolu se schématem a opakovatelný. Pokud jej testy průběžně mění, přestává být spolehlivým základem.
Factory vytvoří jen údaje potřebné pro konkrétní test: zákazníka s danou rolí, produkt s dostupnou zásobou nebo objednávku v požadovaném stavu. Výchozí hodnoty udržujte realistické, ale scénář ať explicitně uvede vlastnosti, které ověřuje. Příliš univerzální factory s desítkami voleb může skrýt, jaký stav skutečně vznikl.
Příprava přes API bývá rychlejší a přesnější než proklikávání uživatelského rozhraní. Playwright například dokumentuje použití APIRequestContext k přípravě serverového stavu před otevřením stránky. UI používejte pro setup tehdy, když je vytvoření daných údajů samo předmětem testu. Jinak může chyba v dlouhém přípravném formuláři překrýt to, co měl scénář ověřovat.
Přímý zápis do databáze může být vhodný v kontrolovaném testovacím prostředí, ale snadno obejde validační pravidla, události a cache aplikace. Pokud jej používáte, držte ho za jasným pomocným rozhraním, verzujte ho se schématem a ověřte, že vytváří stav, který by aplikace dokázala vytvořit platnou cestou.
Jedinečné a zároveň dohledatelné identifikátory
E-mail, uživatelské jméno či číslo objednávky skládejte z názvu scénáře, ID celého běhu a indexu workera. Náhodná přípona může zabránit kolizi, ale sama o sobě ztěžuje pátrání. Identifikátor jako checkout-refund_run842_w3 ukáže, kdo záznam vytvořil a ke kterému reportu patří.
Playwright poskytuje workerům samostatné indexy a v dokumentaci k paralelnímu běhu ukazuje jejich využití k oddělení uživatelů. Stejný princip platí i pro jiné runnery: každý souběžný proces potřebuje vlastní měnitelný stav. Sdílet lze pouze data, která testy nemění.
ID běhu ukládejte do značky nebo metadat záznamu, pokud to doména umožňuje. Cleanup pak může cílit na přesnou skupinu místo nebezpečného pravidla „smaž vše, co vypadá testovací“.
Cleanup je součást návrhu, ne pojistka na konci
Úklid spouštějte v závěrečné fázi testu (teardown) nebo pomocí fixture, která řídí přípravu a úklid, i tehdy, když hlavní ověření selže. Jeho výsledek reportujte samostatně, aby chyba cleanupu nepřepsala původní důvod pádu. Před smazáním si uchovejte identifikátory a diagnostiku potřebné k reprodukci.
Úplný cleanup není vždy možný ani vhodný. Auditní záznamy mohou být neměnné, asynchronní úloha může záznam stále používat a e-mail, fakturu či webhook odeslaný cizí službě nelze vzít zpět. V takových případech použijte odděleného testovacího tenanta, tedy samostatný prostor pro testovacího zákazníka, řízenou náhradu externí služby (stub), časově omezená data nebo pravidelný reset celého prostředí. Scénář musí vědět, který vedlejší účinek zůstává.
Pokud má cleanup široká oprávnění, jeho chyba může poškodit cizí testy. Omezte jej na jednoznačný prefix nebo ID aktuálního běhu a nepřipojujte ho k produkční databázi. U osobních údajů řešte minimalizaci, přístup a dobu uchování; strategické hranice vysvětluje článek testovací data a GDPR.
Praktický minimální model
Pro většinu sad funguje kombinace: verzovaný seed pro neměnné reference, factory nebo API pro měnitelná data, jedinečný prefix pro každý běh a cílený teardown. Jeden test musí projít samostatně, v jiném pořadí i souběžně. Pokud to nedokáže, dočasné spuštění s jedním workerem pomůže potvrdit konflikt, ale nenahrazuje izolaci.
Testovací factory funkce a cleanup kód prověřte alespoň malými integračními kontrolami. Chybná příprava může vytvořit nereálný stav a chybný cleanup může postupně zaplnit prostředí, přestože samotné E2E scénáře vypadají zeleně.
Jak ověřit, že datový model funguje
Nejprve spusťte jeden scénář samostatně na čistém prostředí. Nesmí potřebovat jiný test ani ručně vytvořený záznam. Poté jej spusťte opakovaně bez resetu celé databáze; jedinečné identifikátory a cílený cleanup musí zabránit kolizím. Třetím krokem je souběh se stejným počtem workerů, jaký plánujete v CI.
Kontrola nemá skončit zeleným reportem. Po běhu vyhledejte data podle ID: zůstat mají pouze ta, která datová smlouva záměrně zachovává. Ověřte, že cleanup nezasáhl reference ani záznamy jiného workeru. Při selhání cleanupu musí report obsahovat seznam neodstraněných ID, aby je bylo možné bezpečně vyčistit později.
Pravidelně proveďte také negativní zkoušku. Úmyslně přerušte test po vytvoření objednávky, simulujte nedostupné API během teardownu nebo ukončete worker. Zjistíte, zda se cleanup spustí, zda dokáže pokračovat idempotentně a zda pravidelná údržba odstraní osiřelá data. Idempotentní krok lze bezpečně zopakovat bez dalšího nežádoucího účinku.
Sledujte počet konfliktů jedinečnosti, selhání přípravy (setupu) a záznamů starších než dohodnutá lhůta. Nulová hodnota v jednom běhu není zárukou, ale trend ukáže, zda se prostředí postupně znečišťuje. Pokud roste pouze čas přípravy, zvažte data sdílená jen v rámci jednoho workeru pro drahé zdroje, ale zachovejte oddělení mezi workery a reset stavu, který test mění.
Co tím získáte
Nezávislá data snižují náhodné pády, umožňují bezpečný paralelní běh a zkracují diagnostiku. Z identifikátoru je jasné, který test záznam vytvořil, a z datové smlouvy je jasné, co má po běhu zůstat. Sada tak poskytuje porovnatelný výsledek místo výsledku závislého na historii prostředí.
Další krok
Vyberte jeden často padající E2E scénář a sepište jeho výchozí stav, změny, vlastnictví a cleanup. Nahraďte společný účet vlastním identifikátorem běhu a připravte stav přes cílené API nebo factory. Potom test spusťte samostatně, desetkrát za sebou a souběžně s jeho kopií; každý režim odhalí jiný typ skryté závislosti.