4

この質問:特定の順序で PHPUnit テストを実行する には、私が同意する受け入れられた回答がありますが、設計上の問題は PHP と PHPUnit にあります。

私がテストしているプロジェクトでは、ZF2 と Doctrine を使用しています。AbstractHttpControllerTestCase には、ZF2 アプリケーションをインスタンス化し、Response オブジェクトを作成するすべての手順を実行する "dispatch" メソッドがあります。これらのテストには @covers のアノテーションが付けられ、テスト中に実行中のリクエストによって他のメソッドがカバーされないようにします。リクエストには、あらゆる種類のサービスを使用するビュー ヘルパーを呼び出すビュー スクリプトが含まれる場合があるため、特定のリクエストで使用されるすべてのサービスをモックすることは不可能になります (そして、このコードをコピーしてテストごとに維持するのは面倒になります)。

PHPUnit には、別のプロセスでテストを実行する機能があります。これは、新しい PHP インスタンスをフォークし、コンパイル済みのコード テンプレート (奇妙なもの) を供給することによって実行されます。次に、get_included_files() によってリストされたすべてのファイルが含まれます。これには、オートローダーにヒットしたすべてのものが含まれます。preserveGlobalState が無効になっていても、以前のすべてのテストで変更されたすべてのものが新しいプロセスに含まれます。

一部の依存関係 (composer を介してインストール) は、静的メソッド、final とマークされたクラス、またはその両方を使用します。静的メソッドは PHPUnit でモックできます。最終クラスは Mockery を使用してオーバーロードする必要があります。これは、PHPUnit が最終クラスのモック オブジェクトの作成を完全に拒否するためです。クラスと関数のオーバーロード (ネームスペース トリックを使用) は、後続のテストに影響を与えないように、別のプロセスで実行する必要があります。ここまでは順調ですね。

依存関係をオーバーロードするテストを入力して、静的メソッド (final とマークされているかどうかにかかわらず) に期待を設定するか、まだインスタンス化されていないオブジェクトに期待を設定します。これは、以前のテストのいずれも、オーバーロードして期待値を設定するクラスに触れていない場合にのみ機能します。そうしないと、「クラスを再宣言できません」というエラーで失敗します。PHPUnit は、サブプロセスでテスト環境を再作成するためにすべてを含めて役立つように努めましたが、その結果、テスト ケースが台無しになりました。

したがって、たとえば「@group isolated」でテストをマークし、PHPUnit を 2 回呼び出すことなく、他のテストの前にそれらのテストを実行することは非常に便利です (不便なだけでなく、カバレッジ分析が台無しになります)。

あるいは、PHP 5.5 に既に存在するクラスをオーバーライドする方法があれば、問題のあるテスト ケースの前提条件を修正することができます。しかし、それはおそらく起こらないでしょう (いずれにせよ、ランキットは受け入れられる答えではありません)。

4

0 に答える 0