Best way to create a test database and load fixtures on Symfony 2 WebTestCase?

Solution 1:

If you want to use doctrine:fixtures:load, you can use the --append option to avoid the user confirmation. Since you are recreating the database every time, purging is unnecessary. I used to use doctrine fixtures alone for testing, but have since switched to using fixtures & LiipFunctionalTestBundle to avoid DRY. This bundle makes fixtures easier to manage.

EDIT: David Jacquel's answer is the correct one for loading Doctrine Fixtures:

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

Solution 2:

In order to bypass user confirmation you can use

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

Solution 3:

UPDATED ANSWER

You can create a base class for your test cases which makes fixture loading easy by leveraging some classes from the Doctrine Data Fixtures library. This class would look pretty much like this:

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

Then, in your test case, simply extend the above class and before your test add all the needed fixtures and execute them. This will automatically purge your database before loading fixtures. Example follows:

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

(I decided to "deprecate" this answer because it only explains how to clean up the database without telling how to load fixtures after).

There's an even cleaner way of accomplishing this without having to run commands. It basically consists in using a combination of the SchemaTool and the ORMPurger. You can create an abstract base class which performs this kind of operations to avoid repeating them for each specialized test case. Here's a code example of a test case class which sets up database for a generic test case:

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

This way, before running each test case which inherits from the above class, the database schema will be rebuilt from scratch, then cleaned up after every test run.

Hope this helps.

Solution 4:

I've stumbled upon a really neat bundle named Doctrine-Test-Bundle Instead of creating and dropping schema on every test it simply rollback. My Tests went from 1m40s to.. 2s. And it's isolated. All you need is a clear test database and it'll do the trick.