Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Behat and Symfony data fixtures

I'm wondering is it possible to use separate database for the Behat tests? is there any way to drop and truncate database and load data fixtures with it like you can do with PHPUnit?

like image 488
Einius Avatar asked Mar 05 '15 11:03

Einius


2 Answers

You can create a new environment (like test, dev and prod) and configure it in your preferred way.

As example for configure a behat env, do the following:

  1. create a new file in the web folder called web_behat.php
  2. define a config_behat.yml in the config folder
  3. customize your parameters in the parameters_behat.yml

Then

  1. Use this env in your behat test where you can load your fixtures etc

I don't know as you can setup your fixtures in a behat scenario, but only as example you can do something like this in a command line:

php app/console doctrine:fixture:load --env=behat

DETAILED STEP

  1. create a new file in the web folder called web_behat.php (copying it from web_dev.php and remove ip restrictions ) depends on your sf2 versions but:

web_behat.php

<?php

use Symfony\Component\ClassLoader\ApcClassLoader;
use Symfony\Component\HttpFoundation\Request;


$loader = require_once __DIR__.'/../app/bootstrap.php.cache';

// Use APC for autoloading to improve performance
// Change 'sf2' by the prefix you want in order to prevent key conflict with another application
/*
$loader = new ApcClassLoader('sf2', $loader);
$loader->register(true);
*/

require_once __DIR__.'/../app/AppKernel.php';

$kernel = new AppKernel('behat', false);
$kernel->loadClassCache();
//$kernel = new AppCache($kernel);
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);

Define a config_behat.yml under app/config folder where you recall your custom parameters with the desired configurations (database, email etc) something like this:

config_behat.yml

imports:
    - { resource: config.yml }
    - { resource: parameters_behat.yml }


monolog:
    handlers:
        main:
            type:         fingers_crossed
            action_level: error
            handler:      nested
        nested:
            type:  stream
            path:  %kernel.logs_dir%/%kernel.environment%.log
            level: debug

assetic:
    use_controller: true

framework: 
    test: ~

parameters:
    router.options.matcher.cache_class: ~ # disable router cache
    router.options.matcher_class: Symfony\Component\Routing\Matcher\ApacheUrlMatcher

parameters_behat.yml

parameters:
    database_driver:   pdo_mysql
    database_host:     localhost
    database_port:     ~
    database_name:     test_behat
    database_user:     root
    database_password:

Hope this help

like image 196
Matteo Avatar answered Sep 19 '22 15:09

Matteo


Set a custom environment in your behat, and inject container + entity manager into feature context (or just container and load it from there). Irrelevant settings not shown.

Behat.yml

default:
  suites:
    default:
      contexts:
      - FeatureContext:
          container: '@service_container'
          entityManager: "@doctrine.orm.default_entity_manager"
  extensions:
    Behat\Symfony2Extension:
      kernel:
        env: "test"

FeatureContext

Be sure to replace the fixtures path with yours (in $loader->loadFromDirectory).

<?php

use Doctrine\Common\DataFixtures\Executor\ORMExecutor;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Tools\SchemaTool;
use Symfony\Bridge\Doctrine\DataFixtures\ContainerAwareLoader;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Defines application features from the specific context.
 */
class FeatureContext extends MinkContext
{
    /**
     * @var ContainerInterface
     */
    private $container;

    /**
     * @var EntityManager
     */
    private $em;

    /**
     * FeatureContext constructor.
     * @param ContainerInterface $container
     * @param EntityManager $entityManager
     */
    public function __construct(ContainerInterface $container, EntityManager $entityManager)
    {
        $this->container = $container;
        $this->em = $entityManager;

        $this->setupDatabase();
        $this->loadFixtures();
    }

    protected function setupDatabase()
    {
        $metaData = $this->em->getMetadataFactory()->getAllMetadata();
        $schemaTool = new SchemaTool($this->em);
        $schemaTool->dropDatabase();
        if (!empty($metaData)) {
            $schemaTool->createSchema($metaData);
        }
    }

    protected function loadFixtures()
    {
        $loader = new ContainerAwareLoader($this->container);
        $loader->loadFromDirectory(__DIR__ . '/../../src/AppBundle/DataFixtures');
        $executor = new ORMExecutor($this->em);
        $executor->execute($loader->getFixtures(), true);
    }
}
like image 20
Bouke Versteegh Avatar answered Sep 19 '22 15:09

Bouke Versteegh