ストアドプロシージャの単体テスト


44

私はこれをかなり長い間考えてきました。

基本的な質問は、ストアドプロシージャを単体テストする方法ですか?

私は、古典的な意味で関数のユニットテストを比較的簡単に設定できることを知っています(つまり、ゼロ個以上の引数を取得して値を返します)。しかし、行をどこかに挿入し、挿入の前後にいくつかのトリガーを使用して、一見単純な手順の実際の例を考慮すると、「ユニット」の境界を定義することさえ非常に困難です。INSERT自分自身だけをテストする必要がありますか?それはかなり簡単です、私は思う-比較的低い値で。イベントチェーン全体の結果をテストする必要がありますか?これが単体テストであるかどうかという質問とは別に、適切なテストを設計することは、多くの追加の疑問符が途中で発生する非常に骨の折れる仕事です。

そして、常にデータが変化するという問題が生じます。UPDATE数行以上の影響がある場合、影響を受ける可能性のあるすべての行を何らかの方法でテストケースに含める必要があります。DELETEsなどに関するさらなる困難など。

それでは、ストアドプロシージャをどのように単体テストしますか?完全に絶望的な複雑さの限界がありますか?メンテナンスにはどのようなリソースが必要ですか?

編集 AlexKuznetsovの答えに基づくもう1つの小さな質問:または、それが完全に役に立たないという閾値がありますか?

回答:


32

私たちはこれをほぼ5年間行ってきました。変更を明示的にテストすることは間違いなく実行可能ですが、非常に遅いと思います。さらに、個別のデータベースを使用しない限り、複数の接続からこのようなテストを簡単に同時に実行することはできません。代わりに、修正を暗黙的にテストする必要があります-それらを使用してテストデータの少なくとも一部を構築し、選択が期待される結果を返すことを確認します。

「それらの抜け穴を閉じる:T-SQLの単体テストから学んだ教訓」というタイトルの記事と、いくつかのブログ投稿を書きました。

「複雑さの中に完全に絶望的であるような難題はありますか?」という質問に関して、複雑なモジュールには単純なモジュールよりもはるかに多くのテストが必要です。

メンテナンスを簡素化するために、予想される結果を生成し、それらを別々のファイルに保存します-これは大きな違いをもたらします。


15

はい、イベントチェーン全体を1つのユニットとしてテストする必要があります。したがって、テーブルに挿入していくつかのトリガーを起動するプロシージャを使用した例では、さまざまな入力のプロシージャを評価する単体テストを作成する必要があります。各ユニットテストは、正しい値を返すか、テーブルの状態を正しく変更するか、正しい電子メールを作成するか、そのようなことを行うように設計されている場合は正しいネットワークパケットを送信するかによって、合格または不合格になる必要があります。要するに、ユニットが持つすべての効果を検証する必要があります。

ユニットテストの設計には多少の手間がかかりますが、その作業の大部分はユニットを手動でテストするために行う必要があります。同様に徹底的かつ大幅に簡単にすることができます。

データを変更することでテストはより難しくなりますが、テストがそれほど重要ではなく、実際にユニットテストの価値が上がります。ほとんどの困難は、ユニットに変更が加えられるたびにではなく1回だけ考慮すればよいからです。保存されたデータセット、セットアップ/分解の一部である挿入/更新/削除、および狭いスコープの操作はすべて、これを簡単にするために使用できます。質問はデータベース固有ではないため、詳細は異なります。

ハイエンドまたはローエンドに複雑なしきい値はなく、テストや単体テストを停止する必要はありません。次の質問を検討してください。

  1. 常にバグのないコードを書いていますか?
  2. 小さなユニットには常にバグはありませんか?
  3. 大きなユニットにバグがあっても大丈夫ですか?
  4. 災害を引き起こすにはいくつのバグが必要ですか?

新しいジョブを開始し、多くの場所で使用されている小さな機能を最適化するというタスクがあるとします。アプリケーション全体は、誰も覚えていない従業員によって作成および保守されました。ユニットには通常の予想される動作を説明するドキュメントがありますが、それ以外はほとんどありません。どちらを選びますか?

  • アプリケーションのどこにも単体テストはありません。変更を行った後、ユニット自体に対していくつかの手動テストを実行して、ドキュメントで期待される値がまだ返されることを確認できます。その後、本番環境に展開し、指を交差させて動作することを期待できます(結局、あるユニットでバグのないコードと最適化を常に記述して別のユニットに影響を与えることはありません)、またはアプリケーション全体の学習方法に膨大な時間を費やすことができます動作するため、直接または間接的に影響を受けるすべてのユニットを手動でテストできます。
  • 毎日またはオンデマンドで自動的に実行されるアプリケーション全体の単体テスト。通常の入力値とその期待される応答だけでなく、異常な値と発生する予期される例外もチェックします。変更を行い、アプリケーションの単体テストスイートを実行すると、他の3つのユニットが予期した結果を返さなくなったことがすぐにわかります。そのうちの2つは良性であるため、ユニットテストを微調整してそれを説明します。3つ目は、もう少し微調整と小さな新しい単体テストが必要です。変更を加えると、一連のテスト全体が成功し、自信を持って変更を展開できます。

1
第一に、あなたの答えに感謝します-この質問についてこれ以上の進歩は期待していませんでした...第二に、単純な操作についてあなたが正しいことを認めなければなりません。列の順序を引数と一致させることができるように書かれている場合は問題ないかもしれませんが、あなたは正しいです。おそらく、アプリ全体をテスト体制の下に置く方が良いでしょう。
dezso

@dezsoこれは素晴らしい質問であり、データベースの世界でより多くの露出を必要とする概念です。
リーリッフェル

「イベントチェーン全体を1つのユニットとしてテストする必要があります」-これは、最も直感に反することです。その場合、ユニットではありません。あなたは、統合テストをやっている
ジョー・フィリップス

@Joe Philips-好きなように呼び出します。挿入を実行し、いくつかのトリガーを起動するプロシージャが、自動テストを行う必要があると想定されることを実行します。
リーリフェル

8

PostgreSQLの場合、pgTAPを確認してください

pgTAPは、psqlスクリプトまたはxUnitスタイルのテスト関数でTAPを発行するユニットテストを簡単に作成できるデータベース関数のスイートです。


ご覧いただきありがとうございます。誰もがそれを経験していますか?
-dezso

はい、最近ではかなりの人がいます。質問がある場合は、メーリングリストに登録してください。
理論14年

6

ストアドプロシージャのテストを完全にSQLで実行する場合は、http://tsqlt.org/をご覧ください。

MS SQL 2005 SP2以降と互換性があり、テストを実装するために開発者がC#や他の言語を知る必要がないという利点があります。

再実行可能なテストスイートを実現するために、モックテーブルとモックを実行する機能もあります。

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