はじめに
業務システム開発において、
- ローカルでのテストの実行結果が、開発者の環境差異に左右されないこと
- CI環境でのDB管理の手間の削減
を狙い、単体テスト環境にH2 Databaseを採用し、約2年間運用してきました。
本記事では、このH2をインメモリモードで単体テスト環境に採用した経験について共有します。
なお、筆者はDBをローカルに立てる普通の方式でリーディングしたことがありません。1
h2とは?
H2 Databaseは、Javaで実装された軽量なリレーショナルデータベースです。主な特徴は以下の通りです
- インメモリモード:メモリ上でDBを動作させることができ、高速にテストを実行可能
- 組み込み可能:アプリケーションに組み込んで使用でき、別途DBサーバーを立てる必要がない
技術スタック
- フレームワーク: Nablarch
- ビルドツール: Maven
- テストフレームワーク: Nablarch Testing Framework2
- 本番用DB: PostgreSQL または Oracle
- 単体テスト用DB: H2 Database(インメモリ)
採用してよくなかったこと
採用して運用してみたところ、以下のような課題に直面しました。
1. テストフレームワークのセットアップの大変さ
テストフレームワークがあまりh2を想定して作られておらず、多少のカスタマイズが必要になりました。
あまり無い方式で情報が少ないので、ハマると大変でした。
-
接続情報の設定:H2特有のJDBC URL形式(
jdbc:h2:mem:testなど)やモード指定の調査 - テストサポートクラスの修正:インメモリH2は接続時に起動する仕様のため、テスト前処理でDDLを実行するロジックを追加
2. 標準SQL外の記載
H2は特定のDBの互換モードが存在するものの、各RDBMS固有の方言や拡張機能の全てをサポートしているわけではありません。
業務ロジックの実装時はローカルのProstgreSQLやOracleを利用する開発者が多かったのですが、ローカル実行では動作するが単体テストでは動作しない、という問題がしばしば発生しました。
具体的には以下のような機能で問題が発生しました:
- PostgreSQLのMERGE文
- OracleのDUALテーブル
- Oracle固有関数
プロジェクトとしては「標準SQLのみ利用し、複雑なロジックはアプリに寄せる」ことを規約に定めていました。
ただ、規約違反のコードを書いた時に、「単体テストが動かないので必ず修正が必要になる」と「最悪見逃してもなんとかなる」は結構大きな差でした。
また、設計時点でSQL文レベルまで設計していたため、実装時に設計書の変更もしばしば発生し、地味にコストがかかりました。
3. トラブルシュートの困難さ
インメモリで動作するため、テーブルデータの実物を直接確認できません。
テストが期待通りに動作しない場合、通常のDBであればSQL Clientツールで直接テーブルの中身を確認できますが、H2の場合は以下のような対応が必要でした:
- SQLの実行ログから原因を推測
- テストコード内にデバッグ用のSELECT文を追加してログ出力
採用してよかったこと
もともと狙ったメリットは享受できました。
実際CI環境にDBは立てずに済みましたし、環境差異でCIでテストが失敗するケースはほとんど発生しませんでした。
まとめ
当初想定していたメリットは十分享受できましたが、想定外の部分で予想以上の運用コストが発生しました。
ただ、前述の通り普通にローカルにDBを立てる方式でリーディングしたことがないので、結局どっちがいいの?と言われるとよく分かりません。
次の案件では普通にローカルにDBを立てる方式でやってみて、比較してみたいと思います。