正しい結果が返されるTDDの方法


12

私は新しいプロジェクトを開始し、TDDを使用して設計を推進することに非常に一生懸命取り組んでいます。私は何年もプッシュしてきましたが、ついにこのプロジェクトに余分な時間を費やして、それを適切に行う方法を学びながら、それを使用することを承認しました。

これは、既存のシステムに結び付ける新しいモジュールです。現在、すべてのデータアクセスはWebサービスを介して行われます。Webサービスは、ほとんどの場合、データベースストアドプロシージャの単なる薄いラッパーです。

1つの要件は、特定のストアについて、このアプリケーションに対して有効と見なされるすべての発注書を返すことです。出荷日が店舗のオープン日から特定の範囲内にある場合、POは有効であると見なされます(これは新しい店舗の場合です)。

上記の制約が与えられた場合、このストアに適用できるダースを取得するためだけに100万のPOを戻すつもりはないので、このロジックをアプリケーションコードに入れることはできません。

日付範囲をGetValidPOsプロシージャに渡し、それらの値を使用して有効なPOを返すことができると考えていました。しかし、有効なPOと見なされるものに別の要件を追加するとどうなりますか?

そして、どのようにこれをテストし、機能し続けることを確認しますか?ORMを使用していないため、起こりそうにありません。また、テストでDBを呼び出すことはできません。

立ち往生しています。

私の考えでは、有効なデータを返すモック、不良データを返すモック、不良データが発生した場合にローカルリポジトリに例外をスローさせ、無効なデータがGetValidPOs procによって返された場合に例外がスローされることをテストしますテストで使用されるモック)。

これは理にかなっていますか?または、より良い方法はありますか?

更新: EFを使用できるようです。ストアドプロシージャと複数のデータベースにデータを散在させることの困難さに依存しながら、使用方法を把握し、テスト可能にする必要があります。


好奇心から、単純なSQLステートメントで有効なPOだけを選択できないのはなぜですか?(この質問または回答は解決策を意味するものではありません。)
スカーフリッジ

回答:


7

これは、TDDの時代のストアドプロシージャの大きな欠点です。今でもいくつかの本当の利点がありますが、定義上、ストアドプロシージャを実行するテストは単体テストではありません。それはせいぜい統合テストです。

代わりにORMを使用するようにアーキテクチャを変更できないと仮定した場合の通常の解決策は、これらのテストを単体テストスイートに入れないことです。代わりに、テストを統合スイートに配置します。動作を確認したいときはいつでもテストを実行できますが、テストのセットアップ(DBを適切なテストデータで初期化する)に固有のコストが高く、ビルドボットの単体テストエージェントがリソースに触れないためアクセスできますが、単体テストスイートには含まれません。

ユニットテストできないもの(ADO.NETクラス)をDAOクラスに抽象化することで、データを必要とするコードをユニットテストできます。その後、コードを消費して予想される呼び出しが行われたことを確認し、実際の動作(結果が見つからないなど)を再現してさまざまなユースケースのテストを行うことができます。ただし、ストアドプロシージャを呼び出すためのSqlCommandの実際の設定は、コマンド実行からのコマンド作成を切断し、コマンドエグゼキューターをモックすることにより、ユニットテストを行うことができる最後の作業です。これが懸念事項の多くの分離のように聞こえる場合、それは可能性があります。「間接のレイヤーが多すぎることを除いて、別の間接のレイヤーでは解決できない問題はない」ことを覚えておいてください。ある時点で、「十分です。これを単体テストすることはできません。

他のオプション:

  • SQLiteなどの「短命の」DBMSインスタンスを使用して、ストアドプロシージャをテストします。通常、ORMを使用する場合はこれを行う方が簡単ですが、テストは「インメモリ」で実行できます(またはテストスイートに含まれる事前設定データベースファイルを使用)。それでも単体テストではありませんが、高度な分離で実行できます(DBMSは実行中のプロセスの一部であり、他の誰かの競合するテストスイートの途中にある可能性があるリモート接続するものではありません)。欠点は、ストアドプロシージャの変更がテストで変更を反映せずに本番環境で発生する可能性があるため、テスト環境で最初に変更が行われることを確認する必要があります。

  • ORMへのアップグレードを検討してください。Linqプロバイダーを使用したORM(事実上、一般的に使用されるものにはすべて1つあります)を使用すると、クエリをLinqステートメントとして定義できます。その後、そのステートメントを、適用するテストデータのメモリ内コレクションを持つ模擬リポジトリに与えることができます。したがって、DBに触れることなくクエリが正しいことを確認できます(Linqプロバイダーがクエリを正しくダイジェストできることをテストするには、統合環境でクエリを実行する必要があります)。


2
-1。TDD!=ユニットテストのため。TDDを行うときに統合レベルのテストを含めることは完全に問題ありません。
スティーブンA.ロウ

