user2583322
user2583322

Reputation: 1

PHPUnit_Framework_Exception

I am programming some tests with PHPUnit and recently, I have come across the flag option: --process-isolation After reading that it runs each test in a separate PHP process, I thought it might be helpful to use this flag when I execute my testsuites. However, it constantly raises Exceptions such as:

PHPUnit_Framework_Exception: stty: Standard Input: Invalid Argument

or sometimes:

PHPUnit_Framework_Exception: Notice: Constant PEAR_ERROR_RETURN already defined in /usr/share/php/PEAR.php on line 25
Notice: Constant PEAR_ERROR_PRINT already defined in /usr/share/php/PEAR.php on line 26
Notice: Constant PEAR_ERROR_TRIGGER already defined in /usr/share/php/PEAR.php on line 27
Notice: Constant PEAR_ERROR_DIE already defined in /usr/share/php/PEAR.php on line 28
Notice: Constant PEAR_ERROR_CALLBACK already defined in /usr/share/php/PEAR.php on line 29
Notice: Constant PEAR_ERROR_EXCEPTION already defined in /usr/share/php/PEAR.php on line 34
Notice: Constant PEAR_ZE2 already defined in /usr/share/php/PEAR.php on line 37
Notice: Constant OS_WINDOWS already defined in /usr/share/php/PEAR.php on line 44
Notice: Constant OS_UNIX already defined in /usr/share/php/PEAR.php on line 45
Notice: Constant PEAR_OS already defined in /usr/share/php/PEAR.php on line 46

The first exception only comes up when I activate the flag of process isolation, whereas I don't have it, the test runs smoothly and without any problems. The second exception, at first hand, i thought it might be due to a conflict in inclusions, but after looking it over and changing all include to include_once, the exception still keeps coming up.

Any help would appreciated.

Upvotes: 0

Views: 1103

Answers (2)

Vladimir Bashkirtsev
Vladimir Bashkirtsev

Reputation: 1354

I have dug deep into this issue. I will explain what's going based on assumption PHPUnit 3.7 is in use.

When you use process isolation PHPUnit still injects global state into child process. At this point I may hear some opponents saying having preserveGlobalState on by default is contradicting intention of runInSeparateProcess. I though the same way until I have realized that phpunit.xml has section which defines global variables/constants/includePath - without preserveGlobalState these settings would never make it to child process. So now I am convinced that injection of global state to child process is needed in most cases: all we need to do - ensure that this global state is clean enough for tests to run.

Rightfully Sebastian Bergmann has made some code which exports globals/constants/required files and puts it into Smarty template which in turn becomes PHP script for chlid process. However he has made one small mistake (in my view): he loaded constants BEFORE required files, not after. And this makes big difference! Here the example:

requiredfile.php:

<?php

define("SOME_CONSTANT", true);

class RequiredClass
 {
 }

?>

When this file is loaded by parent PHPUnit process it defines the constant and also adds requiredfile.php to the list of included files.

Then PHPUnit makes PHP script for the child which basically looks like:

<?php

define("SOME_CONSTANT", true);

require_once "requiredfile.php";

?>

Of course it causes PHP to trigger error (constant already defined) which converted by PHPUnit to exception because it has no idea that this error was triggered not by the test code but by the code which PHPUnit has generated.

However constant definitions in this code have if (defined()) and so if we just put definition of constants AFTER required files then no constant redefinition happens and hence no errors.

With failed PHPT tests main culprit is PEAR.php and you cannot avoid it as PHPUnit uses RunTest from PEAR. So unless you fix Smarty template in PHPUnit 3.7 you will not be able to run any PHPT tests along with any tests which use process isolation.

So what you need to do? Easy! Head to PHPUnit/Framework/Process/TestCaseMethod.tpl.dist and swap {constants} and {included_files} . This may be not the best solution for everyone - especially if you cannot change PHPUnit files. But I personally consider it as a bug in PHPUnit and therefore such fix is warranted.

Upvotes: 1

jake_feyereisen
jake_feyereisen

Reputation: 739

Try adding:

/**
 * @runInSeparateProcess
 * @preserveGlobalState disabled
 */

to the PHPDoc above your test rather than using the command line option. The flag may still be preserving the global variables between tests.

Upvotes: 0

Related Questions