69

アプリケーションでいくつかの基本的なルートを実行するWebTestCaseがあります。

setUpPHPUnitのメソッドで、メインデータベースと同じテストデータベースを作成し、それにフィクスチャをロードしたいと思います。

私は現在、いくつかの回避策を実行し、次のようないくつかのコンソールコマンドを実行しています。

class FixturesWebTestCase extends WebTestCase
{
    protected static $application;

    protected function setUp()
    {
        self::runCommand('doctrine:database:create');
        self::runCommand('doctrine:schema:update --force');
        self::runCommand('doctrine:fixtures:load --purge-with-truncate');
    }

    protected static function runCommand($command)
    {
        $command = sprintf('%s --quiet', $command);

        return self::getApplication()->run(new StringInput($command));
    }

    protected static function getApplication()
    {
        if (null === self::$application) {
            $client = static::createClient();

            self::$application = new Application($client->getKernel());
            self::$application->setAutoExit(false);
        }

        return self::$application;
    }
}

しかし、これは最善のアプローチではないと確信しています。特に、ユーザーがcharを押してアクションを確認することdoctrine:fixtures:loadを期待しているためです。Y

どうすればそれを解決できますか?

4

7 に答える 7

38

を使用する場合doctrine:fixtures:loadは、このオプションを使用し--appendてユーザーの確認を回避できます。毎回データベースを再作成するため、パージは不要です。以前はテストにドクトリンフィクスチャのみを使用していましたが、その後、DRYを回避するためにフィクスチャとLiipFunctionalTestBundleの使用に切り替えました。このバンドルにより、器具の管理が容易になります。

編集:David Jacquelの答えは、DoctrineFixturesをロードするための正しい答えです。

doctrine:fixtures:load --no-interaction 
or
doctrine:fixtures:load -n
于 2013-02-07T15:15:18.077 に答える
36

ユーザー確認をバイパスするために使用できます

doctrine:fixtures:load --no-interaction
or
doctrine:fixtures:load -n
于 2013-10-15T13:11:25.850 に答える
35

更新された回答

Doctrine Data Fixturesライブラリのいくつかのクラスを活用することで、フィクスチャのロードを容易にするテストケースの基本クラスを作成できます。このクラスは次のようになります。

<?php

use Doctrine\Common\DataFixtures\Executor\ORMExecutor;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\DataFixtures\Purger\ORMPurger;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bridge\Doctrine\DataFixtures\ContainerAwareLoader;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;

abstract class FixtureAwareTestCase extends KernelTestCase
{
    /**
     * @var ORMExecutor
     */
    private $fixtureExecutor;

    /**
     * @var ContainerAwareLoader
     */
    private $fixtureLoader;

    public function setUp()
    {
        self::bootKernel();
    }

    /**
     * Adds a new fixture to be loaded.
     *
     * @param FixtureInterface $fixture
     */
    protected function addFixture(FixtureInterface $fixture)
    {
        $this->getFixtureLoader()->addFixture($fixture);
    }

    /**
     * Executes all the fixtures that have been loaded so far.
     */
    protected function executeFixtures()
    {
        $this->getFixtureExecutor()->execute($this->getFixtureLoader()->getFixtures());
    }

    /**
     * @return ORMExecutor
     */
    private function getFixtureExecutor()
    {
        if (!$this->fixtureExecutor) {
            /** @var \Doctrine\ORM\EntityManager $entityManager */
            $entityManager = self::$kernel->getContainer()->get('doctrine')->getManager();
            $this->fixtureExecutor = new ORMExecutor($entityManager, new ORMPurger($entityManager));
        }
        return $this->fixtureExecutor;
    }

    /**
     * @return ContainerAwareLoader
     */
    private function getFixtureLoader()
    {
        if (!$this->fixtureLoader) {
            $this->fixtureLoader = new ContainerAwareLoader(self::$kernel->getContainer());
        }
        return $this->fixtureLoader;
    }
}

次に、テストケースで、上記のクラスを拡張し、テストの前に必要なすべてのフィクスチャを追加して実行します。これにより、フィクスチャをロードする前にデータベースが自動的にパージされます。例は次のとおりです。

class MyTestCase extends FixtureAwareTestCase
{
    public function setUp()
    {
        parent::setUp();

        // Base fixture for all tests
        $this->addFixture(new FirstFixture());
        $this->addFixture(new SecondFixture());
        $this->executeFixtures();

        // Fixtures are now loaded in a clean DB. Yay!
    }
}

