HSQLDBユニットテストはアンチパターンですか?


9

HSQLDBは素晴らしいです。また、組み込みモード(専用サーバーは不要)を備えているため、Proof of Conceptsなどの迅速なプロトタイピングが可能になり、さまざまなデータをすばやく簡単に保存できるため、本番環境ですぐに使用できるアプリケーションにも最適です。

ただし、私が過去数年取り組んできたプロジェクトの少なくとも90%は、SQLデータベースを何らかの方法で処理する場合、組み込みHSQLDBを使用するユニットテストを避けられません。

確かに、これらのプロジェクト(ほとんどの場合、標準のMaven構造を使用します)には、大量の「単体テスト」(または少なくとも、ある種のテストがありますが、「単体テスト」領域にあります)があります。いくつかのCRUD操作を実行して結果を確認するために、HSQLDBの1つ以上の埋め込みインスタンスを使用するプロジェクト(「src / test / java」など)の)。

私の質問は、これはアンチパターンですか?HSQLDBは​​簡単に統合でき、組み込みサーバーは非常に軽量であるため、実際のデータベースの「モックアップ」として見過ごされがちですが、そうでない場合はどうでしょうか。(それらのそれぞれは、「何か」で構成されているので、このようなテストは、より統合テストのように扱われるべきではない、データベース・サーバーとの「何か」の統合という)?または、「単体テスト」定義に何か欠けているのでしょうか。このようにHSQLDBを使用すると、「単体テスト」定義の「依存関係を模擬し、単体のみをテストする」部分に固執すると言えます。


3
これは単なるモックがデータベース層に適用されているのではないですか?単体テストに依存するモジュールを取得するためのシンプルで適切な方法である限り、それがアンチパターンであるとは言えません。
Kilian Foth 14

2
@KilianFothはい たとえば、依存関係のあるクラスがある場合(クラスのインスタンス化に必須)、そのクラスを単体テストする場合は、その依存関係をモックしますが、クラスのメソッドをテストするだけでは、 HSQLDBがこれらのタイプの単体テストで持っているように、モックされた依存関係はもう気にしないでください。クラスの単体テスト全体ではそれほど大きな役割はありません...
Shivan Dragon


1
@gnatよく、私は個人的に他の質問が「データアクセスレイヤーで何かを単体テストする方法-データアクセスレイヤーまたは何をモックする必要があるか」のようなものだと思っていますが、私の質問は「単体テストの方法」ですデータアクセスレイヤー自体では、HSQLDなどはモックを作成する有効な方法ですか?」
Shivan Dragon

回答:


8

DAOをテストするときは、HSQLDB(またはDBUnit)のようなものを使用して、データ層に触れるときに記述するコードの品質を保証するために必要なステップとして検討します。すでに指摘したように、これは防弾ソリューションではありませんが、方言と組み合わせると、ケースの妥当な部分をカバーできます。

私の唯一のポイントは、ユニットテストについて話すときは注意しましょう。制御不能な外部コンポーネントと対話するクラスをテストするとき(つまり、非決定的な動作を生成する可能性がある)、それを統合テストとして自動的に検討します。

インターフェースによって隠された具象クラスで(JDBCドライバー、ORMなどを介して)データストアと直接やり取りするロジックを除外したと想定すると、DAOに渡すことによって、DAOの適切な単体テストが開発されます。テストする既知の値のセットを返すインターフェースの具体的なモック実装。


5

IMO:

  • テストにDBが必要な場合、単体テストではありません。統合テストまたは受け入れテストのいずれかです。
  • テストでDBを使用する必要性を回避するには、依存性注入(またはサービスロケーター)を使用して、制御原理の反転に従う必要があります。
  • DBを使用して何かをテストする必要がある場合は、実際のデータベース(タスクに応じて偽または実際のデータを使用)でVMを作成する必要があります。VagrantDockerは、この仕事に最適なツールです。
  • DBをモックすることは悪い習慣です。これは、間違って(DBをモックして)正しくやり直して(実際のDBで動作させる)と同じです。
  • 概念実証プロジェクトの場合は問題ありませんが、それでもやり直しが行われます(コンセプトが証明されている場合)。
  • それが仕事に適切なツールであれば、HSQLDB(または何でも)を単独で使用するのはまったく問題ありません。

4

実稼働環境で使用しているのと同じデータベースを(単体)テストに使用します。

その理由は単純です。データベースの動作が異なるからです。各データベースには独自の独自機能があります。データベースアクセスにORMレイヤーを使用する場合でも、データベースの動作は異なり、パフォーマンスも向上します。

もちろん、単体テスト用の組み込みデータベースの利点は、何も構成する必要がないことです。しかし、すべての開発者のマシンにデータベースをインストールし、単体テストに使用するように構成することはそれほど難しくありません。

先ほどのプロジェクトでも同じ状況でした。JDBCを使用して、データベースでSQLステートメントを実行しました。アプリケーションのテストを作成することを決定したとき、組み込みデータベースを使用しました。そのため、単体テストでは一部のバグを再現できず、組み込みデータベースが本番データベースの機能をサポートしていないため、アプリケーションの一部をテストできない状況が発生しました。したがって、すべての開発者がテストを実行するためにPCの実稼働環境でも使用したものと同じデータベースをインストールしました。


これは、いくつかの環境にインストールすることをお勧めする多くのOracleインスタンスです。ビルドサーバーも忘れないでください。

