ストアドプロシージャの単体テストまたは統合テストですか?


8

最近、複雑なストアード・プロシージャーおよび関数を維持する必要がある多くの機会がありました。これらはすでに壊れており、通常はかなり微妙な方法で行われます。有効なパラメーターを指定してSPを呼び出すことはほとんどなく、単純に機能しませんでした。

私の解決策は、データベースを必要な初期条件に初期化した後、トランザクション内でストアドプロシージャを実行するフレームワークを進化させ、同じトランザクション内で期待される結果をテストすることでした。トランザクションはテストの最後にロールバックされました。

これは非常にうまくいきました。しかし、データベースとの統合を伴うため、これを「統合テスト」と呼ぶ人もいます。個々のコンポーネントとそれらのコンポーネントの個々のテストケースをテストし、データベースの初期状態を完全に制御したため、これを単体テストと呼びます。

しかし、どこに線を引くべきでしょうか?これは統合テストですか、それとも単体テストですか?この種のテストが悪い考えである実際的な理由はありますか?これが「唯一の」統合テストである場合、これらのストアドプロシージャに対して実際の「単体テスト」を行う方法についての提案はありますか?


更新、3年半後。私の現在のプロジェクトでは、SSDT単体テストの使用を開始しましたが、成功した可能性もありますが、より優れている場合もあります。SQL Server単体テストを使用したデータベースコードの確認を参照してください。これらは通常、SQL Server LocalDBのインスタンスにデータベースプロジェクトを展開するので、これにより、テストに影響を与えるデータベース環境に関する質問がなくなります。事前テスト中に、データベースに必要なデータを入力します。これにより、データベースの内容に関する質問が削除されます。実際、私はこれを行うためにMERGEステートメントを使用して、現在のテストに必要のないすべてのデータがテストの前にデータベースから削除、挿入、または更新されていることを確認しています。彼らには問題があります:

  • 彼らは速くない
  • テスト条件を再利用することはできません
  • 事前テストを再利用することはできません(プロジェクト内のすべてのテストにそれらを共通にしない限り)
  • ユーザーインターフェイスを改善できる

上記の問題の理由の1つは、まだそれらについて不満を述べていないことです。興味のある方はこの機能を試してみて、不満を言うことをお勧めします。これが改善の方法です。


1
なぜそれが悪党か?
doppelgreener

良い質問。タイトルの変更についてどう思いますか?おそらくこのようなもの:「ストアドプロシージャをユニットテストする方法」
Matthew Rodatus

@マシュー:「共同編集」
John Saunders、

回答:


7

ユニットテストのポイントは、魔法のユニットテストの妖精を作り、あなたの意見を検証することではありません。これは、システムの最小で最も単純なビルディングブロックをテストするためのものです。したがって、より広範囲の機能をテストするのではなく、何かが思ったように機能しなかったために作動しました。それで、これをさらに分解できますか?私はあなたができるとは思わない、その場合:

(a)私にはユニットテストのように聞こえます。(b)必要なものをテストするので、ユニットテストかどうかは関係ありません。そもそもユニットテストを使用するポイントです。

手順が複雑すぎると感じた場合は、それ自体を(データベースプロシージャまたはコードで)小さな部分に分割することをお勧めしますが、そのためには、最初にこれらのテストを実施する必要があります。


7

定義による単体テストは、実行環境またはプラットフォームでのコードの「単体」のテストを中心に展開します。使用しているプラ​​ットフォームはデータベースであるため、統合プラットフォームではなく、使用する必要があります。

より良い質問は、なぜあなたは気にするのですか?自動化され、付加価値がある限り、単体テスト、受け入れテスト、スモークテスト、または機能テストでのテストに注意してください。

私の仕事では、現在、単体テストフレームワークを利用して、受け入れテスト駆動開発(ATDD)を行っています。一部のテストは統合的ですが、そうでないものもあります。それらのほとんどは単体テストではありませんが、以下の条件が満たされていれば問題ありません。

  • テストは価値を追加します
  • テストに誤った失敗や成功がない(ほとんどが確定的)
  • テストは自動化されています

更新

