Jak změřit pokrytí testy a kdy už je zbytečné
Častou chybou je testovat pouze šťastnou cestu. Věnujte čas i edge case: prázdné stavy, neplatné payloady, nebo akce, které nemění stav. Reducer by měl vždy vrátit aktuální stav pro neznámou akci, a to je snadné otestovat. Pro async akce otestujte, že se více volání chová správně – například že nedochází k race condition, když dvě akce běží paralelně. To lze simulovat pomocí Promise.all a kontroly pořadí dispatchovaných akcí.
Při měření se zaměřte na tři čísla: pokrytí řádků, pokrytí větví (branch) a pokrytí podmínek. Řádky ukazují, kolik kódu se vůbec provedlo, větve odhalují, zda testy procházejí oběma cestami u podmínek, a podmínky kontrolují kombinace logických výrazů. Většinou stačí sledovat pokrytí řádků a větví, protože pokrytí podmínek je už hodně detailní a pro běžné projekty může být zavádějící. Praktický postup: nastavte ve CI minimální hranici pokrytí, ale ne jako tvrdý limit, spíš jako varování. Pokud pokrytí klesne pod 80 % u kritických modulů, build by měl upozornit, ale ne blokovat – blokování vede k obcházení testů.
Typickou chybou je měřit pokrytí pouze u testů, které běží rychle, a ignorovat pomalé integrační testy. Pak čísla vypadají skvěle, ale reálné pokrytí je nízké. Dalším častým problémem je zapomínat na měření u nově napsaného kódu – pokud přidáte funkci bez testu, pokrytí klesá, ale nikdo si toho nevšimne, dokud není příliš pozdě. Řešení: automaticky generujte report po každém pushnutí do větve a posílejte ho do týmového chatu, aby byl vidět hned.
Praktický postup pro unit testy reducerů Pro testy reducerů si připravte testovací rámec, například Jest nebo Vitest. Vytvořte si pomocnou funkci, která vytvoří nový store s vaším reducerem. Pak jednoduše zavoláte dispatch s danou akcí a porovnáte výsledný stav s očekávaným objektem. Pozor na to, abyste testovali pouze jeden slice stavu, ne celý store, jinak se testy stanou křehkými a změny v jiné části aplikace je rozbijí. Typická chyba je testovat reducer tak, že měníte původní stav – vždy vytvářejte nový objekt pomocí spread operátoru nebo Immutable.js, jinak se testy chovají nepředvídatelně.
Největší úskalí při psaní prvních testů je práce s náhodnými hodnotami, s časem a s globálním stavem. Pokud funkce používá aktuální datum nebo náhodu, test může pokaždé vrátit jiný výsledek. Řešením je předat takové hodnoty jako parametry, případně použít injektování závislostí. Nikdy nespoléhejte na to, že test projde, i když jste ho spustili stokrát – pokud obsahuje náhodu, je to jen otázka času, kdy selže. Stejně tak se vyhněte testům, které mění soubory nebo databázi bez předchozího vyčištění. Test by měl být opakovatelný a měl by běžet stejně dobře na vašem počítači i na serveru.
Největší český problém je vztah k odhadům. Tým často vnímá odhady jako závazek vůči managementu, a proto buď nadhodnocuje, nebo se bojí říct pravdu. Odhady jsou ale pouze nástroj pro plánování, ne výkonnostní kritérium. Pokud management začne měřit rychlost týmu (velocity) a tlačit na vyšší čísla, tým začne uměle navyšovat odhady. Místo toho se zaměřte na stabilní tempo – pokud je rychlost konstantní, můžete plánovat s větší jistotou. A pokud tým dodává méně, než slíbil, řešte příčiny, ne čísla.
Pokud testujete celý store, mějte na paměti, že integrační testy mají své místo, ale pro rychlost a čistotu jsou unit testy vhodnější. Pro reducery a async akce je izolace nejlepší, protože vám umožní rychle identifikovat, kde došlo k chybě. Pamatujte, že testy jsou také dokumentací chování. Pokud se stav změní způsobem, který není pokrytý testem, je to často první signál, že nová funkce přináší nečekané vedlejší účinky. Proto udržujte testy malé, zaměřené na jednu odpovědnost, a vždy je spouštějte při každé změně kódu.
Testování Redux logiky nemusí vždy znamenat spuštění celé aplikace. Reducery i async akce jsou čisté funkce, které lze ověřit v izolaci, což výrazně zrychluje vývoj a zvyšuje spolehlivost. Klíčové je pochopit, že reducer je deterministická funkce závislá pouze na svém stavu a akci. Proto stačí vytvořit inicializovaný store a posílat do něj akce, aniž byste potřebovali renderovat komponenty nebo běžící server.
První sprint: co si pohlídat a čeho se vyvarovat Plánování sprintu by mělo trvat maximálně dvě hodiny na jeden týden sprintu. Pokud plánujete dvoutýdenní sprint, vyhraďte si čtyři hodiny. Během plánování si tým vezme položky z backlogu, které zvládne dokončit. Tady pozor na přehnaný optimismus – odhadujte v ideálních hodinách, ne v reálném čase. Reálný čas zahrnuje schůzky, e-maily, pohovory u kávovaru. Většina českých týmů má při prvním plánování tendenci naložit si o třicet procent více práce, než stihne. Výsledek? Na konci sprintu se dělá „hotovo" z poloviny, a to není hotovo. Definice hotového musí být jasná: kód je otestovaný, zareviewovaný, nasazený do produkce a zdokumentovaný. Bez této definice je Scrum jen divadlo.