karakaram-blog

[Symfony2] DoctrineFixturesBundleをPHPUnitと連動させる方法

 ツイート 0  シェア 0  Google+1 0  Hatena 2

symfony-logo

前回の記事で、Symfony2のblogチュートリアルにファンクショナルテストを書きましたが、前回書いたテストにはテストメソッドの実行順序に依存関係がありました。例えば、先にデータ登録のテストを記述しないと詳細画面のテストが失敗するといった状態でした。

この問題を解決するためにDoctrineFixturesBundleを導入します。

参考にさせていただいたサイト

動作確認環境

  • Symfony 2.0.11
  • PHP 5.3.10
  • PHPUnit 3.6.10

目次

  1. Symfony/depsファイルの編集
  2. DoctrineFixturesBundleのダウンロードとインストール
  3. Symfony/app/autoload.phpの編集
  4. Symfony/app/AppKernel.phpの編集
  5. Fixtureの作成
  6. コマンドラインからFixtureをロードする
  7. テストコードからFixtureをロードする
  8. 11章に進み、リファクタリングを行う

Symfony/depsファイルの編集

Symfony/deps ファイルに下記を追加します。私は[doctrine]ブロックの上に追加しました。

...
[doctrine-fixtures]
    git=http://github.com/doctrine/data-fixtures.git

[DoctrineFixturesBundle]
    git=http://github.com/doctrine/DoctrineFixturesBundle.git
    target=/bundles/Symfony/Bundle/DoctrineFixturesBundle
    version=origin/2.0
...

DoctrineFixturesBundleのダウンロードとインストール

DoctrineFixturesBundleをインストールするにはgitが必要です。以下の手順に進む前にgitをインストールし、githubからgit cloneできる状態にしておきます。

Symfonyのディレクトリに移動し、下記コマンドを実行します。私は念のため、apacheとmysqlを停止して実行しました。

$ php bin/vendors install --reinstall

githubよりファイルのダウンロードとインストールが行われます。

インストール完了後に Clearing the cache for the dev environment with debug true と表示されたので下記コマンドを入力してキャッシュを消しました。不要な操作かもしれませんが、念のため。

$ php app/console cache:clear --no-warmup

メモ

以前、インストールの途中で Symfony/app/cache ディレクトリに何か残っているといった内容のエラーが出たことがあります。

php app/console cache:clear –no-warmup を行なってもエラーは消えず、よく分からなかったので、sudo rm -rf Symfony/app/cache/* して Symfony/app/cache に再度書き込み権限を与えたところうまくいきました。

キャッシュを削除したことによる影響は分かりませんが、インストール後、特に問題なく動作しているのでよしとします。

テストの実行

インストール処理でいろいろ更新されたようですので、前回の記事で作成したテストを走らせてみます。

$ phpunit -c app/

PHPUnit 3.6.10 by Sebastian Bergmann.

Configuration read from /Users/karakaram/Sites/Symfony/app/phpunit.xml.dist

........

Time: 5 seconds, Memory: 40.75Mb

OK (8 tests, 22 assertions)

テストがOKなのでアプリケーションへの影響はなさそうです。

Symfony/app/autoload.phpの編集

Symfony/app/autoload.php の $loader->registerNamespaces() メソッドの引数に下記を追加します。私はDoctrine\\Commonの上に追加しました。

$loader->registerNamespaces(array(
	...
    'Doctrine\\Common\\DataFixtures' => __DIR__.'/../vendor/doctrine-fixtures/lib',
	...
));

Symfony/app/AppKernel.phpの編集

Symfony/app/AppKernel.php の registerBundles() メソッドの $bundles 変数に下記を追加します。私はDoctrineBundleの下に追加しました。

public function registerBundles()
{
    ...
    $bundles = array(
        ...
        new Symfony\Bundle\DoctrineFixturesBundle\DoctrineFixturesBundle(),
        ...
    );
    ...
}

以上でインストールは完了です。テストを実行してアプリケーションが壊れていないことを確認してから先に進みましょう。

Fixtureの作成

DoctrineFixturesBundleでは、FixtureはPHPで記述します。csvやymlによるFixtureはサポートされていないようです。

以下、Fixtureです。ファイルの名前はマニュアルにならって、LoadPostData.php としました。

// src/My/BlogBundle/DataFixtures/ORM/LoadPostData.php

namespace My\BlogBundle\DataFixtures\ORM;

use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use My\BlogBundle\Entity\Post;

/**
 * My\BlogBundle\Entity\PostエンティティのFixture
 *
 * @uses Doctrine\Common\DataFixtures\FixtureInterface
 */
class LoadPostData implements FixtureInterface
{
    /**
     * load
     *
     * @param Doctrine\Common\Persistence\ObjectManager $manager
     * @access public
     * @return void
     */
    public function load(ObjectManager $manager)
    {
        $post = new Post();

        $post->setTitle('title');
        $post->setBody('bodybodybody');
        $post->setCreatedAt(new \DateTime());
        $post->setUpdatedAt(new \DateTime());

        $manager->persist($post);
        $manager->flush();
    }
}

コマンドラインからFixtureをロードする

Fixtureができたら、コマンドラインからFixtureをロードしてみます。

下記コマンドでロードできます。–purge-with-truncate はテーブルをtruncateしてからロードするオプションです。

$ php app/console doctrine:fixtures:load --purge-with-truncate

テストコードからFixtureをロードする

前回書いたテストコードにsetupメソッドを追加し、Fixtureをロードするコードを追加します。テストメソッドが実行されるごとにデータがFixtureで初期化されるようになります。

use文がいくつか追加されていることに注意してください。

// src/My/BlogBundle/Tests/Controller/DefaultControllerTest.php

namespace My\BlogBundle\Tests\Controller;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Bundle\FrameworkBundle\Client;
use Symfony\Component\DomCrawler\Form;
use Doctrine\Common\DataFixtures\Loader;
use Doctrine\Common\DataFixtures\Executor\ORMExecutor;
use Doctrine\Common\DataFixtures\Purger\ORMPurger;
use My\BlogBundle\DataFixtures\ORM\LoadPostData;

/**
 * DefaultControllerTest
 *
 * @uses Symfony\Bundle\FrameworkBundle\Test\WebTestCase
 */
class DefaultControllerTest extends WebTestCase
{
    /**
     * setUp
     *
     * @access public
     * @return void
     */
    public function setUp()
    {
        $kernel = static::createKernel();
        $kernel->boot();
        $loader = new Loader($kernel->getContainer());
        $loader->addFixture(new LoadPostData);
        $fixtures = $loader->getFixtures();
        $em = $kernel->getContainer()->get('doctrine.orm.entity_manager');
        $purger = new ORMPurger($em);
        $purger->setPurgeMode(ORMPurger::PURGE_MODE_TRUNCATE);
        $executor = new ORMExecutor($em, $purger);
        $executor->execute($fixtures);
    }
    //中略

setupメソッドを追加したら、テストメソッドの順番を変えてテストを実行してみます。例えば、削除のテストを先頭に移動してテストを実行してみます。テストが通ればFixtureの導入は成功です。

テストコードもFixtureに合わせてリファクタリングします。

11章に進み、リファクタリングを行う

次回はblogチュートリアル(11) まとめと応用に進みます。テストコードがありますので、安心してリファクタリングできます。

今回の記事のソースコードもgithubに置いてあります。tagは10.1です。
https://github.com/karakaram/symfony2-blog-tutorial/tags

 ツイート 0  シェア 0  Google+1 0  Hatena 2