web-dev-qa-db-ja.com

phpunit-テストはひどく遅い

私はユニットテストの世界でますます深く潜っています。

私が遭遇した1つの問題、これがフィードバックが必要な場所です。複数のテストスイートを実行するときです。たぶんそれは私だけですが、テストに合格するにはパラメーター--process-isolationを使用する必要があります。すべてのスイートを問題なく個別に実行できますが、これまでのところ、アサーションが180に分散している6〜7個のスイートを実行すると、-process-isolationなしで実行すると失敗します。問題は、このパラメーターを使用すると、通常の2.5分間ではなく、35分間テストが最後に実行されることです。ちょっと待ってください。

この問題は、特定のテストでモックDIコンテナーを使用することに関連しており、テストスイートがチェーンで実行されている場合、コンテナーが適切に再初期化されません。予想される失敗をテストするためにDI-Containerに設定された静的プロパティは、次のスイートのテストを失敗させます。コンテナーには、静的varに含まれるオブジェクトを保持できるパラメーターがあり、呼び出しごとに同じインスタンスを返します。変装したシングルトン。そして、これはアプリケーションレベルで問題なく実行されます。これは、テストの煩わしさです。

そのコンテナーパラメーターを回避し、静的プロパティを使用しないようにアプリケーションをコーディングすることはできますが、方法論のために有用な言語構造を回避することはやり過ぎのようです。

たぶん私は何か間違ったことをしているでしょう(確かにそうだと思います!)が、すべてのテストに対してSUTをクリーンな状態でテストを実行したい場合、--process-isolationを使用して回避することはできないという印象があります。これにより、テストに非常に時間がかかり、喜びが少しなくなります。コーディング時にスイートとテストを個別に実行し、主要なコミットの前にバックグラウンドでスイートを実行することで、問題を多少回避しました。

私が通常経験しているものはありますか?これに対抗する方法はありますか?テスターはどのようにしてテスト時間を合理的に確保していますか?テストに影響を与えないように、静力学はどのように処理されますか?

どんな洞察も高く評価されました/コメントは高く評価されました。

44
stefgosselin

あなたにはいくつかの問題があります。

1つはプロセスの分離です。通常、これは必要ではないはずであり、どのテストが致命的にテストを破壊するものであるかを見つけるためにそれを使用したいだけです。ご存知のように、速度は非常に遅いため、修正できません。ただし、グローバル変数のバックアップを無効にするとすると、テストごとに数ミリ秒節約できます。

最初の問題につながる2番目の問題は、静的変数がテスト中に保持されるため、コードをテストできないことです。これは最も嫌われているシングルトン問題です。依存関係コンテナに「クリーンアップ」または「リセット」メソッドを提供することで、この問題を解決できます。これらは、メインのテストケースクラスのsetUp()メソッドから呼び出され、すべてをクリーンな状態にリセットします。

速度

テストの実行時間に関して-私は最近、どのテストが遅すぎるかを見つけることについて ブログエントリ を書きました。一般に、ファイルを保存した後でテストを実行できない場合、または各ボックスで各コミットを実行した場合、テストは遅すぎます。 10秒は私にはほとんど受け入れられません。テストが多いほど、実行速度は遅くなります。

実際に35分ある場合は、テストを賢明なグループに分割して、必要なテストを自分のマシンで実行できるようにします-変更したコードをテストするテストのみ。次世代のPyrus PEARインストーラー)は、変更したファイルに応じて 実行する必要のあるテストを自動的に検出して実行する の気の利いた機能を備えています。PHPUnitそれはありませんが、手動でphpunit --group ..をエミュレートできます:)

常に、Webサービスとデータベースのモックを作成するか、少なくとも、単一のテストごとに必要なデータのみを使用してデータベースを実行します。ユーザーをデータベースに保存できるかどうかを確認するテストでWebサービスの応答を3秒間待つのは、決して望まないことです。

34
cweiske

SQLiteの_:memory:_ではなくMySQLでテストするときに私が通常行うことの1つは、_tests/CreatesApplication.php_内にHash::setRounds(5);を追加することです。私はこれを経験して、特にMySQLでのテストを非常に速くします:

_public function createApplication()
{
    $app = require __DIR__ . '/../bootstrap/app.php';

    $app->make(Kernel::class)->bootstrap();

    // TODO: DON'T FORGET TO IMPORT HASH OBJECT ON TOP
    Hash::setRounds(5);

    return $app;
}
_
4
Hassan Azimi

いくつかのトリック。

  1. たとえば、onwファイルをテストする場合は、テストケースをフィルタリングします。

    phpunit --filter 'Default_My_Test'

  2. Phpunit.xmlファイルのコードカバレッジを削除します。コードカバレッジを取得する場合は、次の操作を行います。

    phpunit --coverage-html ./report reportTest

2