開発ボックス(Linux Mint)でPHPUnitテストが正常に失敗すると、継続的インテグレーションボックス(Centos)で「セグメンテーション違反」が発生します。両方のマシンが同じバージョンのPHPUnitを実行しています。私の開発ボックスはPHP 5.3.2-1ubuntu4.9を実行しており、CIはPHP5.2.17です。ただし、最後の手段としてPHPのアップグレードは残したいと思います。
このスレッドによると: PHPUnitはセグメンテーション違反を取得します Xdebugを非アクティブ化/再インストールしようとしました。 inclue.soをインストールしていません。
CIボックスでは、現在アクティブになっている拡張機能は2つだけです。php-xmlのdom(phpunitに必要)とmemcache(フレームワークに必要)ですが、他のすべてはオフになっています。
Cweiskeが提案した内容の次に、アップグレードPHPが選択肢になく、セグメンテーション違反の原因を特定するのに問題がある場合は、デバッガーを使用して詳細を調べることができます。
次の方法でgdbを起動して、PHPUnitセッションをデバッグできます。
gdb --args php /usr/bin/phpunit quiz_service_Test.php
次に、r
と入力して、プログラムを実行するか、最初に環境変数を設定します。
set env MALLOC_CHECK_=3
r
PHPのデバッグシンボルをシステムにインストールして、デバッグの結果を改善することも検討してください。gdbは起動時にこれをチェックし、その方法を通知します。
PHPUnitのセグフォールトに問題があり、答えを見つけるのに苦労したので、これが後で同じ問題を抱えている人に役立つことを願っています。
PHPUnitはセグフォールトしていましたが、
しばらくして、データプロバイダーを使用したテスト、特に再帰参照が多いオブジェクトを渡したデータプロバイダーの失敗が原因であることに気付きました。ついにベルが鳴り、私はいくつか掘り下げました。問題は、データプロバイダーを使用していてテストが失敗すると、PHPUnitが失敗の説明に提供された引数の文字列表現を作成して、何が失敗したかを通知しようとすることです。引数の1つに無限の再帰がある場合、問題が発生します。実際、PHPUnitがPHPUnit_Framework_TestCase::dataToString()
(1612行目あたり)で行うことは、_print_r
_を使用してデータプロバイダーによって提供されたすべての引数を出力することです。これにより、PHPが試行するとセグメンテーション違反が発生します。無限再帰オブジェクトの文字列表現を作成します。
私がたどり着いた解決策は次のとおりです。
dataToString()
をオーバーライドして、データ配列内のこれらの種類のオブジェクトをチェックします(私の場合、これらのオブジェクトがどのように見えるかを知っているので可能です)。オブジェクトが存在する場合は、特別な値を返します。存在しない場合は、親メソッドに渡します。私は同様の問題を抱えていて、でgarbgecollactorを無効にすることによって
PHPStorm =>構成の編集=>インタープリターオプション:-d zend.enable_gc = 0
または、コマンドラインからテストを実行している場合は、次を追加してみてください。
-d zend.enable_gc = 0
セグメンテーション違反が発生したら、PHPを最新バージョンにアップグレードします。パッケージマネージャーの最新版だけでなく、php.netで入手可能な最新版もアップグレードします。それでもセグメンテーション違反が発生する場合は、この問題はPHP自体ではまだ修正されていません。古いバージョンのPHPであった可能性があるため、わざわざセグメンテーション違反を取り除こうとしないでください。新しいものですでに修正されています。
次のステップは、問題を特定することです。何も削除できなくなるまで、テストをどんどん小さくしていきます(ただし、セグメンテーション違反は発生します)。それがある場合は、テストをセグメンテーション違反のあるスタンドアロンのphpスクリプトに移動します。これで、PHPバグトラッカーにバグのテストスクリプトができました。
私は同じ問題を抱えていて、それを突き止めることができました。それは、定義されていないクラス変数を書き込もうとしたことです。
セグメンテーション違反を引き起こした私のクラス(それはcakePHPクラスです):
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');
}
}
2番目の変数を追加して修正しました。
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でコードを実行した場合と、他の環境で実行した場合とでは異なるようです。
Laravel内のPHPunitに関連して誰かがこれに遭遇した場合
問題が何であるかを理解するのに少し時間がかかりました。私は現在のコードと以前のリビジョンとの違いを調べていて、試行錯誤を繰り返してようやくそこにたどり着きました。
私は2つの異なるモデルを持っていましたが、どちらもprotected $with
オーバーライド。
これは、phpunitが処理できないある種のループを引き起こしていたに違いありません。
うまくいけば、誰かがこれが役に立つと思うでしょう。
以下は、私にとって同様の問題を修正しました(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
私も同じ問題に直面しました。 PHPUnitを4.1バージョンにアップグレードして(テストを実行するため)、Isaacが指摘したように、オブジェクトを表示することができました。
したがって、これとまったく同じ問題が発生した場合は、PHPUnit> = 4.1にアップグレードすると、「セグメンテーション違反」メッセージが表示される代わりにエラーが表示されます。
https://stackoverflow.com/a/38789046/24679 に加えて、これは私を大いに助けました:
PHP function gc_disable();
を使用できます
PHPUnit bootstrapコードにもini_set('memory_limit', -1);
を使用して配置しました
同じオブジェクトを指すプロパティを持つオブジェクト、または他の種類のポインタループがある場合、実行中にこのメッセージが表示されます
serialize($object);
そして、あなたがLaravelユーザーであり、モデルを扱っている場合。そして、考えれば、$hidden
プロパティを使用してポインタループを回避するため、この問題が発生することはありません。モデルには、$hidden
プロパティはserialize
には影響せず、JSON
とarray
へのキャストにのみ影響することに注意してください。
モデルをMailable
オブジェクトのプロパティに保存したときに、この問題が発生しました。
で修正
$this->model->refresh();
__construct
メソッドで、オブジェクト全体がシリアル化される直前。
コードカバレッジで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
上記のパスの現在のxdebug.so
を Komodo Remote Debugging Package の最新バージョンに置き換えました。対応するダウンロード済みパッケージのサブフォルダーはPHP =私が持っているバージョン(私にとっては5.5)で、すべてが機能しました。