O věci jménem PHPUnit a následné sestavě se systémem Jenkins jste asi slyšeli. Taky jsem zkusil a mám několik zásadních výhrad.
První a ta nejhorší výhrada se týká především autorů návodů a tutoriálů. Všichni autoři, které jsem našel (včetně oficiálních), rádi předvedou, jak začít psát jednoduchý test. Dobře. Kolo dva ale zní, že naprosto všichni také předpokládají, že vývoj pomocí testování pojede od samého začátku nebo testy nad běžící aplikací bude psát zkušený kodér. Chyba...
Druhá výtka navazuje. Pokud mám chuť se testování naučit a zároveň je třeba ho zahájit nad nějakou aplikací, tak potřebuji začít v části, kde vadný test nenadělá moc škody. Tedy ne hlavní části jako jsou uživatelské účty. Proto jsem chtěl začít v pluginu, jehož využití je jenom místní. Nejde to. Z nějakého důvodu nedokážu podhodit tabulku připravených falešných dat (mock) jako zdroj pro srovnání. Projížděl jsem spousty míst, včetně oficiální podpory CakePHP na irc, ale nikde nebyl návod, jak rozjet pouze věci v testu v pluginu.
Tohle jsou asi největší důvody, proč i já zatím preferuji vývoj vodopádem ( naprogramuj - var_dump - uprav - ... - hotovo). Dále je snazší přejít z vývoje skrz testy na vodopád.
Odpověď zní - PHPUnit je nepoužitelné. KWebCMS 1 a 2 NENÍ stavěné na testování těmito prostředky. Je to způsobeno hlavně tvrdým zaměřením na práci nad diskem - jeho databází jsou soubory a složky. A to je věc, která velmi omezuje možnost užít nástrojů, které se souborovými systémy až tak nemají rády. Pro automatické testování nad souborovým systémem je třeba očekávat jak různorodé nedostupnosti disku, tak potřebu mít někde bezpečně odložená základní data, která pak proti testům staví. Druhá věc, která dělá tyto věci nepoužitelnými, je užitá logika, kde jsem výrazně zaměřen na vstupy a výstupy a co si drží uvnitř, to je pro okolí černá skříňka. A to hlavě díky tom, že jsem to dotáhl až do absurdního stavu, kdy v zásadě jsou v některých případech ve třídě v modulu jen dvě funkce - která data přebere a která vyplivne výsledek v požadovaném tvaru.
Samotná testovací sestava jde napsat, avšak musí počítat právě i se specifiky práce proti disku. Veškeré knihovny (nízkoúrovňové operace) lze testovat jen přímo proti datům, která mají na disku a která se tak ověří z něj. Navíc je potřeba podstrčit celé falešné testovací prostředí. Vyšší úroveň (moduly) už lze testovat obvyklejším způsobem. U mne je jen potřeba podhodit správné falešné knihovny a další součásti. Nakonec nejvyšší úroveň (paradoxně prostředí jádra) zajímá jen jestli existuje modul, je rozumný uživatel a smí modul pro uživatele otevřít a které všechny moduly zná. Vůbec jádra všech tří součástí (prezentace, administrace, instalace) jsou svým postavením vyjímečná vůči ostatním částem. Ale to je jinam.
Změna stavu. Díky pokroku uvnitř PHP (5.5+) lze poměrně rozumně začít řešit problematiku, která s připojení na disk vyplývá. Proto u této verze už bylo přistoupeno (2017) k užití testování. Je to vidět na mých externích knihovnách, které když mají verzi, tak jsou zpravidla testované "durch" - buď test nebo coverage ignore. Vendor součásti KWCMS4 jsou testované poměrně důkladně. A dost se to vyplatilo.
V rámci sebevzdělávání jsem narazil na problematiku unit testů a jejich užití nad libovolným mapperem. Po nějaké době jsem došel k názoru, o který se zde podělím.
Jde o hlášku, že mappery nelze testovat. Souhlasím, nelze je testovat prostými unit testy. Ty mají řešit logiku částí aplikace a jejího chování a ne jak se dostane k datům. Zde nastupují integrační testy. Protože obchodní logice by měl být ukradený zdroj dat. Tedy jestli k nim přijde z databáze, ze souboru, z cache... Na komunikaci s těmito zdroji dat se můžou podělat věci, které nelze řešit z pohledu obchodní logiky. Ale lze je řešit z pohledu techniky.
I já jsem v kw_mapperu narazil na úroveň, kde nestačí otestovat tvar dotazu a jak se pak vykrmí entity záznamů. Prostě není v mých silách kontrolovat, že je připojená databáze s uživatelským nastavením nebo disk někde v cloudu nespadl a není teďka jen ke čtení, přičemž já tam potřebuji zapsat. To je problém zdroje dat a tedy integrace.
Takže mappery lze testovat. A lze testovat i části je obsahující. Lze je testovat integračními testy, které už počítají s úložišti a tím, že v těch úložištích něco už je. A ani není chybou návrhu, že je potřeba s k těm datům nějak dostat.
V PHP je hranice mezi unit testy a integračními testy částečně mazaná pomocí phpunit, které ty integrační umí také. Onen rozdíl je však poznat velmi záhy, když je potřeba pro testy něco nasypat do úložiště. Integrační test úložiště vyžaduje.
Díky tomu jsem měl (jaro 2021) problém s testy částí kw_mapperu, které právě do databází přistupují - nebyl jsem schopen dotlačit testovací virtuál do stavu, kdy by si ta data pamatoval. Prostě neviděl nahraná předpřipravená data. A dotazy se tvářil, že je vlastně všechno v pořádku. A já bez otestování těchto částí nehodlal vydat major verzi. Část problému nakonec byla způsobena potřebou PHP posílat dotazy po jednom a ne celým balíkem.
Jiná věc je, že jsem viděl snahy nacpat obchodní logiku do databází. Tím myslím různé vnitřní definované procedury v databázích. To jsou i různé triggery. Prostě že aplikace nemá představu, co jí vlastně databáze dodá nebo jak jí bude s daty manipulovat. Tohle dělá děsivý problém s přenositelností a je to podle mne forma vendor lock-inu. Pokud budu potřebovat vyměnit databázi (protože se třeba změnila licence nebo přišla život ulehčující featura), tak mne tohle drží na pro mne už nevhodném produktu nebo mne může stát hromadu peněz to předělat na tu vyhlédnutou. Databáze má jen skladovat data, ne řešit, že uživatel je blb a chce tam dát něco, co tam nepatří. To mají ovlivnit maximálně constraints a vzdálené klíče. A i s těmi (a jinými agregačními funkcemi) je třeba postupovat opatrně, protože to omezuje skladování mimo databázové systémy - u souborů si pak tohle typicky musíte stejně řešit sami někde vedle.
S tím souvisí i využívání vlastních dotazů. Dotazy "napřímo" jsou hezká věc právě jen do chvíle, kdy je třeba rozmýšlet, jestli to někdo někdy nebude spouštět na něčem totálně jiném. Nápověda: bude. Pro správně napsaný mapper není problém celý systém přepnout pouhou změnou nastavení a projetím automatických testů. Ruční dotazy je třeba fyzicky zkontrolovat. To zvyšuje cenu migrace.