読者です 読者をやめる 読者になる 読者になる

tanaka's Programming Memo

プログラミングについてのメモ。

PHPUnitによるデータベース操作のテスト

ユーザーを管理する操作をテスト駆動開発の手法で作ってみるために調査しました。

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

データベースのテストにはPHPUnit_Extensions_Database_TestCaseを継承して行うとあります。その場合はSeleniumとの同時テストはできません。テストはなるべく切り分けた方がよいので、データベースの操作はSeleniumとは連携させずに単体でテストすることにします。

テスト用のファイルなどを整える

テスト用のデータベースは、ローカルに立ち上げているMySQLにします。これにテスト用のデータベースとユーザーを登録して、テスト時には、そこに接続するようにします。

以下を参考に、環境を構築しました。
PHP DBまわりのテスト - Qiita

データベースを作成

  • ローカルのphpmyadminにルートでログイン
  • テスト用のDBを検索順を指定して作成
  • 作成したデータベースを選択
  • 特権メニューを選択
  • ユーザを追加する
  • ユーザ名とHost、パスワードを設定。作成したデータベースへの全ての特権を与えるにチェックを入れて実行

テスト用のデータベースの構築

  • 作成したデータベースに必要なテーブルを追加したり、データを追加する
  • テストに利用するデータは、MySQLXML形式でエクスポートしたものを利用可能
  • BLOBなどのバイナリデータは、SQL形式のみの出力になる。

設定ファイルの作成

  • testsフォルダー内に以下のようなphpunit.xmlというファイルを作成して、各項目を設定する。
<?xml version="1.0" encoding="UTF-8" ?>
<phpunit>
    <php>
        <var name="DB_DSN" value="mysql:dbname=<データベース名>;host=localhost" />
        <var name="DB_USER" value="<ユーザー名>" />
        <var name="DB_PASSWD" value="<パスワード>" />
        <var name="DB_DBNAME" value="<データベース名>" />
    </php>
</phpunit>

共通コードの作成

PHPUnit マニュアル – 第8章 データベースのテストから、共通コードを自分のtestsフォルダー内に作成しておく。以下、抜粋。

<?php
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;
    }
}
?>

テストデータの準備

PHPUnit マニュアル – 第8章 データベースのテストでは、様々な形式でデータセットを準備する方法が紹介されていますが、今回はAES_ENCRYPT()で暗号化したフィールドがあります。紹介されている方法は全てのデータがテキストである必要があるため使えません。

そこで、SQLを使って、テーブルを削除する関数と、配列に設定したデータを必要な部分は暗号化して登録する関数を作成しました。

DBへの接続はもともとPDOを利用していましたので、getConnection()後を呼び出したあとにそのPDOを利用するか、getConnection()と同じパラメータで自分でMySQLに接続します。今回は、自分で接続しました。

現在の状況

自分でMySQLにデータを登録した場合でも、getConnection()やgetDataSet()の機能は利用できますので、行数などは簡単に取得できます。

ただし、バイナリには非対応ですので、データベースレベルでのアサートはせず、テスト対象の機能の戻り値などでアサートして済ませています。