データベースとユニット/統合テスト


25

Webアプリケーションを使用したユニット/統合テストについて誰かと話し合いをしましたが、1つのコアアイデアについて意見の相違があります。問題は、ユニットテストの対象となるデータベースにデータを事前に入力しておくべきだと考えている人が話していることであり、テストの実行前後に完全に空である必要があると思います。

データベースに事前入力されたデータに関する私の懸念は、データが良好な状態に維持されることを確認する方法がないことです。テスト自体はデータベース内のデータを作成、削除、変更するため、テストを開始する前にデータベースにデータを保持するのは良いことではありません。

データベースの機能をテストする最良の方法は、次のセットアップを行うことです。

  1. テストを実際に実行する前の「セットアップ」フェーズでは、まずデータベース内のすべてのテーブルを切り捨てます
  2. 次に、実行しようとしているテストケースに必要なすべてのデータを挿入します
  3. 次に、テストケースを実行して検証します
  4. 次に、「ティアダウン」フェーズで、データベース内のすべてのテーブルを再度切り捨てます

テスト対象のデータがテスト可能な優れたテストであることを保証する他の良い方法はありません。

ここに何かが足りませんか?これは、データベース関連の機能をテストする最良の方法ではありませんか?(テストを開始する前、またはテストが完了した後でも)データベースに常に存在するデータベースを事前に設定しておくと、メリットがありますか?私のプロセスを異なる方法で説明して、私のポイントをよりよく理解するためのアイデアの助けも素晴らしいでしょう(つまり、私のポイントにメリットがある場合)。


回答:


21

私にとって、単体テストはデータベースを扱うべきではなく、統合テストはデータベースを扱うべきです。

データベースを扱う統合テストは、実際にはティアアップおよびティアダウンのアプローチで空のデータベースを使用する必要があります。トランザクションベースのアプローチを使用するのは非常に良い方法です(つまり、セットアップでトランザクションを作成し、ティアダウンでロールバックします)。

友達がやりたいように聞こえるのは、「回帰」の観点からテストすることです。つまり、そこに実際のデータがあり、システムがどのように反応するかを確認します。ドメインモデルのいくつかの癖。

あなたのベストプラクティスは進むべき道であり、私がしがちなのは、不良データのシナリオを見つけたら、セットアップを使用して統合テストを作成し、その正確なシナリオで分解することです。


私はユニットがモックされたデータを使用し、統合がデータベースを使用する必要があると聞いていることに加えて、ユニットテストと統合テストの違いは確かだと思います(別のスレッドプログラマを開始しました。 )。それ以外は、あなたが言っていることはすべて、私が考えていることと一致しているようです。
ライアンゼック

問題ありません。他の回答に詳細を追加しました
ニコラスメイン

1
なぜDBを単体テストできないのですか?SQLをストアドプロシージャに入れると、テスト定義のデータを使用してSQLを単体テストすることができ、突然すべてが簡単になります。これは間違いなく、より多くの人が従うべきベストプラクティスです。MSの言う
gbjbaanb

1
integration tests- どういう意味ですか?私は、データベースを使用しているモジュールに述べたようにすべきであるユニットテストでテストします。データベースを手動でモックするか、メモリ内実装に置き換えることができます
-hellboy

6

テストがデータベースに依存している場合、データベースが空であるよりも、気になるデータがテストのために既知の状態にあることがより重要だと思います。適切なテストの尺度の1つは、各テストが1つの理由で失敗し、他のテストが同じ理由で失敗しないことです。

そのため、テストでデータの状態を考慮する場合、データをその既知の状態にし、テストの実行後にデータをその状態に戻すと、テストが再現可能になります。

モックによってデータの状態からテストを切り離すことができれば、それも良いことです。あなたはユニット/統合テストをしていると言いますが、もちろんこれら2つのことは別々に考慮されるべきです。可能な場合は単体テストをデータベースから切り離し、統合テストは既知の状態のデータベースでテストする必要があります。


2

事前にデータベースが作成されていることの利点の1つは、必要なデータが挿入されているため、必要なデータを挿入するコードを記述する必要がないことです。そうでなければ、欠点のみがあります。誰かがデータベースのテストデータを変更したのでしょうか?たぶん誰かがデータを更新しようとしましたか?しかし、さらに悪いことは、1つのテストケースがデータベースをひどく台無しにしていることです。データベース全体を手動で数回再作成することになります。

