Testování reducerů a async akcí v Reduxu bez integračního prostředí
Druhý častý problém je ignorování dotazovacích vzorů. NoSQL databáze nejsou univerzální – každý typ má specifické možnosti dotazování. Než nasadíte, zkuste si napsat pět nejčastějších dotazů, které vaše aplikace bude spouštět. Pokud zjistíte, že potřebujete fulltextové vyhledávání nebo složité agregace, možná je lepší zůstat u relační databáze nebo zkombinovat obojí (tzv. polyglot persistence). Také si rozmyslete, jak budete data mazat – některé NoSQL databáze nemají efektivní operaci pro smazání velkého rozsahu dat.
Selektory by měly být jediným místem, kde čtete data ze store. Pomocí knihovny reselect lze snadno vytvářet memoizované selektory, které se přepočítávají jen když se změní vstupní části stavu. To zabrání zbytečnému renderování komponent a zvýší výkon. Vyhněte se přímému přístupu ke store v komponentách – používejte hooky useSelector a useDispatch. Jasně oddělte prezentační komponenty (které jen zobrazují data) od kontejnerových (které mají přístup k Redux). Díky tomu bude kód snadno testovatelný a znovupoužitelný.
Při škálování aplikace se vám bude hodit rozdělení store do menších modulů, tzv. slices pomocí nástroje Redux Toolkit. Ten vám poskytne createSlice, který automaticky generuje akce a reduktory. Díky tomu píšete méně boilerplate kódu a méně chyb. Redux Toolkit také zahrnuje Immer, který umožňuje psát mutující zápis, ale pod kapotou stále vytváří neměnné aktualizace. Pokud přecházíte ze staršího kódu, postupně migrujte – není nutné předělávat vše najednou.
Psaní testů bývá často odkládáno na později, ale s knihovnou pytest se z něj stane překvapivě rychlá a příjemná činnost. Na rozdíl od složitějších frameworků nabízí pytest jednoduchou syntaxi, která nevyžaduje psát třídy ani dědit z testovacích základů. Stačí obyčejné funkce, které začínají slovem test_, a pytest je automaticky najde a spustí. Díky tomu se dá testování naučit za odpoledne a postupně ho zapojit do běžného vývoje.
Pokud se pro NoSQL rozhodnete, začněte s menším projektem. Nepřevádějte hned celý systém. Vytvořte si vzorovou aplikaci s reálnými daty a otestujte výkon, škálování a operace jako backup a obnova. Sledujte, jak se databáze chová při zátěži, a hlavně si nastavte monitorování. NoSQL není samospasitelný – pokud vám chybí zkušenosti, může se snadno stát, že místo zjednodušení dostanete složitější infrastrukturu. Začněte s jasným cílem, měřte výsledky a teprve poté rozšiřujte.
Async akce testujete podobně, ale potřebujete mockovat závislosti, jako jsou API volání. V Redux Thunk se akce stává funkcí, která přijímá dispatch a getState. V testu zavoláte tuto funkci s mocknutým dispatch a getState a ověříte, že dispatch byla volána s očekávanými akcemi. Pro Redux Saga je postup složitější: potřebujete spustit generátor a kontrolovat, jaké efekty vrací. Můžete použít knihovnu redux-saga-test-plan, která zjednodušuje testování sekvencí efektů. Důležité je nastavit časové limity pro async operace, aby test nespadl na otevřeném spojení.
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.
Nezapomeňte na devtools – Redux DevTools jsou nezbytným nástrojem pro ladění. Díky nim můžete sledovat každou akci, stav a dokonce cestovat v čase. Ujistěte se, že v produkčním prostředí devtools vypnete, abyste zbytečně nezpomalovali aplikaci. Poslední rada: ptejte se sami sebe, zda daná funkce skutečně potřebuje Redux. Pokud si nejste jisti, začněte s lokálním stavem a Redux přidejte teprve tehdy, když se objeví konkrétní problém. Tím udržíte kód čistý a srozumitelný.
Pro jednoduché aplikace, které potřebují standardní CRUD operace, je REST jasnou volbou. Pokud máte veřejné API, které budou používat tisíce vývojářů, REST usnadňuje dokumentaci i verzování. Stačí dodržovat HTTP metody a stavové kódy, a klienti hned vědí, co se děje. Vyhnete se také problémům s cachováním, protože REST umí dobře využít HTTP cache. Typická chyba? Snažit se RESTem obejít tím, že vytvoříte deset různých endpointů pro jednu obrazovku. To je signál, že byste měli přemýšlet o GraphQL.
Základní test vypadá tak, že do souboru s názvem test_nazev.py napíšete funkci test_něco() a uvnitř použijete příkaz assert. Například chcete-li ověřit, že funkce secti(2, 3) vrací 5, stačí napsat assert secti(2, 3) == 5. Pytest při selhání ukáže, které hodnoty se lišily, takže nemusíte psát vlastní hlášky. Důležité je testy psát tak, aby byly nezávislé na pořadí, a proto se vyhýbejte sdíleným proměnným napříč testy. Pokud potřebujete připravit data, použijte takzvané fixture, které se definují pomocí dekorátoru @pytest.fixture a pak se předávají jako parametry funkce.