Nette\Tester: vyřešený problém s prostředím a nápady na vylepšení

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Eda
Backer | 220
+
0
-

Zdarec.

Přišel jsem po čase k projektu, kde mám pár testů a chtěl jsem pokračovat ve vývoji. První, co jsem chtěl udělat, bylo spustit stávající testy. Nedávno jsem totiž u sebe migroval na PHP7, tak jsem předpokládal, že se možná něco rozbilo.

Zavolal jsem tedy příkaz pro tester se změněným php.ini:

vendor/bin/tester ./tests -p php -c /etc/php/7.0/apache2/php.ini

A opravdu, něco se pokazilo :-) Dostávám:

-- FAILED: evidencia-dopravcov/tests/DataLogEntityPreparer.phpt
   Exited with error code 254 (expected 0)

-- FAILED: evidencia-dopravcov/tests/UserOldRolesFixer.phpt
   Exited with error code 254 (expected 0)

Tady bylo trochu WTF. Když si přímo v souborech s testy něco dumpuju, ve výstupu konzole se to neobjeví, ani když přidám přepínač --debug. Žádný jiný přepínač pro „zachování výstupu“ jsem nenašel. Nešlo by tohle nějak upravit? Nebo to jde a špatně jsem hledal?

Nakonec jsem postupným laděním zjistil, že to padá v konstruktoru RobotLoaderu:

	public function __construct()
	{
		if (!extension_loaded('tokenizer')) {
			throw new Nette\NotSupportedException('PHP extension Tokenizer is not loaded.');
		}
	}

Další WTF. Proč mi Tester neukázal přímo tu Exceptionu a místo, kde to spadlo? To by mi ušetřilo dost času při ručním hledání.

Po tomto zjištění si říkám, jasně, nemám nalinkované nějaké rozšíření, nalinkuju ho a pohoda.

Ale v PHP manuálu píšou, že Tokenizer je již od nějaké pradávné verze přímo součástí PHPka.

Divné. Zkusím to tedy ověřit. Do konzole zadám:

php -m | grep tokenizer
-- nebo
php -r "var_dump( get_loaded_extensions() );"

A opravdu tokenizer k dispozici i v command-line je.

Zkouším jeden test pustit jako spustitelný skript jen pomocí phpka:

php tests/DataLogEntityPreparer.phpt

Skript skončí bez chyb. Pro jistotu zkouším explicitně uvést název php.ini souboru:

php tests/DataLogEntityPreparer.phpt -c  /etc/php/7.0/apache2/php.ini

Opět bez chyb.

Dokonce, když dumpnu hned na začátku tester.php informaci o tom, zda je tokenizer načten:

var_dump(extension_loaded('tokenizer'));

Tak zjistím, že ano (true).

Když ale stejnou funkci zavolám až v samotném testu, skončí to false.

Tester tedy spouští PHP proces pro testy nějak „špatně“. Když si vypíšu informace o běhovém prostředí pro Tester, dostanu tohle:

$ vendor/bin/tester -i -p php -c /etc/php/7.0/apache2/php.ini
 _____ ___  ___ _____ ___  ___
|_   _/ __)( __/_   _/ __)| _ )
  |_| \___ /___) |_| \___ |_|_\  v1.7.1

PHP binary:
/usr/bin/php7.0

PHP version:
7.0.7-4+deb.sury.org~trusty+1 (cli)

Loaded php.ini files:
/etc/php/7.0/apache2/php.ini

Loaded extensions:
Core, date, filter, hash, libxml, openssl, pcntl, pcre, Reflection, session, SPL, standard, zlib

Binárka je stejná, php.ini je stejné… co se tedy liší v testeru oproti normálnímu spuštění PHPka v konzoli, že jednou tam tokenizer je a podruhé není?

Nic, situaci teda vyřeším tak, že „extension=tokenizer.so“ přidám přímo do php.ini, který linkuju, případně parametrem „-d“ pro Tester.

Ale dalo to zabrat, než jsem se k tomu dostal.

Třeba někdo bude řešit něco podobného a tento post mu pomůže.

A třeba se někdo ( @Milo ? ) vyjádří k těm dvěma WTF, na které jsem narazil, a třeba se díky tomu povede Tester zase posunout dál :-)

Edit: A příběh pokračuje. Těch rozšíření chybí při spuštění testeru mnohem víc. Takže jsem všechny ručně musel přidat do php.ini. Při ručním spuštění se nahrají automaticky všechna rozšíření ze složky /etc/php/7.0/apache2/conf.d, při spuštění Testerem ne.

