PHPUnit+DbUnit

2013-01-06T00:00:00+00:00 PHP PHPUnit

引き続きPHPUnitドキュメント読みつつ進めてみる

とにかくPHPUnit_Extensions_Database_TestCaseを使えるようにしないといけないのだけど、こいつ自体はDbUnitに入ってる模様なので、DbUnitを入れる

pear install phpunit/DbUnit

んでディレクトリ構造

├── fixture.yaml
├── fixture1.xml
├── fixture2.xml
├── phpunit.xml
└── tests
    └── sample.php

でディレクトリ構造にあるようにデータベースにテストデータを注入するfixture自体が色々種類がある

  • 通常のXMLファイル
  • フラットなXMLファイル
  • YAMLファイル
  • CSVファイル

他にも色々あるけど、今回はフラットなXMLファイルとYAMLファイルの2つをやってみる

phpunit.xml

<?xml version="1.0" ?>
<phpunit>
    <php>
        <var name="DB_DSN" value="mysql:dbname=sample" />
        <var name="DB_USER" value="user" />
        <var name="DB_PASS" value="pass" />
    </php>
    <testsuites>
        <testsuite>
            <directory suffix=".php">tests</directory>
        </testsuite>
    </testsuites>
</phpunit>

な感じでデータベース接続に必要な情報をphpunit.xml側に設定する。これでスーパーグローバル変数から参照出来る模様

fixture1.xml

<?xml version="1.0" ?>
<dataset>
    <sample id="1" name="hoge" created="2013-01-01 00:00:00" />
    <sample id="2" name="fuga" created="2013-01-02 00:00:00" />
</dataset>

<dataset>内のノードはノード名がテーブル名、属性がカラム名とその値になるようなのでそのフォーマット方式に従って定義する

fixture2.xml

<?xml version="1.0" ?>
<dataset>
    <item id="3" name="foobar" price="100" />
</dataset>

fixture1.xmlと同様なフラット方式なXMLファイル。PHPUnit_Extensions_Database_DataSet_CompositeDataSetを使う事でfixtureを複数使う事が出来る模様

fixture.yaml

sample:
  - name: hoge
    created: "2013-01-01 00:00:00"
  - name: fuga
    created: "2012-01-01 00:00:00"

あとは上記のをテストケース上で使うだけ

tests/sample.php

<?php
// 普通のXML FixtureはcreateXMLDataSet
// フラットなXML FixtureはcreateFlatXmlDataSet
// mysqldump --xmlな場合はcreateMySQLXMLDataSet

class SampleTestCase extends PHPUnit_Extensions_Database_TestCase {

    private $db;

    private function getDB() {
        if (is_null($this->db)) {
            global $DB_DSN, $DB_USER, $DB_PASS;

            $this->db = new PDO($DB_DSN, $DB_USER, $DB_PASS);
        }

        return $this->db;
    }

    // PHPUnit_Extensions_Database_TestCaseで必要
    public function getConnection() {
        return $this->createDefaultDBConnection($this->getDB(), "sample");
    }

    // PHPUnit_Extensions_Database_TestCaseで必要
    public function getDataSet() {
        /* CompositeDataSetを使う場合

        $ds1 = $this->createFlatXmlDataSet("fixture1.xml");
        $ds2 = $this->createFlatXmlDataSet("fixture2.xml");

        return new PHPUnit_Extensions_Database_DataSet_CompositeDataSet(
            array($ds1, $ds2)
        );
        */

        return new PHPUnit_Extensions_Database_DataSet_YamlDataSet("fixture.yaml");
    }

    public function test1() {
        $db = $this->getDB();

        $st = $db->prepare("SELECT * FROM sample");
        $st->execute();

        $results = $st->fetchAll(PDO::FETCH_ASSOC);
        $this->assertCount(2, $results);
    }

    public function test2() {
        $this->assertThat(
            $this->getConnection()->getRowCount("sample"),
            $this->equalTo(2)
        );
    }
}

ってな感じかなと。個人的にはあくまでfixture的な扱いを使う前提だけで良いのではと思う所(モデルとかテストする名目であれば別にDbUnitな機能を使う必要性があるのかが微妙)

PHPUnit+Seleniumと雑多メモ ざっくりとPHPUnitマニュアル読みつつやってみる