私は何も切り捨てないことを除いて、テストの作成方法は正しいです。

  • セットアップフェーズ:データベースへの接続を取得し、データを挿入します
  • 実行段階
  • ティアダウンフェーズ:挿入されたデータを削除(切り捨て)

現在、このシナリオは単体テストに最適です。単体テストと統合テストの両方にデータが必要な場合、すべてのテストケースに共通の1つの大きなセットアップフェーズ(すべての「挿入」を1つの静的メソッドに再グループ化)も非常にうまく機能することがわかりました。それはあなたのアイデアとあなたの友人のアイデアの中間点のようなものです。唯一の欠点は、既存のテストケースを壊さないために、新しいデータを追加するときに非常に注意する必要があることです(ただし、テーブルごとに2行から3行のように追加する場合は、問題になりません)


誰かがエラーを引き起こすような方法で誤ってデータを変更するよりも、テストに必要なデータベースの各部分を作成するのではないでしょうか?テストが失敗したときにデータが正しいことを確認しなければならないことは、防ぐことができる何かのように思えます。
ライアンゼック

1
さまざまなテストケースに役立つデータを挿入する大きなセットアップフェーズは、連携して動作するアプリケーションのさまざまな部分を確認する必要がある統合テストにのみ役立つ場合があります。他の統合テストでそれらのいくつかが必要になる可能性が高いため、この大きな「挿入」の一般的なセットを持つ価値があります。それ以外の場合、純粋な単体テストだけを話しているのであれば、テストケースごとに1セットのデータを挿入することは絶対に必要です。
ジャレイン

1

同僚と例を絞り込み、その意味を正確に把握する必要があると思います。両方が同じページにいる可能性があります。

例:アカウントトランザクションテーブルの確認

  1. トランザクションのないユーザー/アカウントについてこのテーブルの表示をテストしませんか?
  2. 最初のレコードの追加をテストし、残高を作成できるかどうかを確認します。
  3. 既存のレコードがある場合にレコードを作成し、ランニングバランスおよびその他のビジネスルールを確認します。
  4. 既存のレコードと他のすべてのCRUDを含む表を表示します。

手順1と2を実行することでこれを達成するか、既にこの状態のデータベースから開始するか(バックアップを復元しますか?)、それが重要かどうかわかりません。私にスクリプトを作成するというあなたのアイデアは、必要な変更を管理しやすくします(管理者アカウントを作成するのを忘れて新しいユーザーに必要な場合と同様です)。スクリプトファイルは、一部のバックアップファイルよりもソース管理の方が簡単です。これは、このアプリを配布するかどうかにも影響されます。


0

いくつかの回答の側面をまとめて、2pを追加するには...

注:私のコメントは、特に UIテストではなく、データベーステストに関連しています(ただし、明らかに同様に適用されます)。

データベースは、フロントエンドアプリケーションと同じくらいテストする必要がありますが、「フロントエンドで動作しますか?」に基づいてテストされる傾向があります。または「レポートは正しい結果を生成しますか?」、私の意見では、データベース開発のプロセスの非常に遅いテストであり、あまり堅牢ではありません。

通常のUAT /パフォーマンス/その他に加えて、データウェアハウスデータベースのユニット/統合/システムテストを利用するクライアントが多数あります。テスト。彼らは、継続的な統合と自動テストにより、従来のUATに到達する前に多くの問題を拾い上げ、UATの時間を節約し、UATが成功する可能性を高めることに気付きました。

フロントエンドまたはレポートのテストに関して、データベースのテストに同様の厳密さを適用する必要があることにほとんどの人が同意するはずです。

テストで重要なことは、エンティティの複雑な組み合わせに進む前に、小さな単純なエンティティをテストして正確性を確認し、より広いシステムに拡張する前に正確性を確認することです。

だから私の答えにいくつかのコンテキストを与える...

単体テスト

  • テーブル、ビュー、関数、ストアドプロシージャなど、ユニットが機能することを証明するためのテストの焦点がある
  • インターフェイスを「スタブ」して、外部の依存関係を削除する必要があります
  • 独自のデータを提供します。データの既知の開始状態が必要です。そのため、事前テストのデータが存在する可能性がある場合は、ポピュレーションの前に切り捨て/削除を行う必要があります。
  • 独自の実行コンテキストで理想的に実行されます
  • 自動的にクリアし、使用したデータを削除します。これは、スタブが使用されていない場合にのみ重要です。

