PHPUnit + DBUnitでMySQLのテストを行う

■ 目次

  1. 概要
  2. テストの流れ
  3. 環境の準備
    1. MySQLのインストール
    2. MySQL環境の準備
    3. PHP5.6のインストール
    4. composerのインストール
    5. phpunitのインストール
  4. PHPUnitファイルの用意
    1. DB接続情報を記述したファイルの用意
    2. 共通ロジックをまとめたファイルを用意
    3. フィクスチャを作る
    4. テストケースを作成する
  5. PHPUnit実行
  6. もう少し修正を加えてみる
    1. 任意のSQLを実行する
    2. CSVデータとテーブルをSELECTした結果を比較する
  7. 参考

■ 概要

PHPUnitとDBUnitを使ってMySQLのテストを行う(Oracleのテストもできる)
テスト用のMySQLを用意してPHPUni+DBUnitでinsert,updateなどのテストを行って
その後に意図したデータになっているか確認をすることができる

■ テストの流れ

データベースのテストは次の4段階に分けて考える必要がある

Gerard Meszaros は、著書 xUnit Test Patterns でユニットテストを次の四段階に分類しています。

  1. フィクスチャのセットアップ (Setup)
  2. テストしたいシステムの実行 (Exercise)
  3. 結果の検証 (Verify)
  4. 後始末 (Teardown)

PHPUnit マニュアル – 第8章 データベースのテスト

フィクスチャとはアプリケーションやデータベースの初期状態のこと、テストを実行する前に用意する

■ 環境の準備

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

■ 参考

基本はマニュアルを熟読する


Be First to Comment

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です