创建一个测试数据库和负载器具上的Symfony 2 WebTestCase最佳方式吗?(Best w

2019-07-19 13:38发布

我有我的应用程序执行一些基本路线一WebTestCase。

我想,在setUp PHPUnit的方法,创建一个测试数据库等同于我的主数据库和夹具加载到其中。

目前,我正在做一些变通方法和执行一些控制台命令,像这样:

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

但我敢肯定这是不是最好的方法,特别是因为doctrine:fixtures:load预计用户打一个Y字符以确认操作。

我该如何解决呢?

Answer 1:

如果你想使用doctrine:fixtures:load ,你可以使用--append选项,以避免用户确认。 既然你每次重新创建数据库,清洗是不必要的。 我习惯一个人使用原则灯具进行测试,但已经切换到使用固定装置和LiipFunctionalTestBundle以避免干燥。 这束使灯具更易于管理。

编辑:大卫Jacquel的答案是正确的加载主义灯具:

doctrine:fixtures:load --no-interaction 
or
doctrine:fixtures:load -n


Answer 2:

为了绕过用户确认就可以使用

doctrine:fixtures:load --no-interaction
or
doctrine:fixtures:load -n


Answer 3:

已更新ANSWER

您可以为您的测试用例基类,这使得灯具装载从利用一些类容易学说数据灯具库。 这个类看起来非常像这样:

<?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!
    }
}

OLD ANSWER

(我决定“弃用”这个答案,因为它只是解释了如何清理数据库瞒着如何加载后夹具)。

有完成此无需运行命令的更清洁的方式。 它基本上包括在使用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();
    }
}

通过这种方式,运行从上面的类继承的各测试用例之前,数据库架构将从头开始重建,那么每个试运行后清理。

希望这可以帮助。



Answer 4:

我已经在一个名为很整洁束跌跌撞撞主义试验捆绑不是创建和每次考试它只是回滚下降架构。 我的测试中,从1m40s去.. 2秒。 而且它隔离。 所有你需要的是一个明确的测试数据库,它会做的伎俩。



Answer 5:

我用这个命令:

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

但当然LiipFunctionalTestBundle看起来很有希望。



Answer 6:

我想加载所有的灯具,如doctrine:fixtures:load命令一样。 我不想运行exec从测试盒内,因为它似乎是一个混乱的方式做事情。 我看着条令司令部请问这是怎么本身,只是复制了相关线路。

我从Symfony的扩展WebTestCase和内核创建之后我就打电话给我的方法,它的作用完全象学说负载灯具命令。

    /**
     * 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);
    }


Answer 7:

就在最近捆绑hautelook / AliceBundle暴露两个特点,帮助您解决在功能测试负载灯具的使用情况: RefreshDatabaseTraitReloadDatabaseTrait

从文档:

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)
    }
}

而您们好!



文章来源: Best way to create a test database and load fixtures on Symfony 2 WebTestCase?