Help us understand the problem. What is going on with this article?

PHP DBまわりのテスト

More than 5 years have passed since last update.

DBを使ったテストを考えた場合、
・Insertのテストが走るとTableにそのデータがInsertされテストが正常完了する
・上記テストをもう一度走らせると、前回のInsertされたデータがあるのでDuplicateでテストが失敗する

上記の問題を解決することを考える
・テストが走るとテーブルが初期化される
・Insertのテストが走ると初期化されているので、前のテストでInsertされたデータは消えているので、Duplicateにはならない。

phpunit/dbunit

・テストが接続するDB情報を設定できる
・テストが走るとテーブルのデータが初期化される

インストール

Composerを使ってインストール

composer.json
{
    "require": {
        "phpunit/phpunit": ">=4.0,<5.0",
        "phpunit/dbunit": ">=1.3,<1.4"
    }
}

・テストでは本番DBにはInsertさせないのでレプリカのDBとテーブルを用意する
・DBUnitはデータベースを作ったりテーブルを作ったりは出来ないので事前に用意しておく

sql
create database hogeDB

・接続するユーザーを作る

sql
GRANT ALL PRIVILEGES ON hogeDB.* TO hoge@'%' IDENTIFIED BY 'password' WITH GRANT OPTION;

テストが接続するためのDB情報

tests/phpunit.xml
<?xml version="1.0" encoding="UTF-8" ?>
  <phpunit>
    <php>
      <var name="DB_DSN" value="mysql:dbname=hogeDB;host=localhost" />
      <var name="DB_USER" value="hoge" />
      <var name="DB_PASSWORD" value="password" />
      <var name="DB_DBNAME" value="hogeDB" />
  </php>
</phpunit>

・テーブルの初期値データをmysqldumpで取得する

$ mkdir -p tests/fixture
$ mysqladmin --xml -t -u hoge -p hogeDB > tests/fixture/expect.xml

・テストの初期処理

CommonDatabaseTest.php
<?php
class CommonDatabaseTest extends PHPUnit_Extensions_Database_TestCase
{
    static public $pdo = null;
    public $connection = null;

    // テストのDB接続情報
    public function getConnection()
    {
        if ( $this->connection == null ) {
            if ( self::$pdo == null ) {
                self::$pdo = new PDO($GLOBALS['DB_DSN'],
                                     $GLOBALS['DB_USER'],
                                     $GLOBALS['DB_PASSWORD']);
                self::$pdo->query('SET NAMES UTF8');
            }
            $this->connection = $this->createDefaultDBConnection(self::$pdo, $GLOBALS['DB_DBNAME']);
        }

        return $this->connection;
    }

    // テストがDBに接続してデータを初期化する処理
    public function getDataSet()
    {
        $compositeDs = new PHPUnit_Extensions_Database_DataSet_CompositeDataSet([]);

        // fixture配下の.xmlファイルをすべて読み込んでデータセットしてる
        $dir = dirname(__FILE__) . '/fixture';
        $fh  = opendir($dir);

        while ($file = readdir($fh)) {
            if ( preg_match('/^\./', $file) ) {
                continue;
            }
            if ( preg_match('/\.xml$/', $file) ) {
                $ds = $this->createMySQLXMLDataSet("$dir/$file");
                $compositeDs->addDataSet($ds);
            }
        }

        return $compositeDs;
    }
}

・テストファイル

dbTestSample.php
require_once "CommonDatabaseTest.php";

class dbTestSample extends \CommonDatabaseTest {

    public function testRegisterUser()
    {
        // アプリ側のInsert処理
        $register = new Register();
        $result   = $register->insertMemberData([
            'name'        => '山田太郎',
            'birthday'    => '1980/08/01',
            'sex'         => 0,
        ]);

        // Insert後の期待値Tableデータ
        $expectedTables = $this->createMySQLXMLDataSet('/path/test/except/table.xml');
        $expectedMember = $expectedTables->getTable('member');

        // Insert後のTableデータ
        $doneUser = $this->getConnection()->createQueryTable('member', 'SELECT * FROM member');

        // tableの状態が同じか
        $this->assertTablesEqual($expectedMember, $doneUser);
    }

}

・実行

$ vendor/bin/phpunit -c tests/phpunit.xml tests/dbTestSample.php

所感

・まだよくわかっていない。
・アプリ側のDB接続情報も、テストで動かされた場合はテストDBに接続するように変更が必要なのかな?
・SQLのテストに使える
・機能テストに使える
・データベース接続を伴うクラス、メソッドは他との依存関係をなくすように設計する

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした