データベーステスト:アプリケーションのデータ整合性を検証する方法

Yunhao Jiao
データベーステスト:アプリケーションのデータ整合性を検証する方法 cover

データベースのバグはソフトウェア開発において最もコストの高い部類に入ります。ユーザーが回避策を取れる壊れた UI や、フラストレーションを引き起こす遅い API とは異なり、データを破損・喪失・漏洩させるデータベースエラーはコンプライアンスインシデント、ユーザーの信頼失墜、そして数日から数週間かかる復旧作業を生み出します。

それにもかかわらず、データベーステストはアプリケーション品質の中でも最も体系的に対処されていない領域の一つです。ほとんどのテストスイートは API や UI レベルでアプリケーションが正しく機能することを検証しますが、データ層、つまりスキーマの正確性、制約の強制、マイグレーションの安全性、および操作をまたいだデータ整合性を具体的にテストしていません。

データベーステストとは何か

データベーステストとは、データベースとそれと連携するアプリケーションコードが、データを正しく保存・取得・変換・保護することを検証するものです。以下を含みます。

  • スキーマテスト:データベーススキーマはアプリケーションの期待と一致しているか?
  • CRUD 操作テスト:作成・読み取り・更新・削除操作は正しい結果を生成するか?
  • 制約テスト:データベース制約(一意、NOT NULL、外部キー)は正しく強制されているか?
  • マイグレーションテスト:スキーママイグレーションは正しく実行され、データを一貫した状態に保つか?
  • パフォーマンステスト:クエリは許容できる時間内に結果を返しているか?
  • データ整合性テスト:操作をまたいで関連テーブル間のデータは一貫性を保っているか?

データベーステストがしばしば欠如している理由

ほとんどの自動テストスイートはデータベース層をモック化します。つまり、実際のデータベース呼び出しをインメモリのフェイクやモック関数に置き換えます。これによりテストは高速で独立したものになりますが、重大なギャップが残ります。テストは、特定のデータベースの振る舞いを前提としたアプリケーションコードの正確性を確認するものの、実際のデータベースがその振る舞いを本当に生成するかどうかは検証しません。

モックテストでは検出できないデータベースのバグ:

  • ORMの設定ミス:ORMが想定と異なるSQLを生成するケースで、モックは正しい値を返すが実際のデータベースでは返らない
  • クエリのパフォーマンス:ORMがN+1クエリを生成し、小規模なテストデータセットでは正常に動作するが、本番環境ではタイムアウトする
  • 制約違反:アプリケーションが制約の存在を前提としているが、その制約を作成したマイグレーションが本番環境で実行されていない
  • データ型のエッジケース:誤ったフォーマットでテキストとして保存された日付が、ユニットテストでは正しくパースされるが本番環境のクエリでは失敗する
  • 並行処理の問題:順次実行をモックしたテストでは検出できない、データベースの並行操作におけるレースコンディション

データベーステストの種類

スキーマテスト

実際のデータベーススキーマがアプリケーションの期待通りであることを検証する:

制約テスト

データベースの制約が適切に適用されていることを検証する:

マイグレーションテスト

各データベースマイグレーションについて、以下の項目をテストする:

  • 直前のスキーマ状態からエラーなしにマイグレーションが実行される
  • マイグレーション前に存在していたデータが正しく保持または変換される
  • マイグレーション後のスキーマに対してアプリケーションが正常に動作する
  • マイグレーションがロールバック可能である(ロールバック機能が必要な場合)

トランザクションおよびアトミック性テスト

アトミックであるべき操作が実際にアトミックであることを検証する:

AIが生成したコードにおけるデータベーステスト

AIコーディングツールには、データベーステストの優先度を高める固有のパターンがある:

ORMクエリの効率性。AIが生成するORMコードは、リスト取得用のクエリを1件、関連データ取得用のクエリをアイテムごとに1件ずつ発行するN+1クエリを生成しがちです。小規模なデータセットでは正常に動作しますが、本番規模ではパフォーマンスが著しく低下します。リスト操作ではクエリ件数を明示的にテストしてください。

nullチェックの欠如。AIが生成するコードは、オプションフィールドが常に存在することを前提とする傾向があります。null値または欠損したオプションフィールドを持つ操作をテストしてください。

デフォルト値の誤り。AIが生成するスキーママイグレーションでは、既存データの新しいカラムに対して誤ったデフォルト値が設定されることがあります。既存レコードに対するマイグレーションの動作をテストしてください。

レースコンディションへの脆弱性。AIが生成するコードは並行処理を考慮していないことが多いです。データの整合性を確保するため、並行操作を明示的にテストしてください。

TestSpriteのエージェント型テストには、実際のHTTPリクエストを通じてデータベース層を実行するAPIレベルのテストが含まれており、アプリケーションの境界面で表面化するデータ整合性の問題を検出します。

実践的なデータベーステストのセットアップ

ほとんどのアプリケーションにおける実践的なセットアップ:

  1. インテグレーションテストにはモックではなく実際のテスト用データベースを使用する(ローカルのPostgreSQL/MySQLインスタンスまたはDockerコンテナ)
  2. スキーママイグレーションとシードデータの組み合わせを用いて、テスト実行のたびにデータベースをリセットする
  3. 制約を明示的にテストする — 各データベース制約が適用されていることを確認するテストを少なくとも1件作成する
  4. CIパイプラインの一部としてマイグレーションをテストする — マイグレーションは本番環境で実行される前にCIで正常に完了していることを確認する
  5. リスト操作のパフォーマンステストにデータベースクエリ件数を含める

TestSpriteでデータ整合性テストをセットアップする →