それはすべてコストと利益の問題です。可動部分が多いほど、非決定的テストのリスクが高くなります。従来の単体テストでは可動部分が最も少なく、したがって非決定的である可能性が最も低くなります。トレードオフは、統合ポイント(コード、データベース、fs、ネットワークなど)をテストしていないことです。これらはすべて、誤った失敗または成功のリスクが十分に低い限り、テストでカバーするのに役立ちます。

テストは、彼らが何であるかではなく何に価値があるかを提供します。重要なのは、どのくらいの頻度で誤った失敗と成功を経験するかです。それがネットワークのメンテナンスウィンドウであるため、毎月2時間、誤った障害が発生した場合、テストの値は明らかです。失敗した場合、特定のテストではなく、ネットワークリソースに問題があることが明らかです。 そして、これらの統合ポイントをテストしているため、テストカバレッジが増えます。


私が気にする理由の1つは、単体テストがその定義による「単体テスト」でないと文句を言う場所があることです。もう1つの理由は、「中間層は存在しますか?(単体テストと統合テスト)」のコメントで取り上げられたことです
John Saunders

@John @dietbuddhaの回答と私が読んだ調査に基づく:ネットワークスタックとDBサーバーを利用しているため、テストは「ほとんど確定的」ではありません。それらは単体テストとして分類されるべきではありません。しかし、もちろんそれは私の意見です。
Matthew Rodatus

1
@マシュー:どのプラットフォームで開発しているかはわかりませんが、私が使用しているネットワークスタックとデータベースサーバーが頻繁に失敗しないことを保証します。実際、これらのコンポーネントの障害は、テストの目的で無視できます。
John Saunders、

@John Saunders:更新された回答
dietbuddha

2

データがどこから来たのかによります。テストプレフィックスでテスト条件を作成している場合、単体テストと呼ぶのが妥当だと思います。そうしないと、ユニットテストで「既存」と見なされるものについて、細かい議論が行われます。データベースの単体テストがデータベーステーブルの存在などに依存しているのと同じように、データベースの外部の単体テストは、クラス定義や、多くの場合これらのクラスのインスタンスなどに依存しています。それは悪くない、それは現実的です。


1

私はそれを統合テストであると考えます:

  1. 単体テストよりもはるかに遅いです。
  2. 単一のアトミックなコード単位ではなく、プロシージャ、データベースサーバー、ネットワークスタックなどを実行します。
  3. テストが失敗した場合、エラーが発生した場所を検出するのは簡単ではありません。それぞれの障害を手動で調べて、それが外部システム障害であるか、コードであるかを確認する必要があります。

ただし、あなたが説明するようなテストは、非常に重要です。私たちは最近、そのようなテストを追加し始めました。特定の環境で手動でテストすることができないストアドプロシージャをテストするためです。ストアドプロシージャの自動テストを行う別の方法がわかりません。

したがって、これらのテストは優れたアイデアですが、統合テストと呼ばれます。テストのカテゴリまたは名前のサフィックスを使用して、通常の単体テストと区別してください。このようにして、ビルド自動化での単体テストの失敗とは異なる方法で統合テストの失敗にフラグを付けることができます。


@マシュー:.NET BCLまたはCLRをテストする以上に、データベースサーバーやネットワークスタックはテストしません。また、ローカライズの失敗はまったく問題ありませんでした。多分私は私が意味する種類のテストのより詳細な例を示すべきです。
John Saunders、

@John「データベースサーバーとネットワークスタックをテストする」と言ったときは、実行しているコードをテストしているということです。.NET BCL / CLRには、ユニットテストへのチケットが必要です。チケットがないとコードを記述できません。ただし、データベースサーバーと通信するテストでは、サーバーとネットワークもテスト(テスト)しています。私は尋ねるべきだと思います:どのように手順テストを実行していますか?C#ユニットテストメソッドから?SQLスクリプト?結果報告をどのように自動化しますか?
Matthew Rodatus

@Matthew:私のクラスのメソッドの通常のNUnitテストは、定義により.NET Frameworkを実行しています。私ではなく、.NETが機能すると想定しています。同様に、SQL Serverが機能し、SqlCommandクラスが機能し、TCPトランスポートが機能すると想定しています。私はそれらについてまだ間違っていません。
John Saunders、

