単体テスト-データベース結合アプリ


15

データベースに緊密に結合されたアプリケーションに統合されるモデルの単体テストでの最良のアプローチは何でしょうか?

ここでの特定のシナリオはショッピングカートです-カートからのアイテムの追加と削除、および価格設定ロジックなどをテストできるようにしたいと思います。データベースへのアクセスは避けてください。


1
「アプリのコードを書き直してください」と効果的に答えが投票されるのは
興味深い-AD7six

回答:


10

依存性注入は、これを処理する1つの方法です。テストデータベースを設定してショッピングカートを模倣することも、顧客の取引を「確認」するコードを作成することもできます。その後、実行時に、ソフトウェアは接続するコンポーネントを選択します。

テスト中に本番データベースに接続しないでください!


1
DIと適切なアプリケーション設計により、データベースなしでテストできるはずです。注入するモックがバックエンドデータベースの十分な詳細なモックを提供することを条件とします。
ピーターK.

4

単体テストでは、テスト対象の境界を定義する必要があります。単体テストは統合テストとは異なります。価格設定ロジックがカートのコンテンツから独立している場合は、個別にテストします。これが当てはまらず、すべてのモジュールが密結合している場合は、本番環境を可能な限り模倣するテスト環境を構築し、それを操作します。ショートカットやシミュレーションが長期的に役立つとは思わない。


2

モデルは(具体的な)DBに依存するべきではありません。モデルに渡される抽象DB(「インターフェイス」と呼ばれる)のみを知っている場合は、DBをモックオブジェクトに置き換えることができます

では、オブジェクト指向プログラミングモックオブジェクトは、制御の方法で、実際のオブジェクトの動作を模倣するオブジェクトをシミュレートしています。プログラマーは通常、モックオブジェクトを作成して他のオブジェクトの動作をテストします。これは、自動車の設計者が衝突テストダミーを使用して、車両の衝撃における人間の動的な動作をシミュレートするのとほぼ同じ方法で...


1

同様の問題がありました-テストDBが値を保持することを保証する可能性がありませんでした。したがって、将来的には、たとえば他の価格を取得します。

必要なデータを小さなsqlite -DB に抽出し、このDBをテストに使用しました。Test-DBは、ユニットテストのセットアップの一部になりました。


2
単体テストのポイントは、コードを単独でテストすることです。sqllite dbを使用する場合は、分離されていません。また、データベース間の不整合によりエラーが発生する可能性があります
トムスクワイアズ

0

「最良」は主観的ですが、テストデータベース接続を使用するだけでかまいません。

フィクスチャを使用していくつかのテストデータ(購入するサンプル製品)をロードし、テストするクラス/関数のテストケースを記述します。


統合テストとしてデータベースに作用する機能をテストする単体テストを記述することは、@ murphを非常に誤解させます。
AD7six

1
さて、今私は深く混乱しています-それがデータベースを含む場合、それは自己定義的ではないため、ほとんどの定義ではユニットテストではありません。データベースがある場合は、より高いレベルでテストを実行します。テストは依存関係があり、「結合」するものを調べます。とにかく、これは問題を解決する方法についての私の心への明確な説明ではありません。
マーフ

0

私は、構築されたsymfonyの1.4(PHP)のためのプラグインを(特に)この問題に取り組むために。これは、Djangoのテストフレームワーク(Python)の動作方法をモデルにしています。フレームワークは、各テストが開始する前に個別のテストデータベースを構築および設定し、各テストの完了後にテストデータベースを破棄します。

パフォーマンス(スキーマが変更されない場合、構造全体を再構築するのではなく、単にデータをクリアしないのはなぜか)と利便性(データベースの検査後にテストが失敗したので、無差別に破壊しないでください!)、私は少し異なるアプローチを取りました。

最初のテストが実行される前に、最後のテスト以降にモデルが変更された場合に備えて、データベースが破棄されて再構築されます。後続の各テストを実行する前に、データベース内のデータは消去されますが、構造は再構築されません(必要に応じてテストから手動で再構築をトリガーできます)。

各テストでデータフィクスチャを選択的にロードすることにより、後続のテストを妨げることなく、そのテストに適した環境を作成できます。フィクスチャファイルを再利用することもできます。これにより、このタスクの煩わしさが大幅に軽減されます(ただし、テストの作成で最も嫌いな部分です!)。

どちらのテストフレームワークでも、データベースアダプタは、「実稼働」接続ではなくテスト接続を使用して、テスト実行による既存データの破損を防止するように構成されています。


0

先に進み、フィクスチャを使用してデータをプリロードしてください。それは、データの操作をテストするときに、単体テストフレームワークが一般的に機能するように見える方法です。

しかし、あらゆる種類のデータベースに接続する必要がなく、ユニットテストがコードの外部に触れないという非常に厳格な定義に従うことを本当に避けたい場合は、オブジェクトのモックを見てください-それはあなたにアイデアを与えるかもしれません。

たとえば、必要なコードにSQLを直接ドロップする代わりに、そのSQLの機能のみを実行するメソッドを呼び出す方法があります。使用するPerson.getPhoneNumber()のではなく、例えば、SELECT phone_number FROM person WHERE id = <foo>。一見簡潔でわかりやすいだけでなく、テスト中にPersonオブジェクトをモックすることで、データベースにアクセスする代わりに、getPhoneNumber()常に555-555-5555何かを返すことができます。


0

少し長く巻かれていれば、junitでこれを行うのはかなり簡単です。

「セットアップ」は、一時テーブルのセットを定義および設定する必要があります。

その後、すべての更新、挿入、削除機能の単体テストを実行できます。

各テストについて、更新メソッドを呼び出してから、いくつかのSQLを実行して期待される結果を確認します。

「分解」フェーズでは、すべてのテーブルをドロップします。

この方法では、常に同じ初期データに対して同じテストを実行します。テスト間でテーブルを保持すると、失敗したテストによって「汚染」されてしまいます。また、すべてのテストで新しいキーを発明し続ける必要があるため、一貫した「挿入」テストはほとんど不可能です。

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