web-dev-qa-db-ja.com

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

私は誰かとウェブアプリケーションとのユニット/統合テストについて話し合ったことがありますが、1つのコアアイデアについて意見の相違があります。問題は、私が話している人が、単体テストで使用するデータベースにデータが事前に入力されている必要があり、テストが実行される前後に完全に空である必要があると考えていることです。

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

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

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

テスト対象のデータが適切なテスト可能なテストであることを確認する他の方法はありません。

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

25
ryanzec

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

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

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

あなたのベストプラクティスは、進むべき道であり、私がしがちなことは、悪いデータのシナリオを見つけた場合、その正確なシナリオでセットアップとティアダウンを行う統合テストを書くことです。

22
Nicholas Mayne

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

したがって、テストでデータの状態を考慮している場合は、データをその既知の状態にして、テストの実行後にデータをその状態に戻し、テストを再現できるようにします。

モックによってデータの状態からテストを切り離すことができれば、それも良いことです。ユニット/統合テストを行っているとおっしゃっていますが、もちろんこれら2つは個別に検討する必要があります。ユニットテストは可能な限りデータベースから切り離し、統合テストはデータベースを既知の状態でテストする必要があります。

6
Paddyslacker

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

私は何も切り捨てないことを除いて、あなたはテストがどのように書かれるべきかについて正しいです:

  • セットアップフェーズ:データベースへの接続を取得し、データを挿入する
  • 実行フェーズ
  • 分解フェーズ:挿入されたデータを削除(切り捨て)

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

3
Jalayn

同僚と例を絞り込んで、それらが正確に何を意味するのかを知る必要があると思います。両方とも同じページにいる可能性があります。

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

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

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

1
JeffO

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

注:私のコメントは特にデータベーステストに関するものであり、UIテストではありません(明らかに同様です)。

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

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

フロントエンドやレポートのテストと同様に、データベースのテストにも同様の厳格さが適用されることにほとんどの人が同意すると思います。

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

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

単体テスト

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

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

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

(ユニット)統合テスト

私は このSEの投稿 がさまざまな種類のテストについて話すのに役立つことを発見しました。

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

単体テストからこれらの統合テストに移行する場合、さまざまなテストケースをテストするために、データが少し増えることがよくあります。明らかに、これらのテストは本番データベースでは実行できません。

次に、System TestingSystem Integration Testing(aka end- 2エンドテスト)。データ量とスコープが増加します。これらすべてのテストは、回帰テストフレームワークの一部になるはずです。 これらのテストの一部は、ユーザーによってUATの一部として実行されるように選択される場合がありますが、UATはusers、ITの定義ではない-よくある問題!

だから私はいくつかのコンテキストを与えたので、あなたの実際の質問に答えるために

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