【发布时间】:2012-04-09 17:52:19
【问题描述】:
我有一个 PHPUnit 测试套件,由于未找到类定义,该套件目前正在导致致命错误。归根结底,这是测试代码本身的失败,以及开发人员在提交代码之前未能证明测试本身的正确性。
但是,这样的事情确实时有发生,如果发生致命错误(无论最终由谁负责),测试被简单地标记为失败,而测试的其余部分,那就太好了套件仍然被执行。
我已阅读有关--process-isolation 开关的信息,据我所知,它应该 解决这个问题。由于每个测试都在单独的进程中运行,如果子进程因致命错误而死亡,父进程仍然可以继续运行。事实上,这在对类似问题的回答中明确说明了这一点:https://stackoverflow.com/a/5340151/84762,它显示了我希望自己看到的确切输出类型。
但是,无论我是否使用 --process-isolation 标志,我似乎都能得到完全相同的输出:
没有进程隔离
[kogi@phagocyte ~]$ /usr/bin/phpunit --colors --verbose --coverage-html "target/coverage" ~/app/zend/tests/application/
PHP Fatal error: Class 'Rmd_Database_OldObject' not found in /home/kogi/app/zend/private/models/translate/Poll.php on line 9
PHP Stack trace:
PHP 1. {main}() /usr/bin/phpunit:0
PHP 2. PHPUnit_TextUI_Command::main() /usr/bin/phpunit:46
PHP 3. PHPUnit_TextUI_Command->run() /usr/share/pear/PHPUnit/TextUI/Command.php:130
PHP 4. PHPUnit_Runner_BaseTestRunner->getTest() /usr/share/pear/PHPUnit/TextUI/Command.php:150
PHP 5. PHPUnit_Framework_TestSuite->addTestFiles() /usr/share/pear/PHPUnit/Runner/BaseTestRunner.php:96
PHP 6. PHPUnit_Framework_TestSuite->addTestFile() /usr/share/pear/PHPUnit/Framework/TestSuite.php:419
PHP 7. PHPUnit_Util_Fileloader::checkAndLoad() /usr/share/pear/PHPUnit/Framework/TestSuite.php:358
PHP 8. PHPUnit_Util_Fileloader::load() /usr/share/pear/PHPUnit/Util/Fileloader.php:79
PHP 9. include_once() /usr/share/pear/PHPUnit/Util/Fileloader.php:95
PHP 10. require_once() /home/kogi/app/zend/tests/application/translate/PollTest.php:11
Fatal error: Class 'Rmd_Database_OldObject' not found in /home/kogi/app/zend/private/models/translate/Poll.php on line 9
Call Stack:
0.0003 91584 1. {main}() /usr/bin/phpunit:0
0.0076 612672 2. PHPUnit_TextUI_Command::main() /usr/bin/phpunit:46
0.0076 613744 3. PHPUnit_TextUI_Command->run() /usr/share/pear/PHPUnit/TextUI/Command.php:130
0.0246 1249464 4. PHPUnit_Runner_BaseTestRunner->getTest() /usr/share/pear/PHPUnit/TextUI/Command.php:150
0.0706 1626680 5. PHPUnit_Framework_TestSuite->addTestFiles() /usr/share/pear/PHPUnit/Runner/BaseTestRunner.php:96
0.1691 8053584 6. PHPUnit_Framework_TestSuite->addTestFile() /usr/share/pear/PHPUnit/Framework/TestSuite.php:419
0.1693 8057320 7. PHPUnit_Util_Fileloader::checkAndLoad() /usr/share/pear/PHPUnit/Framework/TestSuite.php:358
0.1694 8057664 8. PHPUnit_Util_Fileloader::load() /usr/share/pear/PHPUnit/Util/Fileloader.php:79
0.1711 8240600 9. include_once('/home/kogi/app/zend/tests/application/translate/PollTest.php') /usr/share/pear/PHPUnit/Util/Fileloader.php:95
0.1805 9187768 10. require_once('/home/kogi/app/zend/private/models/translate/Poll.php') /home/kogi/app/zend/tests/application/translate/PollTest.php:11
WITH进程隔离
[kogi@phagocyte ~]$ /usr/bin/phpunit --colors --verbose --coverage-html "target/coverage" --process-isolation ~/app/zend/tests/application/
PHP Fatal error: Class 'Rmd_Database_OldObject' not found in /home/kogi/app/zend/private/models/translate/Poll.php on line 9
PHP Stack trace:
PHP 1. {main}() /usr/bin/phpunit:0
PHP 2. PHPUnit_TextUI_Command::main() /usr/bin/phpunit:46
PHP 3. PHPUnit_TextUI_Command->run() /usr/share/pear/PHPUnit/TextUI/Command.php:130
PHP 4. PHPUnit_Runner_BaseTestRunner->getTest() /usr/share/pear/PHPUnit/TextUI/Command.php:150
PHP 5. PHPUnit_Framework_TestSuite->addTestFiles() /usr/share/pear/PHPUnit/Runner/BaseTestRunner.php:96
PHP 6. PHPUnit_Framework_TestSuite->addTestFile() /usr/share/pear/PHPUnit/Framework/TestSuite.php:419
PHP 7. PHPUnit_Util_Fileloader::checkAndLoad() /usr/share/pear/PHPUnit/Framework/TestSuite.php:358
PHP 8. PHPUnit_Util_Fileloader::load() /usr/share/pear/PHPUnit/Util/Fileloader.php:79
PHP 9. include_once() /usr/share/pear/PHPUnit/Util/Fileloader.php:95
PHP 10. require_once() /home/kogi/app/zend/tests/application/translate/PollTest.php:11
Fatal error: Class 'Rmd_Database_OldObject' not found in /home/kogi/app/zend/private/models/translate/Poll.php on line 9
Call Stack:
0.0003 91752 1. {main}() /usr/bin/phpunit:0
0.0076 612824 2. PHPUnit_TextUI_Command::main() /usr/bin/phpunit:46
0.0076 613896 3. PHPUnit_TextUI_Command->run() /usr/share/pear/PHPUnit/TextUI/Command.php:130
0.0246 1250360 4. PHPUnit_Runner_BaseTestRunner->getTest() /usr/share/pear/PHPUnit/TextUI/Command.php:150
0.0708 1627528 5. PHPUnit_Framework_TestSuite->addTestFiles() /usr/share/pear/PHPUnit/Runner/BaseTestRunner.php:96
0.1688 8054296 6. PHPUnit_Framework_TestSuite->addTestFile() /usr/share/pear/PHPUnit/Framework/TestSuite.php:419
0.1690 8057992 7. PHPUnit_Util_Fileloader::checkAndLoad() /usr/share/pear/PHPUnit/Framework/TestSuite.php:358
0.1691 8058336 8. PHPUnit_Util_Fileloader::load() /usr/share/pear/PHPUnit/Util/Fileloader.php:79
0.1707 8241296 9. include_once('/home/kogi/app/zend/tests/application/translate/PollTest.php') /usr/share/pear/PHPUnit/Util/Fileloader.php:95
0.1801 9188464 10. require_once('/home/kogi/app/zend/private/models/translate/Poll.php') /home/kogi/app/zend/tests/application/translate/PollTest.php:11
对于我们这些无法在头脑中有效区分的人来说,这两个输出实际上是相同的(除了执行时间和内存使用情况几乎可以忽略不计)。
在这两种情况下,致命错误都会杀死整个测试套件。在这种特殊情况下,这发生在第三个测试中,其余 150 个测试(在其他几个文件/套件中)从未执行。
我在这里做错了什么?是否有其他方法可以在一个测试中出现致命错误(将测试标记为失败)并继续执行剩余的测试?
编辑
我正在使用 PHPUnit 3.6.10
编辑
对这个问题的答案的评论激发了 PHPUnit 的 GitHub 页面上的一张新票:https://github.com/sebastianbergmann/phpunit/issues/545
【问题讨论】:
-
您会在这里找到答案:stackoverflow.com/questions/277224/…
-
我不确定你是指说他们不能被抓住的部分还是说他们不应该被抓住的部分......但两种说法都是错误的。在这种情况下,当测试系统的功能时,在不终止其余测试过程的情况下捕获致命错误非常重要。如果我误解了您的回答,我深表歉意,请告诉我。
-
我指的是说它不能被抓住的部分。确实,您可以使用 register_shutdown_function 来打印要记录的内容并这样做“清理”,但是由于框架已经被破坏(在堆栈上),我不相信您可以“恢复”您的程序。既然您确切知道在哪一行触发了致命错误 - 为什么不修复它呢?
-
感谢您的澄清。关键不是修复它。在这种情况下,这是微不足道的。关键是防止由于单个开发人员的错误提交而无法运行剩余的测试。如果有人提交了一个糟糕的测试,它不应该禁用整个系统。我知道致命错误是......致命的。你无法从他们身上恢复过来。但据我了解,PHPUnit 的 --process-isolation 函数将每个单独的测试函数分叉到一个单独的子进程中。如果那个孩子有一个致命错误,它就无法恢复,但父母仍然可以将它标记为失败的测试并继续下一个
-
现在我明白了 :) 根据这个:stackoverflow.com/questions/3841190/… 你应该在一个新的过程中启动 每个测试套件 希望它有所帮助。
标签: php unit-testing error-handling continuous-integration phpunit