我正在使用PHPUnit编写一些测试,最近,我遇到了标记选项: - process-isolation 在读取它在一个单独的PHP进程中运行每个测试后,我认为它可能当我执行我的测试套件时,有助于使用此标志。但是,它不断提出例外:
PHPUnit_Framework_Exception: stty: Standard Input: Invalid Argument
或有时:
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
第一个例外只有在我激活进程隔离标志时才出现,而我没有它,测试运行顺利且没有任何问题。 第二个例外,我认为这可能是因为包含内容存在冲突,但在查看并将所有包含更改为include_once后,异常仍然会出现。
任何帮助都会受到赞赏。
答案 0 :(得分:1)
我深入研究了这个问题。我将基于PHPUnit 3.7正在使用的假设来解释正在发生的事情。
当您使用进程隔离时,PHPUnit仍会将全局状态注入子进程。在这一点上,我可能听到一些反对者说默认使用preserveGlobalState与runInSeparateProcess的意图相矛盾。我以同样的方式,直到我意识到phpunit.xml有定义全局变量/常量/ includePath的部分 - 没有preserveGlobalState这些设置永远不会进入子进程。所以现在我确信在大多数情况下需要注入全局状态到子进程:我们需要做的就是 - 确保这个全局状态足够干净,以便运行测试。
正确地说,Sebastian Bergmann已经制作了一些代码,用于输出全局/常量/必需文件并将其放入Smarty模板中,后者又成为chlid进程的PHP脚本。然而,他犯了一个小错误(在我看来):他在所需文件之前加载常量,而不是之后。这有很大的不同!这里的例子是:
requiredfile.php:
<?php
define("SOME_CONSTANT", true);
class RequiredClass
{
}
?>
当这个文件由父PHPUnit进程加载时,它定义了常量,并将requiredfile.php添加到包含文件列表中。
然后PHPUnit为孩子制作PHP脚本,基本上看起来像:
<?php
define("SOME_CONSTANT", true);
require_once "requiredfile.php";
?>
当然它会导致PHP触发由PHPUnit转换为异常的错误(已经定义的常量),因为它不知道这个错误不是由测试代码而是由PHPUnit生成的代码触发的。
然而,这段代码中的常量定义有if(defined()),所以如果我们只是将常量定义为AFTER所需的文件,那么就不会发生重复定义,因此没有错误。
由于PHPT测试失败,主要罪魁祸首是PEAR.php,你无法避免它,因为PHPUnit使用PEAR的RunTest。因此,除非您在PHPUnit 3.7中修复Smarty模板,否则您将无法运行任何PHPT测试以及任何使用进程隔离的测试。
那你需要做什么?简单!前往PHPUnit / Framework / Process / TestCaseMethod.tpl.dist并交换{constants}和{included_files}。这可能不是每个人的最佳解决方案 - 特别是如果您无法更改PHPUnit文件。但我个人认为这是PHPUnit中的一个错误,因此需要进行此类修复。
答案 1 :(得分:0)
尝试添加:
/**
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
到测试之上的PHPDoc而不是使用命令行选项。该标志可能仍然保留测试之间的全局变量。