[解決済み] データベース駆動型アプリケーションのユニットテストに最適な戦略とは?
質問
私は、バックエンドに様々な複雑さを持つデータベースによって駆動される多くのウェブアプリケーションを扱っています。一般的には オーエム ビジネスロジックやプレゼンテーションロジックとは別のレイヤーです。このため、ビジネスロジックのユニットテストは非常に簡単です。物事を個別のモジュールで実装し、テストに必要なデータはオブジェクトモッキングでフェイクすることが可能です。
しかし、ORMやデータベース自体のテストは、常に問題や妥協がつきまとうものでした。
長年にわたり、私はいくつかの戦略を試してきましたが、どれも完全に満足できるものではありませんでした。
-
既知のデータでテスト用データベースをロードする。ORMに対してテストを実行し、正しいデータが戻ってくることを確認します。この場合の欠点は、テスト DB はアプリケーションデータベースのスキーマ変更に追従しなければならず、同期がとれなくなる可能性があることです。また、人工的なデータに依存するため、ユーザーの愚かな入力によって発生するバグを明らかにできない可能性があります。最後に、テストデータベースが小さいと、インデックスの欠落のような非効率的な部分を明らかにすることができません。(OK、最後のものはユニットテストが本当に使われるべきものではありませんが、それは問題ではありません)。
-
本番用データベースのコピーをロードし、それに対してテストする。ここで問題なのは、本番用 DB に何が入っているのか、その時点では全くわからないということです。
これらの戦略はどちらも特定のデータに依存しており、ユニットテストは機能のみをテストするものであるべきだと指摘する人もいます。そのために、提案されているのを見たことがあります。
- モックデータベースサーバーを使用し、ORMが与えられたメソッド呼び出しに応答して正しいクエリを送信しているかどうかだけをチェックします。
データベース駆動型アプリケーションのテストに使用したことのある戦略があれば、教えてください。最も効果的だったのは何ですか?
解決方法は?
私は、この最初の方法を使い、かなりの成功を収めましたが、少し違った方法で、あなたの問題のいくつかを解決できると思います。
-
スキーマ全体とそれを作成するためのスクリプトをソース管理下に置き、チェックアウト後に誰でも現在のデータベース・スキーマを作成できるようにする。さらに、ビルドプロセスの一部で読み込まれるデータファイルに、サンプルデータを入れておきます。 エラーの原因となるデータを発見したら、それをサンプルデータに追加して、エラーが再発しないことをチェックします。
-
継続的インテグレーション・サーバーを使用して、データベース・スキーマを構築し、サンプル・データをロードし、テストを実行します。 このようにして、テスト用データベースの同期を保ちます(テスト実行のたびにデータベースを再構築します)。 CIサーバーが専用のデータベースインスタンスにアクセスし、所有する必要がありますが、1日に3回データベーススキーマを構築することで、おそらく納品直前まで見つからなかったであろうエラーを劇的に発見することができるようになりました。 毎回コミットする前にスキーマを再構築しているとは言えません。 誰かやってますか? このアプローチでは、その必要はありません(そうすべきかもしれませんが、誰かが忘れたとしても大したことではありません)。
-
私のグループでは、ユーザー入力はアプリケーションレベル(データベースではない)で行われるので、これは標準的なユニットテストによってテストされます。
本番用データベースコピーの読み込み。
これは、私が前職で使っていた方法です。 いくつかの問題があり、非常に苦労しました。
- コピーが製品版から古くなってしまう。
- コピーのスキーマに変更が加えられ、本番システムには伝搬されない。 この時点でスキーマがバラバラになってしまう。 面白くないですね。
データベースサーバをモック化する。
今の仕事でもやっています。 すべてのコミット後に、モックデータベースアクセサが注入されたアプリケーションコードに対してユニットテストを実行します。 そして、1日に3回、上記のような完全なDBビルドを実行します。 私は間違いなく両方のアプローチをお勧めします。
関連
-
2021MySql-8.0.26インストール詳細チュートリアル(ベビーシッターレベル)
-
EF Exception Inquiry (エンティティオブジェクトは、IEntityChangeTrackerの複数のインスタンスから参照できません。)...
-
アプリケーションから DB2 SQL Error が報告され続けます。SQLCODE=-302, SQLSTATE=22001, SQLERRMC=null, DRIVER=4.17.29
-
MySqlエラー解析'where節'の未知の列'xxx'
-
CMakeのエラーを解決する。ソースディレクトリ "*" には、CMakeLists.txt が含まれていないようです。
-
DB2におけるNULLおよびNULL処理
-
ORA-01034 を解決する: ORACLE は利用できません ORA-27101: 共有メモリ領域が存在しない
-
[解決済み] フェイク、モッキング、スタビングの違いとは?
-
[解決済み] C#でユニットテスト用にファイルシステムをモック化する方法とは?
-
[解決済み] Unit Testsでランダムデータ?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
SQL SERVER データベース SELECT INTO および INSERT INTO の使用法(テンポラリテーブルへのデータ挿入を含む)
-
Postgresql でテーブル "t" の FROM 句の項目が見つからない。
-
redisサーバーに接続するとプロンプトが表示されます。Redis Client On Error: Error: connect ECONNREFUSED 127.0.0.1:6380 設定はあってる?
-
PostgreSQLのリモートアクセスエラーを解決する サーバーに接続できませんでした:接続拒否(0x0000274D/10061)
-
mysqlの外部キー作成失敗の問題
-
[解決済み] redis-serverを停止するにはどうすればよいですか?
-
[解決済み] Googleが使用しているデータベースは何ですか?
-
データファイルのsqlldrフィールドが最大長を超えています。
-
Net connection pool configuration Timeout expired. 操作の完了前にタイムアウト時間が経過したか、サーバーが応答していない。"
-
[解決済み] VARCHAR(255) が(他の長さではなく)頻繁に使用されているのを見るのは、何か理由があるのでしょうか?