概要
PHPUnitとDBUnitを使ってMySQLのテストを行う(Oracleのテストもできる)
テスト用のMySQLを用意してPHPUni+DBUnitでinsert,updateなどのテストを行って
その後に意図したデータになっているか確認をすることができる
テストの流れ
データベースのテストは次の4段階に分けて考える必要がある
Gerard Meszaros は、著書 xUnit Test Patterns でユニットテストを次の四段階に分類しています。
- フィクスチャのセットアップ (Setup)
- テストしたいシステムの実行 (Exercise)
- 結果の検証 (Verify)
- 後始末 (Teardown)
フィクスチャとはアプリケーションやデータベースの初期状態のこと、テストを実行する前に用意する
環境の準備
MySQLのインストール
$ sudo yum -y install http://dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm $ sudo yum -y install mysql-community-server $ sudo service mysqld start
MySQL環境の準備
$ mysql -uroot -p -e "create database test_database" $ mysql -uroot -p -e "create table test_database.hoge_table (id int, name varchar(20))"
MySQL環境の確認
$ mysql -uroot -p -e "show databases" Enter password: +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test_database | +--------------------+ $ mysql -uroot -p -e "use test_database;show tables;desc hoge_table" Enter password: +-------------------------+ | Tables_in_test_database | +-------------------------+ | hoge_table | +-------------------------+ +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | | name | varchar(20) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+
PHP5.6のインストール
$ sudo rpm -Uvh http://ftp.iij.ad.jp/pub/linux/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm $ sudo rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm $ sudo yum install -y --enablerepo=remi --enablerepo=remi-php56 php php-opcache php-devel php-mbstring php-mcrypt php-mysqlnd php-phpunit-PHPUnit php-pecl-xdebug php-pecl-xhprof $ php --version PHP 5.6.20 (cli) (built: Mar 31 2016 07:24:47) Copyright (c) 1997-2016 The PHP Group Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies with Xdebug v2.4.0, Copyright (c) 2002-2016, by Derick Rethans
composerのインストール
$ curl -sS https://getcomposer.org/installer | php $ sudo mv composer.phar /usr/local/bin/composer $ composer -V Composer version 1.0.0 2016-04-05 13:27:25
phpunitのインストール
$ mkdir phpunit; cd phpunit $ vim composer.json $ cat composer.json { "require-dev": { "phpunit/phpunit": "4.5.*", "phpunit/dbunit": ">=1.2" } } $ sudo /usr/local/bin/composer install $ vendor/bin/phpunit -V PHPUnit 4.5.1 by Sebastian Bergmann and contributors. unrecognized option -- V
PHPUnitファイルの用意
最終的に以下のようにファイルを作成する
$ tree . ├── composer.json ├── composer.lock ├── tests │ ├── assert # テストファイル │ │ └── HogeTableTest.php │ ├── common # テストファイル共通の処理が書かれている │ │ └── Generic_Tests_DatabaseTestCase.php │ ├── _fixute # データセット │ │ └── hoge_table.csv │ └── phpunit.xml # DB接続情報を記述 └── vendor # composerを使ってinstallしたdbunit,phpunitのファイル群が入っている
DB接続情報を記述したファイルの用意
PHPUnit実行時に引数でこのファイルを指定する
最悪このファイルがなくてもPHPUnitのファイルにDB情報を直接記述するのも可
$ mkdir -p tests/common $ mkdir -p tests/assert $ mkdir -p tests/_fixute $ cat tests/phpunit.xml <?xml version="1.0" encoding="UTF-8" ?> <phpunit> <php> <var name="DB_DSN" value="mysql:dbname=test_database;host=localhost" /> <var name="DB_USER" value="root" /> <var name="DB_PASSWD" value="" /> <var name="DB_DBNAME" value="test_database" /> </php> </phpunit>
共通ロジックをまとめたファイルを用意
$ cat tests/common/Generic_Tests_DatabaseTestCase.php <?php abstract class Generic_Tests_DatabaseTestCase extends PHPUnit_Extensions_Database_TestCase { // PDO のインスタンス生成は、クリーンアップおよびフィクスチャ読み込みのときに一度だけ static private $pdo = null; // PHPUnit_Extensions_Database_DB_IDatabaseConnection のインスタンス生成は、テストごとに一度だけ private $conn = null; /** * @return PHPUnit_Extensions_Database_DB_IDatabaseConnection */ 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; } }
フィクスチャを作る
記述方法はYAML,CSV,Array,XMLなどで記述できる
YAMLが一番わかりやすいがMySQLのselectはCSV形式で出力できるためそのまま活用できやすいのでCSVで作成する
$ cat tests/_fixute/hoge_table.csv id,name 1,'tomsato' 2,'hogehoge' 3,'hello world' 11,'testtest'
テストケースを作成する
$ cat tests/assert/HogeTableTest.php <?php require_once dirname(__DIR__).'/common/Generic_Tests_DatabaseTestCase.php'; class HogeTableTest extends Generic_Tests_DatabaseTestCase { /** * @return PHPUnit_Extensions_Database_DataSet_IDataSet */ protected function getDataSet() { $dataSet = new PHPUnit_Extensions_Database_DataSet_CsvDataSet(); $dataSet->addTable('hoge_table', dirname(__DIR__)."/_fixute/hoge_table.csv"); return $dataSet; } public function testGetRowCount() { // 4件insertしたのでテーブルの件数が4件になっていることを確認する $this->assertEquals(4, $this->getConnection()->getRowCount('hoge_table')); } }
PHPUnit実行
以下のコマンドを実行すると対象のtableにデータが入ってテストケースが実行されます
実行時にはtableが一度クリーンされるので空の状態でデータが入るので冪等性を意識して、何度でもテストを再実行できるようにしましょう
$ vendor/bin/phpunit -c tests/phpunit.xml tests/assert/HogeTableTest.php PHPUnit 4.5.1 by Sebastian Bergmann and contributors. Configuration read from /home/tomsato/phpunit/tests/phpunit.xml . Time: 259 ms, Memory: 3.75Mb OK (1 test, 1 assertion)
■ もう少し修正を加えてみる
任意のSQLを実行する
// 以下のメソッドを追加 $ vim tests/common/Generic_Tests_DatabaseTestCase.php ... public function getPdo() { return self::$pdo; } ... // update文を記述 $ vim tests/assert/HogeTableTest.php public function testUpdateSql() { $pdo = $this->getPdo(); $pdo->exec("update hoge_table set id=111 where id='11'"); } // 実行 $ vendor/bin/phpunit -c tests/phpunit.xml tests/assert/HogeTableTest.php
実行後にtableを確認するとupdate文が実行されている
CSVデータとテーブルをSELECTした結果を比較する
updateなどでデータを修正した後に意図したデータになっているか確認するために
CSV(他にYAML,配列,XMLなど)データとテーブルをSELECTした結果を比較する
// 以下のメソッドを追加する $ vim tests/assert/HogeTableTest.php ... public function testQuerySql() { $queryTable = $this->getConnection()->createQueryTable( 'hoge_table', 'select * from hoge_table' ); $expectedTableObj = new PHPUnit_Extensions_Database_DataSet_CsvDataSet(); $expectedTableObj->addTable('hoge_table', dirname(__DIR__)."/_fixute/hoge_table.csv"); $expectedTable = $expectedTableObj->getTable('hoge_table'); $this->assertTablesEqual($expectedTable, $queryTable); } ... // 実行 $ vendor/bin/phpunit -c tests/phpunit.xml tests/assert/HogeTableTest.php
参考
基本はマニュアルを熟読する
コメントを書く
コメント一覧