単体テストは、テスト駆動開発のサブセットです。テスト駆動開発では、システムのウォーキングスケルトンを作成し、そのシステムで単体テスト、統合テスト、機能テストを実行します。統合テスト、単体テスト、または受け入れテストが失敗すると、それらをパスしてさらにテストを記述します。
CodeART

1
皆さん、私はそれをすべて理解しています。統合テストでなければならないということは、TDDができないということをどこで言いましたか?私のポイントは、ストアドプロシージャを単独でテストすることはできないということです。これは、できる限り多くのコードベースに対して行いたいことです。代わりに、SPをテストするには、より複雑で実行時間の長い統合テストが必要です。手動によるテストよりも優れていますが、統合が多いテストスイートの実行には数時間かかり、CIの作業に悪影響を与える可能性があります。
キース

SPテストでは、多くの場合、テストデータベースに特定のデータセットが必要です。期待される結果を達成するためにデータベースを適切な状態にするためのコードは、多くの場合、実際に実行しているコードよりもLoCが多く、実行時間が数倍長くなります。これにより、テストスイートの時間の複雑さがさらに悪化し、多くの場合、個々のテストごとにセットアップを繰り返す必要があります(クエリ内の各機能要件が満たされていることをテストするには、SPごとにおそらく複数必要です)。
キース

ストアドプロシージャは、単独でテストできます。他にどのように検証されますか?Transact SQLにはtSQLt(tsqlt.org
ケビンクライン

4

私の助言は分割して征服することです。とりあえずデータベースと永続性を忘れて、リポジトリまたはデータアクセスオブジェクトの偽の実装のテストに集中してください。

上記の制約が与えられた場合、このストアに適用できるダースを取得するためだけに100万のPOを戻すつもりはないので、このロジックをアプリケーションコードに入れることはできません。

発注書を返すリポジトリをモックします。20の奇数の注文書でモックを作成します。

日付範囲をGetValidPOsプロシージャに渡し、それらの値を使用して有効なPOを返すことができると考えていました。しかし、有効なPOと見なされるものに別の要件を追加するとどうなりますか?

GetValidPOsの呼び出しをスタブして、データベースプロシージャではなく、モックを呼び出します。

そして、どのようにこれをテストし、機能し続けることを確認しますか?ORMを使用していないため、起こりそうにありません。また、テストでDBを呼び出すことはできません。

モックから正しいデータが返されることを確認するには、単体テストが必要です。

また、データベースから正しいデータが返されることを確認するための統合テストも必要です。統合テストでは、構成とクリーンアップが必要になります。たとえば、統合テストを実行する前に、スクリプトを実行してデータベースをシードします。スクリプトが機能したことを確認します。ストアドプロシージャを呼び出してデータベースを照会します。結果が正しいことを確認してください。データベースをクリーンアップします。

私の考えでは、有効なデータを返すモック、不良データを返すモック、不良データが発生した場合にローカルリポジトリに例外をスローさせ、無効なデータがGetValidPOs procによって返された場合に例外がスローされることをテストしますテストで使用されるモック)。

既に述べたように、少なくともクエリ可能なデータを返すモックが必要です。

データを照会するときは、システムが例外を適切に処理できることを確認する必要があります。したがって、特定のシナリオで例外をスローするように動作を模擬します。次に、システムがこれらの例外を適切に処理できることを確認するテストを作成します。


それが私がやろうとしていることです。私たちのデータアクセスはORMの使用を助長しないため、モックと同じように機能する実際の実装を書くのが難しいだけです。必要なデータの大部分はいくつかのシステムにあり、更新中であっても、Webサービスを介してアクセスされることになっています。
CaffGeek

0

JavaまたはJavascriptの単体テストがJava用のJava言語を使用した単体テストの作成を意味し、Javascriptを使用したJavascript関数の単体テストと同様に、自動化されたテストを作成してストアドプロシージャを作成することは、探している単体テストライブラリがストアドに基づいていることを意味します手順。

別の言い方をすると、ストアドプロシージャを使用してストアドプロシージャをテストします。

  • プロシージャ言語で開発しているため、プロシージャ言語でテストを書くスキルが必要です。
  • 手続き言語でテストを書くと、手続き言語のスキルが向上し、製品開発に役立ちます
  • DBが提供するすべてのツールに直接アクセスでき、それらのツールを使用して、ユニットテストを可能な限りシンプルに保つことができます。
  • システムの境界を越えていないため、テストしている手順と同じDBに格納されている単体テストは高速です(速度などの単体テストに最も近いもの)

OO languangeのTDDのように、ユニットテストで1行程度のデータのみをセットアップして、プロシージャに必要なものをテストします(ミニマリズム、単純なテストに必要なもののみを取得します)。この結果、ストアドプロシージャごとにいくつかの簡単な単体テストが作成されます。これらの簡単なテストは、テストが実際に必要とするものに簡単にマップできない大規模なデータセットに依存する複雑なテストを行うよりも維持しやすいでしょう。

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