これを行う利点は、テストのすべての外部依存関係を削除し、正確性を証明するために最小限のテストを実行することです。明らかに、これらのテストは運用データベースでは実行できません。ユニットの種類に応じて、次のようなさまざまな種類のテストが行​​われる場合があります。

  • スキーマチェック、これを「データコントラクト」テストと呼ぶ人もいます
  • 通過する列値
  • 関数、プロシージャ、ビュー、計算列のデータの異なる値を使用した論理パスの実行
  • エッジケーステスト-NULL、不正なデータ、負の数、大きすぎる値

(ユニット)統合テスト

私が見つかりました。このSEが投稿テストの様々なタイプの話をするのに役立ちます。

  • ユニットが統合されることを証明するためのテストに焦点を当てています
  • 多数のユニットで一緒に実行
  • インターフェイスを「スタブ」して、外部の依存関係を削除する必要があります
  • 外部データの影響の影響を除去するために、独自のデータを提供します
  • 独自の実行コンテキストで理想的に実行されます
  • 自動的に消去され、作成されたデータを削除します。これは、スタブが使用されていない場合にのみ重要です。

単体テストからこれらの統合テストに移行する場合、より多様なテストケースをテストするために、わずかに多くのデータが存在することがよくあります。明らかに、これらのテストは運用データベースでは実行できません。

これは、システムテストシステム統合テスト(エンドツーエンドテストとも呼ばれます)に進み、データ量とスコープが増加します。これらのテストはすべて、回帰テストフレームワークの一部になる必要があります。これらのテストの一部は、ユーザーがUATの一部として実行するために選択する可能性がありますが、UATはユーザーによって定義されたテストであり、ITによって定義されたものではありません-一般的な問題です!

あなたの実際の質問に答えるために、コンテキストを与えました。

  • ユニットおよび統合テストのデータを事前に入力すると、誤ったテストエラーが発生する可能性があるため、避ける必要があります。
  • 一貫したテストを保証する唯一の方法は、ソースデータに関する仮定をせず、厳密に制御することです。
  • あるテスターが、ソース管理されたデータベースコードの異なるブランチで同じテストを実行する別のテスターと競合しないようにするために、個別のテスト実行コンテキストが重要です。

-3

率直に言って、既存の本番データベースとほぼ同じサイズのデータ​​ベースなしで単体テストを行うと、テストに合格し、本番環境でパフォーマンスに失敗するものが多くなると思います。もちろん、この理由から、小さなローカルデータベースを開発する人に対しても反対です。

また、コードがデータ固有の場合、どのようにデータなしで効果的にテストできますか?クエリが正しい結果を返したかどうかを見逃すことになります。クエリが正しい場合ではなく、構文が正しいかどうかを確認するだけで、空のデータベースに対するテストを検討する必要がある場合があります。それは近視眼的のようです。私は、カテゴリー的に間違っているテストを実行して合格するものを見すぎました。単体テストでそれを見つけたくありませんか?私がやります。


空のデータベースに対して実行することはお勧めしません。手順2が表示された場合、「実行するテストケースに必要なすべてのデータを挿入します」と表示されます。パフォーマンスの問題については、それが単体テストの目的ではなく、より多くの負荷テストだとは思いません。コードの論理が機能することを確認するために、単体テストをテストします。論理的に機能する場合は、同じ基本データの1レコードまたは100,000,000,000レコードで機能します(かなり遅いと考えられます)。
ライアンゼック

データベースクエリは単に論理的なものではなく、すぐにそれが機能しないことがわかります。1つのレコードで機能するものは、しばしばprodでタイムアウトになり、単体テストでは可能な限り早くそれが示されます。
HLGEM

単体テストと統合テストは機能に関するものであり、パフォーマンスではないため、少量のデータでテストできます
-user151019

単体テストではデータベースを使用しないでください-統合テストではデータベースを使用します。
ニコラスメイン

1
実際に話しているのは負荷テストです。受け入れテストのセットがあり、それらを負荷テストツールにフックした場合、目的の効果を達成できます。
ニコラスメイン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.