単体テストとTDDを使用して、主にデータベースCRUD操作に依存するアプリをテストするにはどうすればよいですか?


22

仕事中、私のプロジェクトの1つは主に外部クライアントから渡されたデータを取得し、データベースに保持することです。JPAを使用するJavaエンタープライズアプリであり、ほとんどのロジックはCRUD操作を中心に展開します。

バグの大部分は、何らかの形でJPAに関係しています。

  • 例1:[保存]ボタンを2回クリックすると、JPAは同じエンティティをデータベースに2回挿入しようとし、主キー違反が発生する場合があります。
  • 例2:データベースからエンティティを取得し、編集して、そのデータを更新しようとします。JPAは、古いインスタンスを更新する代わりに、新しいインスタンスを作成しようとする場合があります。

多くの場合、ソリューションはJPAアノテーションを追加/削除/変更する必要があります。また、DAOロジックの変更に関係する場合もあります。

単体テストとTDDを使用してコードに自信を持たせる方法がわかりません。ユニットテストとTDDの適合性が悪いのか、問題に近づいているのかがわかりません。

単体テストは、実行時にしかこれらの問題を発見できず、問題を再現するためにアプリサーバーに展開する必要があるため、不適切なように見えます。通常、データベースは関与する必要がありますが、これは単体テストの定義の外側にあると考えられます。これらは統合テストです。

TDDは、展開とテストのフィードバックループが非常に遅いため、非常に非生産的であるため、不適切なように思われます。deploy + testフィードバックループには3分以上かかります。これは、作成中のコードに関するテストを具体的に実行した場合にのみ発生します。すべての統合テストを実行するには、30分以上かかります。

この型の外側にはコードがあり、できる限りいつでも単体テストを行っています。しかし、バグの大部分と最大のタイムシンクは、常にJPAまたはデータベースに関係しています。


同様の別の質問がありますが、アドバイスに従えば、コードの最も不安定な部分(JPA)をラップし、それ以外のすべてをテストします。私の質問の文脈では、私は同じ悪い状況にいるでしょう。JPAをラップした後の次のステップは何ですか?IMOその質問は(おそらく)私の質問に答えるためのステップですが、それに対する答えではありません。


4
実際にテストするためにデータベースをセットアップする必要があるので、あなたがしているのは基本的に統合テストです。1つのモジュールが他のモジュールに依存することを想像できるので、さらに統合テストのようにします。TDDアプローチをアプリケーションに適用する方法に関する質問を変更します。
情報14年

