ソフトウェア開発では、アプリケーションの土台となるビジネス ルールに基づいて、さまざまな状態のデータを処理、保存します。 どのようなソフトウェア アプリケーションでも、取得し処理するためのデータがデータベースに保存されていなければ成り立ちません。 したがって、アプリケーション用のデータベース システムには、(SQL でも NoSQL でも) アプリケーションのデータ処理とストレージの要件を満たすものを選ぶ必要があります。 この要件が満たされているかを判断する一番の方法は、データベースの機能を確かめるテスト システムを構築することです。
データベース テストとは?
過去の記事では、コード テストの手法と適切な API テストの方法を紹介してきました。今回のテーマは、アプリケーションのデータ レイヤーです。 さて、データベース テストでは何をすればよいのでしょう?
データベース テストの主な作業は、各種 SQL クエリを構築して、目的のアプリケーションで必要とされるデータベースの操作、構造、属性を確認および検証することです。
データベースが適切に設定されているかを確認するために、スキーマ (構造) の検証や、CRUD 操作およびトランザクションのテストを行うこともあります。 こうしたテストは、完全に自動化することも、すべて手動で行うことも可能です。さらに、手動と自動のプロセスを組み合わせたハイブリッド アプローチも存在します。 完全手動のテストの例としては、データベース管理システムにアクセスし、クエリを実行して仮説を検証することが挙げられます。 また、アプリケーションの UI について、操作の実行後に適切なデータが返されるかテストする方法もあります。
データベース テストの担当者の役目は、アプリケーション開発者と連携して、データベースの運用シナリオを適切にテストすることです。 テスト担当者は、データベースの構造だけでなく、アプリケーションの土台となるビジネス ルールについても完全に把握していなければなりません。
なぜ、データベース テストが重要なのか?
アプリケーションのデータの整合性が損なわれれば、収益面で大幅な損失となり、ビジネスそのものが崩壊しかねません。 整合性が失われることで被害を受ける対象は、ツイートのリツイート件数などのデータの厳密な正確性が必要ない機能から、株取引アプリの株価表示機能まで、多岐にわたります。 データベース テストで、データの漏えいや整合性の崩壊を完全に防ぐことはできません。しかし、アプリケーションに使用するデータベース システムを徹底的にテストすれば、起こりえる最悪の事態を防ぐことはできます。
データベースをテストする理由としては、次のものがよく挙げられます。
- SQL インジェクション攻撃などの攻撃を防ぐ
- ネットワークの問題や停電が起きた場合でも、データ整合性の崩壊や、データの損失や破損が生じないようにする
- データ品質の低下の原因となるデータベースのエラーを取り除く
- すべてのデータの保存形式が適切であるかを確認する
- データベース内のエンティティ間の関係性を検証する
上述したもの以外にも、さまざまな理由があります。
テストすべき対象は?
ここまでは、データベース テストの概要と重要性を確認してきました。次は、これまでの説明を基に、対応すべきテスト ケースを考えてみましょう。
CRUD
最初のテスト ケースの対象は、アプリケーションで実行される CRUD (作成、読み取り、更新、削除) 操作です。 このテスト ケースの目的は、データの保存と取得が、データの整合性を確保しながら行われているかを確認することです。 テストは、アプリケーション インターフェースから直接実行します。また、データベース管理システム (DBMS) を使用して、SQL データ操作言語 (DML) の各種コマンドでクエリを実行する方法もあります。 さらに、テスト環境において、データベース内のデータを破損させる SQL コマンドを実行して、SQL インジェクション攻撃に対するデータベースのセキュリティを確認します。
トランザクション
トランザクションは、さまざまなクエリを実行する必要があり、さらに失敗時には適切な復元が求められるので、データベース操作の中でも特に注意すべきものです。 標準的なデータベース トランザクションでは、以下の ACID 原理を守らなくてはなりません。
- 原子性 (Atomic): トランザクションではすべての操作を完了しなければならず、1 つでも完了できない場合はどの操作も実行してはならない
- 一貫性 (Consistent): データベースは常に有効な状態にあり、すべての制約が満たされていなければならない
- 分離性 (Isolation): 複数のトランザクションを同時に実行する場合、各トランザクションは互いに独立して実行されなければならない。 つまり、全トランザクションの完了後のデータベースの状態は、各トランザクションを順次実行した場合と同一である必要がある
- 持続性 (Durability) : トランザクションのコミット後に、いかなる理由でもデータが失われてはならない
テストでは、SQL クエリを作成して、アプリケーションのトランザクション操作でこれらの原理が守られているかを確認および検証します。 このタイプのテストは、特に金融アプリケーションをテストするうえで重要です。
スキーマ
データベース スキーマは、データベース構造の設計図です。そのため、データベース テストの担当者は、スキーマを熟知していなければなりません。 スキーマのテストでは、SQL の DESCRIBE (DESC
) コマンドを使用してデータベース スキーマを調査し、アプリケーションの要件に準拠しているかどうかを確認します。 また、正規表現を使用してテーブルのフィールド名を検証し、値がデータ型の要件に準拠していることを確認します。
トリガー
トリガーは、コードのイベント ハンドラーのようなものです。 設定に応じて、テーブルに対してなんらかの操作 (行の新規追加など) が行われたときに、その操作を受けてコードやクエリを実行します。 トリガーはカスケード効果を引き起こします。つまり、ある操作から別の操作を連鎖的に引き起こすのです。 たとえば、データベースからユーザーが削除されたときに、そのユーザーの投稿も削除するトリガーがあるとします。 この場合、他のユーザーの投稿を削除しないように、操作が正確に実行されるかを確認する必要があります。
テストでは、SQL クエリを実行して、カスケードのトリガーとなる操作を実行します。 また、アプリケーション インターフェースからカスケード操作を実行して、データベース レコードに生じる影響を確認する場合もあります。
その他
テストの対象となる操作は、上記ですべてではありません。これらは、データの扱いに注意が必要なアプリケーションで特に重要な操作の一部に過ぎません。
テストすべき操作や属性には、他にも次のようなものがあります。
- データベースの制約
- ストアド プロシージャ
- ビュー
- インデックス
データベース テストを行うには?
さて、テストすべき対象はわかりましたが、肝心のテストはどのように行えばよいのでしょう? 意外かもしれませんが、データベース テストの実行方法は、アプリケーション テストとほとんど同じです。
前述のとおり、これらのテストは手動で行うことができます。たとえば、アプリケーション UI から操作を実行して、各操作の後に適切なデータが返されることを確認したり、データベース レコードを調べて操作の結果を確認したりするのです。 また、データベース管理システムを使用して、テスト クエリを実行し結果を検証する方法もあります。
手作業に不安がある方も、心配はいりません。アプリケーション コードのテストを自動化するのと同じように、データベース テストも自動化できます。 自動化で注意すべき相違点は、実行するものがアプリケーション コードではなく、クエリであるということだけです。 あとは、アプリケーション テストの以下のステップをそのまま流用できます。
- テスト環境を準備する
- テストランナー (例: Selenium) を使用してテストを実行する
- 結果を確認して検証する
- アサーションを報告する
このため、データベース テストの担当者がなによりも備えておくべき素質は、必要なあらゆるテスト ケースに合わせて SQL クエリを作成できる能力とされています。
データベース テストに使うべきツールは?
データベース テスト用のツールには、さまざまなものがあります。 どのテスト ツールを選択すべきかは、次の要素に応じて決まります。
- テスト戦略 (手動、自動、ハイブリッド)
- データベースの種類 (SQL または NoSQL)
- データベース ベンダー (MySQL、MSSQL、Oracle など)
一般的に、データベース テスト システムは、複数のツールを組み合わせて構成します。 たとえば、Java アプリケーションのデータベース テストでは、Selenium と TestNG を組み合わせます。 同様に、SQLite データベースのテストであれば、SeLite と Selenium を併用します。また、SQL Server には、データベースの単体テスト用に複数のツールが付属しています。
おすすめのデータベース テスト ツールについては、こちら (英語) にまとめられています。 テスト ツールを選ぶ際には、上記の要素を参考にしてください。
おわりに
データベース テストは、信頼性の高いアプリケーションを実現するテスト駆動開発プロセスの 1 つです。 データはあらゆるアプリケーションの中核。ユーザーから信頼されるアプリケーションを開発するためにも、まずはデータを適切に取り扱うことから始めましょう。
Happy coding!