各ユニットテストは、他のテストとは独立して実行できる必要がありますか?


24

クラスの2つのメソッドのテストがあるとします。最初の方法では、別の層からデータを収集し、ランタイムに依存しない何らかの種類のストレージ(SQLテーブルなど)に格納するため、このテストで処理されるすべてのデータはテストにハードコーディングされます。2番目のメソッドは、最初のメソッドがデータを残した場所からデータを取得し、何らかの方法で変換(計算、特定の部分を他の場所に移動するなど)を担当します。

この2番目の方法では、最初の方法と同様に入力をハードコーディングするか、2つのテストを連続して実行し、最初のテストで実際に保存されたデータを取得して、1番目のテストが中断した場所から再開できると想定できます。

2番目のオプションを選択した場合、2つの方法がうまく機能するというのは本当に良い考えですが、1番目のテストが失敗した場合、それ以降のすべてのテストは失敗し、バグをより迅速に特定するのに役立つテストの利点がなくなります。

最初のオプションを選択した場合、各メソッドは独立して分離され、テストされますが、それらが実際に適切に連携できることを本当に知ることはありません。

ここでより良いオプションはどれですか?ハードコーディングを使用して分離されたメソッドごとに単一のテストを実行し、次に両方のメソッドを1つに含むより大きなテストを実行するなど、何らかの方法がありますか?


2
実際に、実行するたびにユニットテストの順序を簡単にランダム化できるといいのですが。現在、それらは比較的固定された順序ではあるが、いくつかの未知の状態で実行されています。
ジョブ

回答:


11

最初のオプションを選択した場合、各メソッドは独立して分離され、テストされますが、それらが実際に適切に連携できることを本当に知ることはありません。

メソッドが完全に独立している場合、これは重要ではありません。2番目の方法は次のとおりです。

a)有効なデータが提示されれば、正しく機能します。

b)無効なデータが提示された場合、合理的かつ一貫して失敗します。

同様に、最初のメソッドも同じことを行う必要があります。したがって、エラーのケースを処理する限り、それらは適切に連携します。

メソッドが正しく機能することをテストする場合、それは単体テストではなく統合テストです。


27

テストを独立して実行できない場合、それらは単体テストではありません。

単体テストは、データベーステーブルの内容などの外部状態に依存しないでください。純粋に1ユニットのコードを単独でテストする必要があります。

特定の状態を変更または必要とするテストは有効であり、たとえば統合テストの一部を形成する場合があります。そのような場合、適切なセットアップが行われていることを確認することが重要ですが、これらは単体テストではありません。この場合、1つのテストで別のテストを実行する必要があることをまだアドバイスしません。この場合は、必要なコードを個別のセットアップメソッドに含める必要があります。たとえば、セットアップコードを呼び出して例外がスローされないことを確認する1つのテストと、セットアップメソッドで設定されたデータをアクティブに使用する別のテストがあります。


@Steve、つまりこの例では、メソッド1に1つのテスト、メソッド2に1つのテスト、同じテストで1と2を実行する1つのテストを言いますか?
モーガンハーロッカー

2
はい。最初の2つは単体テストで、3つ目は統合テストのように聞こえます。
スティーブ

顧客モジュールと注文モジュールがあり、顧客に関係なく注文を作成できない場合。顧客モジュールから独立してテストする方法:sqlを使用してデータベースに顧客レコードを作成(顧客に挿入)するか、Customer.createCustomer()を使用します。また、テストでロジックを実装する必要がないため、2番目のIMHOを使用することをお勧めしますが、顧客を作成するテストに合格した場合にのみ機能します。
ダイニウス

@Dainius。単体テストのシナリオでは、通常、模擬オブジェクトを使用するため、模擬顧客を注文モジュールに渡します。この場合、sqlを使用したくないという点で正しいです。
スティーブ

メソッドBがメソッドAに依存するシナリオでは、ほとんどの場合、Aを呼び出してからBを呼び出すメソッドCが存在するようです。この場合、A、B、Cを個別にテストできます。
モーガン・ハーロッカー

9

ユニットテストBによって残された状態に依存するユニットテストBを使用することは、今のところ大丈夫だと確信しています。しかし、1000年のユニットテストがある今から1年を考慮してください。変更を加える必要があるたびに、テストスイート全体が完了するまで10分間待ちますか?

もちろん開発スタイルにもよりますが、機能を開発する際に個々のテストを何度も実行できる、まともなテスト駆動開発を希望する場合は、各テストに独立した機能を与えることをお勧めします。


1
ラスコルニコフを+1、私はこれが後に「すべてのテストを実行する」とき、これが巨大な時間の沈下になるという事実を考慮しませんでした。
モーガンハーロッカー

3

テストセットアップについて話しているように聞こえますが、これはいくつかの方法で実行できます。各テストのテストデータ(フィクスチャと呼ばれる)のクリーンコピーが必要なため、それぞれが互いに依存しないようにする必要があります。

このタイプのテストを可能にするいくつかのフレームワークと、テストおよびテストスイートの開始および終了時にデータ構造を迅速に構築および破棄できるDBUnitなどのツールがあります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.