@randomA正しい、私は質問を編集して明示的に言った。質問を変更するように勧めている理由がわかりません。詳しく説明してもらえますか?私はむしろ統合テストよりも単体テストを書くことを望んでいるので、単体テスト部分をそこに保持したいです(私はそのことを知っていますがunit testing != TDD
ダニエルカプラン14年

特別なことはありませんが、TDDをそこに置くだけです。ユニットテストがある場合、多くの人はあなたが物事を理解していないなどと思うでしょう。あなたにとって良くない..
InformedA 14年


回答:


7

1つのオプションは、H2などのメモリ内テストデータベースを使用することです。これは、標準のディスク使用データベースよりも約10倍高速で、起動/ティアダウン時間が短い傾向があります。

役立つかどうかは、お持ちのJPAの問題が一般的なものであり、別のデータベースで失敗するかどうかに大きく依存します。問題の大部分が見逃された場合、ポイント実行テストはそれほど速くありません。

しかし、システム全体でH2を使用して10回実行することができれば、成果を上げることができます。


これはいい考えですが、アプリサーバーAFAIKに展開する必要があります。3分以上かかります。とはいえ、間違いなくやりがいがあります。しかし、単体テストを実行するのと同じくらい頻繁にテストを実行することを想像するのはまだ難しいため、TDDを使用して開発するのは非効率的です。
ダニエルカプラン14年

1
通常、その要件を回避する方法があると思います(例:docs.oracle.com/middleware/1212/toplink/TLADG/testingjpa.htm)。しかし、正当化されるよりも多くの仕事をする可能性が高い。別のオプションは、より強力なテストサーバーを入手し、並行して実行することです。
soru

1
@tieTYT githubでcrud Webアプリをテストするhsqldbユニットの概念実証:TestingWithHsqldb-ユニットテストでは、アプリをデプロイする必要はありません。

3

データベースの単体テストは非常に簡単です。ストアドプロシージャとトランザクションが必要です。

これは、データベースの単体テストについてマイクロソフトが言ったことです。データベースに対してユニットテストを実行し、DB接続を設定してJavaまたはC#でテストを作成し、トランザクションを開始し、テストに使用するデータをDBに書き込み、テストを実行してからロールバックすることもできます。デプロイしたDBを使用していて、完全に分離されたテストを取得した場合、DBに損傷はありません。

これにより、フレームワーク内でそれを行う方法についての洞察が得られることを願っています。


「私たちのバグの大部分は何らかの形でJPAに関係しています。」と言ったように、この記事のアドバイスはそれらすべてを逃してしまうと思います。また、これらのJava / C#テストがまだ単体テストであると考えると、非常に異なる定義があります。これは一般的には良いアドバイスだと思いますが、それでもスイートを展開して実行するには時間がかかり、TDDを助長しないようです。あなたは同意しませんか?
ダニエルカプラン14年

以前はSQLのDB単体テストを実行していましたが、その後はすべてsprocに含まれていました。あなたが他のSQLプロシージャからユニットテストsqlディレクトリができなくなり、それはそこに(ねえ、私たちがしたビルドサーバーに緑色のダニを得たからそれらを実行するために意味を成していたので、私たちのユニットテストフレームワークは、MSTestをした最も重要な要因)。DBが常に稼働している場合(とにかく内部テストを行った場合)、すべてのSQLコードをアップロードして、ビルドサーバーですべての単体テストを実行するのは簡単です。時にはあなたはこれらのことについて実際的でなければなりません。
gbjbaanb 14

あなたは私の最初の文に応答したとは思わない。
ダニエルカプラン14

それでは、jpa-unitを使用してください。JPAコードがどのように機能するか(または機能しない)に答えることはできません。dbでSQLをテストするためのアイデアを提供してください。
gbjbaanb 14

3

他の人々は「あなたのデータベースをモックアウト!」と答えました。-しかし、実際にコードとの相互作用をテストする必要がある場合、DBレイヤーをモックアウトするポイントは何ですか?

探しているのは、統合テストおよび/または自動化されたUIテストです。問題は次の場合に発生すると述べました。

*If you click the save button twice*

これをテストする唯一の方法は、ボタンを2回クリックする自動UIテストを作成することです。Seleniumをチェックしてください。

また、おそらくユニットテストDBが必要になりますが、テストではそれを示します。維持するのは苦痛ですが、現実の世界ではTDDを歓迎します。


これはより多くの答えよりも暴言のように読み込む
ブヨ

質問に3回答えました-統合テスト、GUIテスト、単体テストDB。はい、それは少し暴言です、私はそれを正気のように編集します。
ロックラン14

1
「これをテストする唯一の方法は、ボタンを2回クリックする自動UIテストを作成することです。Seleniumをチェックしてください。」そのような状況では、バックエンドはそれが発生するのを防ぐ方が適切です。そうしないと、UIはデータベースに直接アクセスできます。
ダニエルカプラン14

0

質問の例では、ボタンを2回クリックして非常に簡単にエラーを引き起こす状況にユニットテスト/ TDDすることはできません。しかし、ユニットテストできるのは、ボタンをクリックしたときに呼び出されるコードで、永続化レイヤーから例外を取得した場合、適切に処理することです(永続化レイヤーをモックアウトするか、インメモリデータベースを他の回答で提案されています)-再スローするか、エラーを表示するか、または何でも。

ユニットテストに適さないテスト(統合/システムテストなど)を実行する必要がある場合、TDDが故障し始める可能性があることは確かです。これは、最近の「TDDはデッド?" ケント・ベック、マーティン・ファウラー、デビッド・ハイネマイヤー・ハンソン間の議論:http : //martinfowler.com/articles/is-tdd-dead/

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