Proč nepoužívat autoloading v testech

TL;DR: Protože se tak ztrácí izolace testů.

Vypadá to jednoduše a přiznám se, že sám toto na několika projektech používám. Mluvím o použití tohoto kódu v phpunit.xml:

Tím se dává PHPUnit vědět, aby před každým testem načetl autoloader od Composeru. Samozřejmě je to nejjednodušší cesta, jak načíst testované třídy, ale je to také způsob, jak přijít o izolaci testů. Nyní je potřeba brát v úvahu, že cokoliv, co je schopen Composer načíst, může být načteno během testů (včetně knihoven třetích stran).

Kdy to může být problém? Řekněme že máme metodu, která dynamicky instancuje objekty a jako parametr přijímá jejich plný název včetně namespace.

Test pro tuto implementaci je velice jednoduchý – předáme metodě „\stdClass“ a ověříme, že na výstupu dostaneme instanci stdClass.

Samozřejmě je potřeba nějaká validace, že předaná třída skutečně existuje, tak není nic lepšího než použít class_exists:

Nyní je na čase napsat test, který předá nenadefinovanou třídu a ověří, že byla vyhozena výjimka InvalidArgumentException. A právě nyní nastává problém s použitím autoloaderu. I pokud uděláte ten nejvíce náhodný název pro „neexistující“ třídu, nikdy si nemůžete být jistí, že se tento název někdy v budoucnu neobjeví v nějaké vaší závislosti.

Jaká je pravděpodobnost, že se to stane? No, spíš máte šanci, že vyhrajete v národní loterii, ale i tak nemám rád tu představu, že je zde možnost, jak rozbít moje testy bez toho, aniž by do nich někdo zasahoval.

Co tedy navrhuji? Vytvořit bootstrap pouze pro testy, manuálně vložit požadované třídy, které jsou potřeba a volitelně vypsat i názvy těch, které rozhodně nesmí být definované.

Tím získáváte plnou kontrolu nad tím, jaké třídy budou v našich testech definované a které ne a nehrozí, že testy rozbije změna v externí knihovně.

Mohlo by se vám líbit...

Napsat komentář

Vaše emailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *