はじめに
初めて Laravel5 でアプリを書いてみて、なんとなく動くようになってきたので、これも初めてのユニットテストに挑戦しようとしています。PHPUnit は、基本的なところはできそうな気になってきましたが、データベース部分はいろいろと難しそう。ということで、PHPUnit のマニュアルの第8章 データベースのテストを斜め読みした時点のまとめです。実装はこれからです。
(ちなみに、マニュアルは翻訳がすごくこなれていてすばらしい。感謝です。)
概要
- DBUnit とは
- PHPUnit でデータベース周りのテストをする時に必要な拡張機能
- (※ 実際は、各言語用 xUnit のための DBUnit があるのではないかと思われます)
- PHPUnit 用の DBUnit の作者は PHPUnit と同じ人(Sebastian Bergmann氏)
- PHPUnit でデータベース周りのテストをする時に必要な拡張機能
- 利用準備
- オプションパッケージの導入
- composer require-dev "phpunit/dbunit": ">=1.2"
- オプションパッケージの導入
- PDO の利用
- DBUnit は「初期化(フィクスチャの作成)や後始末のために」 PDO を使う。
- ※フィクスチャ=アプリケーション(static変数等)やデータベースの初期状態
- アプリケーション側でも PDO を使わないといけないということではない
- DBUnit は「初期化(フィクスチャの作成)や後始末のために」 PDO を使う。
- 考え方
- データベースは基本的に、自分のコードへのグローバルな入力変数である
- → 後続のテストのためにも、きちんとデータの後始末が必要
- データベースは基本的に、自分のコードへのグローバルな入力変数である
- 制限事項
- テストのクラスごとに接続/切断を繰り返すので、テスト全体の終了までに時間がかかりがち
- → 接続を使いまわすことで時間を節約できる
- テストのクラスごとに接続/切断を繰り返すので、テスト全体の終了までに時間がかかりがち
- テストのステップ
- 1.フィクスチャのセットアップ(Setup)
- 2.テストしたいシステムの実行(Exercise)
- 3.結果の検証(Verify)
- 4.後始末(Teardown)
- データベースの接続情報
- 接続用インスタンスを抽象クラス内のプロパティとして持つ
- 設定情報(DB名、ユーザー名等)は XML ファイルで指定可能
- XML ファイルを複数用意し、コマンドラインで切り替え可能
- → データベースを分けることで、複数人が同時にテストできる
- データセットとデータテーブル
- データベースのテーブル/行/カラムの抽象化レイヤー
- 実際のデータはファイル(XML/YAML/CSV)で持ったりすることも可能
- PHPの配列で持つことも可能
データセット
- フラット XML データセット
- ファイルはシンプルで見やすいが、NULL の扱いに制限あり
- createFlatXmlDataSet($filename) でインスタンスを生成
- XML データセット
- ファイル形式はやや冗長だが、NULL の問題は発生しない
- createXmlDataSet($filename) でインスタンスを生成
- MySQL XML データセット
- mysqldump の出力をそのまま読み込める
- createMySQLXMLDataSet($filename) でインスタンスを生成
- YAML データセット
- ファイルはシンプルで見やすく、NULL の問題も発生しない
- 専用のファクトリーメソッドが存在しないので、手動でインスタンスを new する(以下同様)
- new PHPUnit_Extensions_Database_DataSet_YamlDataSet
- CSV データセット
- NULL 値は指定不可
- new PHPUnit_Extensions_Database_DataSet_CsvDataSet
- Array データセット
- ソース中に PHP のコードとして直接データを書ける。いろいろとメリットあり。
- Query (SQL) データセット
- DBのスキーマやデータの中身を流用可能
- 内部で自由に SQL を発行してデータを取り込める
- new PHPUnit_Extensions_Database_DataSet_QueryDataSet
- Database (DB) データセット
- 自動的にすべてのテーブルとその中身を含むデータセットを生成
- Replacement データセット
- NULL の問題を内部のフィルター関数を使って解決する
- データセットフィルタ
- ホワイトリストあるいはブラックリストとして使い、テーブルやカラムを絞り込んだサブデータセットを作る
- Composite データセット
- 既存の複数のデータセットをひとつにまとめる
- 自作
- 上記で満足できない人は、自作も可能。もちろん実装の理解が必要。
データベースアサーション API
- テーブルの行数のアサーション
- assertEquals() で行数を調べる
- テーブルの状態のアサーション
- assertTablesEqual() で、テーブルの中身(全部)が期待した内容と等しいか調べる
- クエリ結果のアサーション
- assertTablesEqual() で、クエリーの結果を期待した内容と比較
- 複数のテーブルの状態のアサーション
- 1.接続の Database (DB) データセットを使い、 それをファイルベースのデータセットと比較する
- 2.データセットを自分で作る
よくある質問
- PHPUnit は、テストごとにデータベーススキーマを作り直すの?
- No
- PDO を使ったアプリケーションじゃないと Database Extension を使えないの?
- No
- 「Too much Connections」 というエラーが出たらどうすればいい?
- 接続を使いまわす
- フラット XML や CSV のデータセットで NULL を扱う方法は?
- 使えません