Když zkontroluju výstup php_ini_scanned_files(), dostanu tohle:

$php -r "var_dump(php_ini_scanned_files());"
string(1207) "/etc/php/7.0/cli/conf.d/10-mysqlnd.ini,
/etc/php/7.0/cli/conf.d/10-opcache.ini,
/etc/php/7.0/cli/conf.d/10-pdo.ini,
/etc/php/7.0/cli/conf.d/15-xml.ini,
/etc/php/7.0/cli/conf.d/20-calendar.ini,
/etc/php/7.0/cli/conf.d/20-ctype.ini,
/etc/php/7.0/cli/conf.d/20-curl.ini,
/etc/php/7.0/cli/conf.d/20-dom.ini,
/etc/php/7.0/cli/conf.d/20-exif.ini,
/etc/php/7.0/cli/conf.d/20-fileinfo.ini,
/etc/php/7.0/cli/conf.d/20-ftp.ini,
/etc/php/7.0/cli/conf.d/20-gettext.ini,
/etc/php/7.0/cli/conf.d/20-iconv.ini,
/etc/php/7.0/cli/conf.d/20-json.ini,
/etc/php/7.0/cli/conf.d/20-mcrypt.ini,
/etc/php/7.0/cli/conf.d/20-mysqli.ini,
/etc/php/7.0/cli/conf.d/20-pdo_mysql.ini,
/etc/php/7.0/cli/conf.d/20-phar.ini,
/etc/php/7.0/cli/conf.d/20-posix.ini,
/etc/php/7.0/cli/conf.d/20-readline.ini,
/etc/php/7.0/cli/conf.d/20-shmop.ini,
/etc/php/7.0/cli/conf.d/20-simplexml.ini,
/etc/php/7.0/cli/conf.d/20-sockets.ini,
/etc/php/7.0/cli/conf.d/20-sysvmsg.ini,
/etc/php/7.0/cli/conf.d/20-sysvsem.ini,
/etc/php/7.0/cli/conf.d/20-sysvshm.ini,
/etc/php/7.0/cli/conf.d/20-tokenizer.ini,
/etc/php/7.0/cli/conf.d/20-wddx.ini,
/etc/php/7.0/cli/conf.d/20-xmlreader.ini,
/etc/php/7.0/cli/conf.d/20-xmlwriter.ini,
/etc/php/7.0/cli/conf.d/20-xsl.ini

Při volání php z testeru ale scanned files úplně chybí – tzn. načítá se jen ten ini file, který se předá v konfiguraci, ini fily pro ta rozšíření už ne.

Bohužel, runtimově zřejmě nejde konfigurace --with-config-file-scan-dir při volání php nijak přenastavit… Takže jdu cestou vlastního ini konfigu pro testy, který bude obsahovat původní konfig + všechny konfigy rozšíření.

Editoval Eda (17. 6. 2016 21:26)

Milo
Nette Core | 1283
+
+1
-

Když si přímo v souborech s testy něco dumpuju, ve výstupu konzole se to neobjeví.

Teď to jednoduše nejde. Ale když test failuje, stdout se vypíše. V hlavě mám na to TODO, ale hned tak to nebude. --debug je v podstatě internal a k tomuhle neslouží.

Další WTF. Proč mi Tester neukázal přímo tu Exceptionu a místo, kde to spadlo?

Voláš v boostrapu testů Environment::setup()?

Potíž s --with-config-file-scan-dir se objevuje často. Je to zmíněno v dokumentaci. Issues k tomu bylo hodně, v Testeru 2.x bude existovat berlička, řeší se to v #290. IMHO, testy by měly být distribuovány s vlastním php.ini, aby bylo zřejmé, jaké rozšíření pro svůj běh potřebují.

Šaman
Člen | 2659
+
0
-

Dumpování v testech jsem vyřešil takhle, jen je potřeba spustit si konkrétní test v prohlížeči. To dělám vždy, když je píšu, spouštění z IDE/konzole provádím jen když provedu nějaké úpravy kódu aplikace a chci si ověřit, že se nic nerozbilo.

Co se php.ini týče, tak to řeším stejně, jako config. Tj. v repozitáři mám php.sample.ini ve kterém je seznam všech nutných nastavení a modů a v .gitignore ignoruji php.ini, který bude závislý na konkrétním stroji (adresy knihoven rozšíření na disku apod.)

Editoval Šaman (19. 6. 2016 22:34)