【PHPUnit x MySQL】データベースのテスト
PHPでデータベースのテストをするためのメモ。
データベーステストの四段階
データベーステストは次の四段階を踏む必要があります。
Gerard Meszaros は、著書 xUnit Test Patterns でユニットテストを次の四段階に分類しています。
1. フィクスチャのセットアップ (Setup)
2. テストしたいシステムの実行 (Exercise)
3. 結果の検証 (Verify)
4. 後始末 (Teardown
このテストの仕組みを一から作るのは面倒です。
そこで、PHPUnitのDBUnit拡張を使います。
DBUnit拡張を使うことによって、データベースの初期化やテストに使用したデータの後始末をうまくやってくれます。
データベース設定を記述
テストに使うデータベースを設定します。
phpunit.xml にデータベース接続に必要な情報を記述します。
phpunit.xml
<?xml version="1.0" encoding="UTF-8" ?> <phpunit bootstrap="src/autoload.php" colors="true"> <testsuite name="tddbc4"> <directory>tests</directory> </testsuite> <php> <var name="DB_DSN" value="mysql:dbname=tddbc4;host=localhost" /> <var name="DB_USER" value="user" /> <var name="DB_PASSWD" value="password" /> <var name="DB_DBNAME" value="tddbc4" /> </php> </phpunit>
テーブルについて
データベーステストで用いるテーブルは予め用意しておく必要があります。
今回用意したテーブルはこんな感じです。
(ER図の関連線の引き方よく分かってない)
ちなみに TDDBC お題 のお題4を通して勉強したのでそのようなテーブルになってます。
初期化に用いるデータの準備
次に初期化に用いるデータセットを用意します。
XMLやCSV、Array等、様々な形式でデータセットを用意することができます。
今回はMySQL XMLデータセットを使いました。
データベースにテストデータとするレコードが入っている状態で、mysqldump
コマンドの --xml
オプションでdumpすることで簡単作成できます。
tests/data_set.xml
<?xml version="1.0"?> <mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <database name="tddbc4"> <table_data name="ng_word"> <row> <field name="id">1</field> <field name="name">Arsenal</field> </row> <row> <field name="id">2</field> <field name="name">悟空</field> </row> </table_data> <table_data name="user"> <row> <field name="id">2</field> <field name="name">taro</field> </row> <row> <field name="id">1</field> <field name="name">t_wada</field> </row> </table_data> <table_data name="user_ng_word"> <row> <field name="id">1</field> <field name="user_id">1</field> <field name="ng_word_id">1</field> </row> <row> <field name="id">2</field> <field name="user_id">1</field> <field name="ng_word_id">2</field> </row> <row> <field name="id">3</field> <field name="user_id">2</field> <field name="ng_word_id">2</field> </row> </table_data> </database> </mysqldump>
テストコードの記述
データベーステストを行うためにまず、PHPUnit_Extensions_Database_TestCase
抽象テストケースを継承したクラス(今回の場合、Generic_Tests_DatabaseTestCase クラス)を作ります。
さらに、2つの抽象メソッド getConnection()
と getDataSet()
を実装します。
これらのメソッドはデータベース接続と初期化が目的です。
実際のテストコードは Generic_Tests_DatabaseTestCase クラスを継承したクラスに記述します。
tests/DatabaseTest.php
<?php // ===== // 引用元 // ===== // PHPUnit マニュアル - 第8章 データベースのテスト // https://phpunit.de/manual/current/ja/database.html abstract class Generic_Tests_DatabaseTestCase extends PHPUnit_Extensions_Database_TestCase { // PDO のインスタンス生成は、クリーンアップおよびフィクスチャ読み込みのときに一度だけ static private $pdo = null; // PHPUnit_Extensions_Database_DB_IDatabaseConnection のインスタンス生成は、テストごとに一度だけ private $conn = null; final public function getConnection() { if ($this->conn === null) { if (self::$pdo == null) { self::$pdo = new PDO( $GLOBALS['DB_DSN'], $GLOBALS['DB_USER'], $GLOBALS['DB_PASSWD'] ); } $this->conn = $this->createDefaultDBConnection(self::$pdo, $GLOBALS['DB_DBNAME']); } return $this->conn; } public function getDataSet() { return $this->createMySQLXMLDataSet('tests/data_set.xml'); } } class DatabaseTest extends Generic_Tests_DatabaseTestCase { /** * @test */ public function 指定したng_wordが検閲に引っ掛かった回数を表示できること() { $filter = new WordFilter(); $ng_word = '悟空'; $num_of_ng_word = $filter->get_num_of_ng_word($ng_word); $this->assertEquals(2, $num_of_ng_word); } }
あとはREDとGREENを回すだけです。
実際にデータベーステストを行うと、面倒なことを凄く簡単にできている感があります。