当PHPUnit测试在我的开发盒(Linux Mint)上正常失败时,它会在我的连续集成盒(Centos)上导致"分段故障"。两台机器都运行相同版本的PHPUnit。我的dev-box运行的是PHP 5.3.2-1ubuntu4.9,CI是PHP 5.2.17。不过,我宁愿把升级PHP作为最后的手段。
根据此线程:PHPUnit出现分段错误我已尝试停用/重新安装Xdebug。我没有安装inclue.so。
在CI框上,我目前只有两个扩展处于活动状态:来自php-xml的dom(phpunit所需)和memcache(我的框架所需),其他所有扩展都已关闭。
根据cweiske的建议,如果升级php对您来说不是一个选项,并且您在查找segfault的源时遇到问题,则可以使用调试器来了解更多信息。
您可以通过这种方式启动gdb来调试PHPUnit会话:
gdb --args php /usr/bin/phpunit quiz_service_Test.php
然后键入r
以运行程序和/或首先设置环境变量。
set env MALLOC_CHECK_=3
r
您还可以考虑在系统上安装PHP的调试符号,以获得更好的调试结果。gdb在启动时为您检查这一点,并留下一个如何做到这一点的通知。
我遇到了PHPUnit分段错误的问题,很难找到答案,所以希望这能帮助以后解决同样问题的人。
PHPUnit正在分段,但仅限于:
- 如果出现错误(或不止一个)
- 在所有测试运行之后,但在打印错误之前
过了一段时间,我意识到这是由于使用数据提供程序的测试失败,特别是对于传递带有大量递归引用的对象的数据提供程序。铃声终于响了,我做了一些挖掘:问题是,当你使用数据提供程序而测试失败时,PHPUnit会尝试为失败描述创建一个所提供参数的字符串表示,以告诉你失败了什么,但当其中一个参数有无限递归时,这是有问题的。事实上,PHPUnit在PHPUnit_Framework_TestCase::dataToString()
(第1612行附近)中所做的是打印出数据提供程序使用print_r
提供的所有参数,这在PHP试图创建无限递归对象的字符串表示时会导致segfault。
我找到的解决方案是:
- 为我的所有测试类使用一个基类(幸运的是我已经在做了)
- 在我的测试基类中重写
dataToString()
,以检查数据数组中的这些类型的对象(在我的情况下这是可能的,因为我知道这些对象是什么样子的)。如果对象存在,我会返回一些特殊值,如果不存在,我只会将其传递给父方法
我遇到了类似的问题,通过禁用中的乱码整理器
PHPStorm=>编辑配置=>解释器选项:-dzend.enable_gc=0
或者,如果你从命令行运行测试,你可以尝试添加:
-d zend.enable_gc=0
当您得到segfault时,请将您的PHP升级到最新版本。不仅是包管理器中的最新版本,而且是php.net上的最新可用版本。如果它仍然存在segfault,那么您可以确定php本身还没有解决这个问题。不要试图在旧版本的PHP中消除segfault,因为它可能已经在新版本中修复了。
下一步是找出问题:让你的测试越来越小,直到你不能删除任何东西(但它仍然会出错)。如果有,请将测试移到一个独立的php脚本中,该脚本会segfault。现在,您已经在PHP错误跟踪器中为您的错误编写了一个测试脚本。
除了https://stackoverflow.com/a/38789046/246790这对我帮助很大:
您可以使用PHP函数gc_disable();
我已经把它和ini_set('memory_limit', -1);
一起放在了我的PHPUnit引导程序代码中
如果有人在Laravel 中遇到与PHPUnit有关的问题
花了一段时间才弄清楚问题出在哪里。我仔细检查了我当前代码和上一次修订版本之间的差异,经过一些尝试和错误,最终达到了目的。
我有两个不同的模型,它们都包含了protected $with
覆盖。
这一定导致了phpunit无法处理的某种循环。
希望有人觉得这很有用。
我也遇到了同样的问题,我试图写一个未定义的类变量:
我的类(它是一个cakeHP类)导致了分段错误:
class MyClass extends AppModel {
protected $classVariableOne;
public function __construct($id = false, $table = null, $ds = null) {
parent::__construct($id, $table, $ds);
$this->classVariableOne =& ClassRegistry::init('ClassVariableOne');
// This line caused the segmentation fault as the variable doesn't exists
$this->classVariableTwo =& ClassRegistry::init('ClassVariableTwo');
}
}
我通过添加第二个变量修复了它:
class MyClass extends AppModel {
protected $classVariableOne;
protected $classVariableTwo; // Added this line
public function __construct($id = false, $table = null, $ds = null) {
parent::__construct($id, $table, $ds);
$this->classVariableOne =& ClassRegistry::init('ClassVariableOne');
$this->classVariableTwo =& ClassRegistry::init('ClassVariableTwo');
}
}
无限递归通常是我们遇到这个问题的原因。在phpunit下运行代码时,无限递归的症状似乎与在其他环境中运行代码时不同。
请更新到最新的XDEBUG。在使用v3.1.5时出现了同样的错误,在升级到3.1.6后,一切都正常。
我遇到了同样的问题。我将PHPUnit升级到4.1版本(以运行测试),它能够向我显示对象,正如Isaac所指出的。
因此,如果您遇到同样的问题,请升级到PHPUnit>=4.1,您将能够看到错误,而不是收到"Segmentation fault"消息。
当运行代码覆盖的PHPUnit时,我一直得到一个Segmentation fault: 11
。在对分段故障进行堆栈跟踪后,我发现以下是导致分段故障错误的原因:
Program received signal SIGSEGV, Segmentation fault.
0x0000000100b8421a in xdebug_path_info_get_path_for_level () from /usr/lib/php/extensions/no-debug-non-zts-20121212/xdebug.so
我用Komodo远程调试包的最新版本替换了上面路径中当前的xdebug.so
,该包是用我的PHP版本(对我来说是5.5)下载的相应包的子文件夹,一切都正常了。
以下为我修复了一个类似的问题(当gdb
回溯的输出包括libcurl.so
和libcrypto.so
时):
禁用/etc/php.d/pgsql.ini
:
; Enable pgsql extension module
; extension=pgsql.so
编辑/etc/php.d/curl.ini
以确保在卷曲:之前包含pgsql.so
; Enable curl extension module
extension=pgsql.so
extension=curl.so
curl.cainfo=/home/statcounter/include/config/cacert.pem
如果您有一个属性指向同一对象的对象,或者其他类型的指针循环,则在运行时会收到此消息
serialize($object);
如果你是Laravel的用户,并且你正在处理模型。如果你认为,你永远不会有这个问题,因为你通过在模型上使用$hidden
属性来避免指针循环,请注意,$hidden
属性不影响serialize
,它只影响到JSON
和array
的强制转换。
当我将一个模型保存到Mailable
对象的属性中时,我遇到了这个问题。
使用修复
$this->model->refresh();
在__construct
方法中,就在整个对象被序列化之前。
这与代码而非扩展有关。在我的情况下,我有这两个文件
-
测试用例
- 示例测试
在测试用例中,有一个名为createApplication的方法。空着吧。
在示例测试中,您可以创建方法并填充$this->assertTrue(true)
以上是基本设置,希望您可以根据需要扩展需求。