古い答え

(この回答は、後でフィクスチャをロードする方法を説明せずにデータベースをクリーンアップする方法のみを説明しているため、「非推奨」にすることにしました)。

コマンドを実行せずにこれを実現するさらにクリーンな方法があります。基本的には、SchemaToolとORMPurgerを組み合わせて使用​​します。この種の操作を実行する抽象基本クラスを作成して、特殊なテストケースごとにそれらを繰り返さないようにすることができます。一般的なテストケースのデータベースを設定するテストケースクラスのコード例を次に示します。

use Doctrine\Common\DataFixtures\Purger\ORMPurger;
use Doctrine\ORM\Tools\SchemaTool;

abstract class DatabaseAwareWebTestCase extends WebTestCase {

    public static function setUpBeforeClass() {

        parent::setUpBeforeClass();

        $kernel = static::createKernel();
        $kernel->boot();
        $em = $kernel->getContainer()->get('doctrine')->getManager();
        $schemaTool = new SchemaTool($em);
        $metadata = $em->getMetadataFactory()->getAllMetadata();

        // Drop and recreate tables for all entities
        $schemaTool->dropSchema($metadata);
        $schemaTool->createSchema($metadata);
    }

    protected function tearDown() {

        parent::tearDown();

        $purger = new ORMPurger($this->getContainer()->get('doctrine')->getManager());
        $purger->setPurgeMode(ORMPurger::PURGE_MODE_TRUNCATE);
        $purger->purge();
    }
}

このように、上記のクラスを継承する各テストケースを実行する前に、データベーススキーマを最初から再構築し、テストを実行するたびにクリーンアップします。

お役に立てれば。

于 2014-03-02T19:53:15.187 に答える
6

Doctrine-Test-Bundleという名前の本当にすてきなバンドルに出くわしました 。すべてのテストでスキーマを作成してドロップする代わりに、単にロールバックします。私のテストは1分40秒から..2秒になりました。そしてそれは孤立しています。必要なのは明確なテストデータベースだけで、それでうまくいきます。

于 2017-06-13T10:15:29.963 に答える
2

私はこのコマンドを使用しました:

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

しかしもちろん、LiipFunctionalTestBundleは有望に見えます。

于 2013-11-17T05:55:13.793 に答える
1

doctrine:fixtures:loadコマンドのようにすべてのフィクスチャをロードしたかったのです。execテストケースの中から実行するのは面倒な方法のように思えたので、実行したくありませんでした。私は、ドクトリンコマンドがこれをどのように実行するかを調べ、関連する行にコピーしました。

私はSymfonyから拡張しWebTestCase、カーネルが作成された後、Doctrineload-fixturesコマンドとまったく同じように機能するメソッドを呼び出しました。

    /**
     * Load fixtures for all bundles
     *
     * @param Kernel $kernel
     */
    private static function loadFixtures(Kernel $kernel)
    {
        $loader = new DataFixturesLoader($kernel->getContainer());
        $em = $kernel->getContainer()->get('doctrine')->getManager();

        foreach ($kernel->getBundles() as $bundle) {
            $path = $bundle->getPath().'/DataFixtures/ORM';

            if (is_dir($path)) {
                $loader->loadFromDirectory($path);
            }
        }

        $fixtures = $loader->getFixtures();
        if (!$fixtures) {
            throw new InvalidArgumentException('Could not find any fixtures to load in');
        }
        $purger = new ORMPurger($em);
        $executor = new ORMExecutor($em, $purger);
        $executor->execute($fixtures, true);
    }
于 2015-06-21T11:35:09.743 に答える
0

つい最近、バンドルhautelook / AliceBundleは、機能テストでフィクスチャをロードするユースケースを解決するのに役立つ2つの特性を公開していRefreshDatabaseTraitますReloadDatabaseTrait

ドキュメントから:

namespace App\Tests;

use Hautelook\AliceBundle\PhpUnit\RefreshDatabaseTrait;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class NewsTest extends WebTestCase
{
    use RefreshDatabaseTrait;

    public function postCommentTest()
    {
        $client = static::createClient(); // The transaction starts just after the boot of the Symfony kernel
        $crawler = $client->request('GET', '/my-news');
        $form = $crawler->filter('#post-comment')->form(['new-comment' => 'Symfony is so cool!']);
        $client->submit($form);
        // At the end of this test, the transaction will be rolled back (even if the test fails)
    }
}

そして、あなたは良いです!

于 2018-12-08T13:02:17.597 に答える