1
@Matthew:SQL Serverとその組み込みのトランスポートおよび機能が機能していない場合、単体テストと統合テストのどちらよりも大きな問題が発生します。私は通常、OSも同様に動作することを前提とし、光の速度は私のテストはで動作し、フレーム内多かれ少なかれ一定であること。
ジョン・サンダース

1
@ジョン私はあなたが私のポイントを得るとは思わないが、まあ。
Matthew Rodatus

0

これは統合テストですか、それとも単体テストですか?

テストはどこで実行されますか?データベース上、またはコードベースのテストハーネス(JUnit)を介して?

データベースでは、おそらく単体テスト(自己完結型)であり、JUnitのようなテストハーネスは外部データベースに接続し、統合テストとして機能します。

これが「唯一の」統合テストの場合

なぜ引用符なのか?統合テストは、決してやってはならないある種の獣ではありません。

これらのストアドプロシージャで実際の「単体テスト」を行う方法についての提案はありますか?

私は通常、ストアドプロシージャの唯一の合理的な単位は、呼び出しコードとプロシージャです。そのため、単体テストのように見える一連のテストで完全なセットを統合テストします。

より良い質問は、なぜ[名前について]気にするのかということです。

テストを分割できるので。統合テストは実行に時間がかかり、追加のセットアップと、多くのテストで共有されるリソース(データベースなど)へのアクセスが必要になる可能性があります。

1)必要に応じて、呼び出しコードに追加の単体テストがあります。


追加の設定はありません。セットアップはすべてテスト自体の中にあります。また、これらのテストはかなり高速です。これまでのところ、テストのプリアンブルの準備では、50行以上を削除してからさらに数十行を挿入する必要はありませんでした。
ジョンサンダース

データベースが実行されていない場合、データベースを起動しますか?
mlk

「データベースを起動する」?いいえ、テストはテスト用の構成ファイルに格納されている構成文字列を使用します。適切な構成文字列が決定された後は、有効なデータベースサーバー内の有効なデータベースを引き続き参照すると想定します。理想的な世界では、これらのテストは、ソースコントロールにも保存されている現在のDDLを使用して、データベースの新しいインスタンスを展開(作成)した後に実行できます。私たちはその理想に向かって取り組んでいます。
John Saunders

行くのに良い理想です。私はしばらくの間同じに向けて取り組んできました。私のポイントは、あなたが(データベースを起動する)起動タスクを持っているということでした。タスクが実行されていなかった場合でも、テストが失敗しないようにすることができます(その必要があります)(MSTestのAssert.Inconclusive)。このテスト領域は、単体テストの灰色の領域です。単体テストのようなテストを作成しますが、それらは統合テストであることを受け入れます。
mlk

1
データベースを立ち上げてどういう意味かわかりません。私の「理想的な世界」では、データベースの新しい空のインスタンスの展開は、テストの一部ではなく、自動化されたビルドの一部になります。
John Saunders、

-1

マイクロテストは、用語や、テストが単体テストであるかどうかに関する議論を回避するのに役立つ便利な用語です。

単体テストの一般的な定義には、テスト対象システムが機能の小さな単位であり、ファイルシステム、ネットワーク、またはデータベースエンジンの助けを借りずに、メモリ内でテストをすべて実行できる必要があることが含まれます。それを実行するために実際のデータベースエンジンが必要な場合、それは単体テストではありません。

この定義はすべてのアプリケーション層で非常にうまく機能しますが、最下位のデータベースアクセス層にとってはあまり役に立ちません。それが特別であることを認識しなければなりません。テストでストレージ/検索/更新/削除機能の小さなユニットのみをテストする場合、テストはシステムの上位層に対して書かれた「厳密な」ユニットテストと同じくらい価値があります。


ここで論争が存在します。私はDALをテストしていません。データベース自体のストアドプロシージャと関数をテストしています。DALがパラメーターを設定してSPまたは関数またはを呼び出すだけの単純なものである場合は、SELECTテストする必要はありません。
ジョンサンダース
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.