@MichaelT知っていますが、代替手段は何ですか?
Uooo 14

2
オラクルの方言(hsqldb.org/doc/guide/dbproperties-chapt.htmlを参照)sql.syntax_oraで動作するHSQLDBを使用できます。これは完璧ではありませんが、ほとんどの場合十分です。ご存知のように、それはすべてのソリューションではありませんが、必要な複数のライセンスの問題を解決し、実行中の別のサービスに依存しないスタンドアロンビルドを可能にします。別のアプローチはdbunitです。実際、各アプローチにはトレードオフがあります。

@MichaelT Oracleは開発/テストが無料です。したがって、テスト用に別のOracleインスタンスをインストールするコストはかかりません。もちろん、これらすべてのインスタンスを実行するためにハードウェアを増設するコストがあります。
2014

2
埋め込まれていないDBにアクセスしている場合は、単体テストとは見なしません
ヘルマン

4

私はいくつかの本当に悪い問題を見つけて修正し、HSQLデータベースに対してテストすることで開発を大幅にスピードアップしました。最下位レベルのアダプタークラス(つまり、DAO)は、実際のラウンドトリップからライブデータベースへの分離が困難な場合があるため、単体テストでテストされないことがあります。私は過去にConnectionとJDBCアーティファクトをあざけたことがありますが、実際には、インメモリデータベースに対してテストするよりもはるかに困難でした。

1つのプロジェクトで、私はHSQLに対して開発とテストを行い、MySqlに対してローカルで実行し、SQL-Serverに対して本番環境にデプロイしました。驚くべきことに、それはうまくいきました。私が遭遇した最大の統合問題は、私自身の仕様の誤解によるものでした(秒対ミリ秒、笑)。

永続化フレームワークは(Hibernateが行うように)基礎となるデータベースをマスクできますが、永続化フレームワーク自体が十分に複雑なセマンティクスを追加する可能性があるため、それを単独で実行すると、本格的な統合テストに至る前に多くの癖を取り除くことができます。

HibernateまたはJPAを使用して、多数の結合を持つ複雑な結果セットを構築する場合を考えてみます。厄介で何度も試してみる場合は、ライブデータベースに対して開発およびテストできます。ただし、オーバーヘッドを抑えて、インメモリデータベースに対して開発およびテストすることもできます。また、データベースフィクスチャのセットアップ/ティアダウンスクリプトや、テストとビルドを他の人と調整することについて心配する必要もありません。また、インメモリデータベースに対してテストする場合は、他の単体テストと同様に、これらのテストをリグレッションに利用できるというメリットがあります。

「コンポーネントテスト」という用語は、単体テスト以上のテストを聞いたことがありますが、それでも単独で行われます。

単体テスト、コンポーネントテスト(実際の名前の場合)、および統合テストはすべて価値を提供します。チームはお互いを省くことができます(そうです、多くのチームは単体テストを行わず、統合テストのみに依存しています)が、それを行うと、他のテスト階層がもたらす利点を失うことになります。

メモリへの統合により分離されたテストの場合、利点はコードの迅速な検証とその後の高速回帰です。分離されたテストの利点であり、追加のインストール、ライセンス、ハードウェアは必要ありません。これにより、データベースがプロビジョニングされるまでDAOをテストするだけの場合よりも、より多くのレベルのコードを分離して検証できます。

したがって、実用的な価値があります。必須ではありませんが、やり終えたときは、満足するよりも満足するようになりました。


3

私は過去にそのようなアプローチを使用していますが、これが「アンチパターン」であるかどうかはわかりません(個人的な感情や経験を普遍的なルールに引き上げようとする人もいますが、そうではありません)。

  • 単体テストの場合、実際の単体テストでは、メモリ内データベースなどの外部のものを使用しません(hashMapまたはスタブライブラリを使用したスタブと比較すると、それほど軽量ではありません)。データアクセスにDIおよびリポジトリやDAOなどの単純なパターンを使用する場合、これは非常に簡単に実現できます。私の目的は、非常に迅速に実行できる多数の単体テストを用意することです。迅速に実行すると、1分もかからずに3kテストで考えています。

  • 統合テストでは、このテストで実際のデータストレージソフトウェアを使用することを好みます。このテストの目的は、ソフトウェアと実際のデータストレージ間の統合を証明することです。ここで別のデータストレージを使用すると、この意図が崩れます。テスト。私はこの統合を実証するためにできるだけ少ない統合テストを書くようにしています、そして通常このテストは通常​​のビルドの外で実行されます(例えば夜間ビルドでのみ)

私は時々HSQLDBを使用して、シンプルなデモや概念実証を構築します。これは素晴らしいツールですが、通常の開発ワークフローでこのツールがどこにあるのかもうわかりません。


0

MyBatisのようなユニットテストデータアクセス製品の場合、私の考えでは、埋め込みHSQLDBを使用したテストはまったく問題ありません(少なくともMyBatisでは、このためにHSQLDBを使用していることはわかっています)。

他のほとんどのプロジェクトでは、私はこの過剰を検討します。実際のデータベースにアクセスする簡単な統合テスト(これらは他のテストに潜在的に副作用があるテスト)を作成し、各クエリ/ステートメントが少なくとも1回使用されることを確認します。プロジェクトの統合テストは単体テストよりもはるかに少ないはずです。

単体テストでは、DAOまたはDBにアクセスするもの(「アダプター」)のモックを作成します。

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