11

テストに使用するダミーデータをどのように管理していますか? それらをそれぞれのエンティティと一緒に保管しますか? 別のテスト プロジェクトで?外部リソースからシリアライザーでそれらをロードしますか? それとも、必要に応じて再作成しますか?

それぞれがエンティティを含む別のモジュールに依存するいくつかのモジュールを持つアプリケーション スタックがあります。各モジュールには独自のテストがあり、実行にはダミー データが必要です。

多くの依存関係を持つモジュールには、他のモジュールからの多くのダミー データが必要になります。ただし、それらはテストリソースの一部であるため、ダミーオブジェクトを公開しないため、すべてのモジュールが必要なすべてのダミーオブジェクトを何度もセットアップする必要があります。

また、エンティティのほとんどのフィールドは null 許容ではないため、オブジェクト レイヤーに対してトランザクションを実行する場合でも、値を含める必要があり、ほとんどの場合、一意性、長さなどの制限があります。

これを回避するベスト プラクティスの方法はありますか、それともすべてのソリューションが妥協しているのでしょうか?


もっと詳しく

スタックは次のようになります。

1 つのモジュール:

src/main/java --> gets jared (.../entities/*.java contains the entities)
src/main/resources --> gets jared
src/test/java --> contains dummy object setup, will NOT get jared
src/test/resources --> not jared

Maven を使用して依存関係を処理します。

モジュールの例:

  • モジュール Aにはいくつかのダミー オブジェクトがあります
  • モジュール Bには独自のオブジェクトが必要であり、かつモジュール A と同じ

オプション a)

テスト モジュールTは、すべてのダミー オブジェクトを保持し、すべてのモジュール内のすべてのテストにテスト スコープでそれらを提供できます (したがって、ロードされた依存関係は jared になりません)。それはうまくいきますか?意味: TAにロードしてAでインストールを実行すると、 Tによって導入された参照、特にBによって導入された参照は含まれませんか? ただし、AはBのデータモデルについて知っています。

オプション b)

モジュール A は、AがBのダミー データについて知らない間に、 Bがそれらを取得src/main/java../entities/dummyできるようにするためのダミー オブジェクトをどこかに提供します。

オプション c)

すべてのモジュールには、シリアル化されたダミー オブジェクトである外部リソースが含まれています。それらは、それらが属するモジュールに依存しているため、それらを必要とするテスト環境によって逆シリアル化できます。ただし、これにはすべてのモジュールがダミーオブジェクトを作成してシリアル化する必要がありますが、どのようにそれを行うのでしょうか? 別の単体テストを使用して単体テスト間に依存関係が発生する場合、またはスクリプトを使用すると、デバッグが難しくなり、柔軟性がなくなります。

オプション d)

モック フレームワークを使用し、必要に応じてテストごとに必須フィールドを手動で割り当てます。ここでの問題は、エンティティのほとんどのフィールドが null 許容ではないため、セッターまたはコンストラクターを呼び出す必要があり、最初からやり直してしまうことです。

望まないこと

必要なオブジェクトの構造は常に変化するため、静的データを使用して静的データベースをセットアップすることは望ましくありません。今はたくさん、あと少し。したがって、休止状態ですべてのテーブルと列をセットアップし、単体テスト時にそれらにデータを入力する必要があります。また、静的データベースは多くの潜在的なエラーとテストの相互依存性をもたらします。


私の考えは正しい方向に進んでいますか?大量のデータを必要とするテストに対処するためのベスト プラクティスは何ですか? いくつかの他のモジュールからのある種のデータで満たされたオブジェクトを必要とするいくつかの相互依存モジュールがあります。


編集

2 番目の回答に応じて、現在どのように行っているかについての詳細情報:

簡単にするために、 、 、 の 3 つのモジュールがPersonありProductますOrder。 オブジェクトPersonを使用していくつかのマネージャー メソッドをテストします。MockPerson

人/src/test/Javaで:)

public class MockPerson {

    public Person mockPerson(parameters...) {
        return mockedPerson;
    }
}

public class TestPerson() {
    @Inject
    private MockPerson mockPerson;
    public testCreate() {
        Person person = mockPerson.mockPerson(...);
        // Asserts...
    }
}

クラスはMockPersonパッケージ化されません。

同じことが製品テストにも当てはまります。

( product/src/test/java内:)

public class MockProduct() { ... }
public class TestProduct {
    @Inject
    private MockProduct mockProduct;
    // ...
}

MockProduct必要ですが、パッケージ化されません。

注文テストには と が必要MockPersonになるMockProductため、現在、 と の両方を作成してMockOrderテストする必要がありますOrder

(順番に/src/test/java :)

これらは重複Personしているため、変更のたびに変更する必要がありProductます

public class MockProduct() { ... }
public class MockPerson() { ... }

これはここにあるべき唯一のクラスです:

public class MockOrder() { ... }

public class TestOrder() {
    @Inject
    private order.MockPerson mockPerson;
    @Inject
    private order.MockProduct mockProduct;
    @Inject
    private order.MockOrder mockOrder;
    public testCreate() {

        Order order = mockOrder.mockOrder(mockPerson.mockPerson(), mockProduct.mockProduct());
        // Asserts...
    }
}

問題は、更新する必要がperson.MockPersonあり、order.MockPersonいつでもPerson変更されることです。

とにかく依存関係がある他のすべてのテストが Mock.mock を呼び出して適切にセットアップされたオブジェクトを取得できるように、Mocks を jar と共に公開する方がよいのではないでしょうか? それとも、これは暗黒面ですか? 簡単な方法ですか?

4

3 に答える 3

3

さて、これまでの全ての評価をじっくり読みましたが、とても良い質問です。問題に対する次のアプローチが見られます。

  1. (静的) テスト データベースをセットアップします。
  2. 各テストには、単体テストを実行する前に (動的) テスト データを作成する独自のセットアップ データがあります。
  3. ダミーまたはモック オブジェクトを使用します。すべてのモジュールはすべてのダミー オブジェクトを認識しているため、重複はありません。
  4. 単体テストの範囲を縮小します。

最初のオプションは非常に簡単で、多くの欠点があります。データモジュールに変更がある場合、誰かがそれを再現する必要があります.多くのメンテナンス オーバーヘッド。言うまでもなく、最初の手でこのデータを生成するのは難しいかもしれません。2 番目のオプションも参照してください。

2 番目のオプションでは、テストの前に、エンティティを作成する「コア」ビジネス メソッドのいくつかを呼び出すテスト コードを記述します。理想的には、テスト コードは製品コードから独立している必要がありますが、この場合、2 回サポートしなければならない重複コードになってしまいます。場合によっては、単体テストのエントリ ポイントを確保するために、運用ビジネス メソッドを分割することをお勧めします (私はそのようなメソッドを非公開にし、リフレクションを使用してそれらを呼び出します。また、メソッドに関する注釈が必要です。リファクタリングは少しトリッキーになりました)。 . 主な欠点は、「コア」ビジネス メソッドを変更する必要がある場合、突然すべての単体テストに影響を与え、テストできなくなることです。したがって、開発者はそれを認識し、「コア」ビジネス メソッドに対して部分的なコミットを行うべきではありません。また、この領域に何らかの変更を加えた場合、「それが単体テストにどのように影響するか」を念頭に置いておく必要があります。また、必要なすべてのデータを動的に再現することが不可能な場合もあります (通常、これはサードパーティ API が原因です。たとえば、いくつかのキーを使用する必要がある独自の DB を使用して別のアプリケーションを呼び出します。このキー (関連するデータ) はサードパーティのアプリケーションを介して手動で作成されます. このような場合, このデータとこのデータのみ, 静的に作成する必要があります. たとえば、作成した 10000 キーは 300000 から始まります. いくつかのキーを使用するために必要な独自のDB。このキー (関連データを含む) は、サードパーティのアプリケーションを介して手動で作成されます。このような場合、このデータのみを静的に作成する必要があります。たとえば、300000 から始まる 10000 個のキーを作成したとします。いくつかのキーを使用するために必要な独自のDB。このキー (関連データを含む) は、サードパーティのアプリケーションを介して手動で作成されます。このような場合、このデータのみを静的に作成する必要があります。たとえば、300000 から始まる 10000 個のキーを作成したとします。

3番目のオプションは良いはずです。オプション a) と d) は、私にはかなり良さそうです。ダミー オブジェクトには、モック フレームワークを使用することも、使用しないこともできます。Mock Framework は、あなたを助けるためだけにここにいます。あなたのユニットのすべてがあなたのすべてのエンティティを知っているという問題はありません。

4 番目のオプションは、単体テストで「単体」とは何かを再定義することを意味します。相互依存関係のあるモジュールがいくつかある場合、各モジュールを個別にテストするのは難しい場合があります。このアプローチは、最初にテストしたのは統合テストであり、単体テストではないことを示しています。そのため、メソッドを分割し、別のモジュールへの相互依存関係をすべてパラメーターとして受け取る小さな「作業単位」を抽出します。このパラメータは (できれば) 簡単にモックアップできます。このアプローチの主な欠点は、すべてのコードをテストするわけではなく、いわば「焦点」だけをテストすることです。統合テストは別途行う必要があります (通常は QA チームによる)。

于 2012-01-20T14:04:20.527 に答える
3

これは当てはまる場合と当てはまらない場合があります。ダミー オブジェクトと関連するセットアップ コードの例を見てみたいと思います。(それがあなたの状況に当てはまるかどうかをよりよく理解するためです。)しかし、私が過去に行ったことは、この種のコードをテストにまったく導入することさえしていません。あなたが説明したように、作成、デバッグ、特にパッケージ化と保守は困難です。

私がよく行ったこと (Java での私の知る限り、これがベスト プラクティスです) は、テスト データ ビルダーの投稿でナット プライスが説明しているように、テスト データ ビルダー パターンを使用することです。

これがある程度関連していると思われる場合は、以下を確認してください。

于 2012-01-14T01:54:52.647 に答える
1

テスト アプローチを変更しても問題を解決できなかったのではないかと思います。

他のモジュールに依存するモジュールの単体テスト、およびそのため、他のモジュールのテストデータに依存するモジュールの単体テストは、実際の単体テストではありません!

テスト中のモジュールのすべての依存関係にモックを挿入して、完全に分離してテストできるようにするとどうなるでしょうか。次に、依存する各モジュールに必要なデータがある完全な環境をセットアップする必要はありません。実際にテストするモジュールのデータのみをセットアップします。

ピラミッドを想像すると、ベースは単体テストであり、その上に機能テストがあり、その上にいくつかのシナリオ テストがあります (Google では、小、中、大のテストと呼んでいます)。

モック化された依存関係は完全に構成可能であるため、すべてのコード パスをテストできる膨大な量の単体テストがあります。その後、個々のパーツを信頼することができ、機能テストとシナリオ テストで実行されるのは、各モジュールが他のモジュールに正しく配線されているかどうかをテストすることだけです。

これは、モジュール テスト データがすべてのテストで共有されるのではなく、グループ化されたいくつかのテストでのみ共有されることを意味します。

cwash で言及されている Builder パターンは、機能テストに確実に役立ちます。完全なオブジェクト ツリーを構築し、各プロパティのデフォルト値を生成するように構成された .NET Builder を使用しているため、これをデータベースに保存すると、必要なすべてのデータが存在します。

于 2012-01-20T09:27:36.220 に答える