Simplify usage of fixtures into your code / tests / dev.
It's a symfony extension for nelmio/alice library.
Sample, load fixture a yml ( and it's dependencies ) :
$fixturesLoaderRegistry = $this->container->get('fixtures.loader.registry');
$fixturesLoader = $fixturesLoaderRegistry->getLoader('default');
$fixturesLoader->load(['@MyBundle/Resources/fixtures/myfixture']);
- symfony
- doctrine ( dbal, orm, fixtures-bundle)
- nelmio/alice
All your fixtures must be written with nelmio/alice format (yml format)
Add "lafourchette/fixtures-bundle"
to your composer file.
"require-dev": {
"lafourchette/fixtures-bundle": "dev-master"
}
And add FixturesBundle
to your AppKernel.php
file.
if ($this->getEnvironment() != 'prod') {
$bundles[] = new LaFourchette\FixturesBundle\FixturesBundle();
}
You have to configure each EntityManager
you use for loading corresponding fixtures.
Sample fixtures.yml
:
fixtures:
entityManagerName: #use same name than the entity manager in doctrine
groups:
# you can declare a named group of fixtures
groupName:
- @MyBundle/Resources/fixtures/myfixture
- @MyBundle/Resources/fixtures/myfixture2
dependencies:
# indicate fixture dependencies, for each fixture
@MyBundle/Resources/fixtures/fixture1
- @MyBundle/Resources/fixtures/fixtureRequiredByFixture1
providerClasses:
# You can indicate wich providers you want to use with the loader
- MyBundle\Fixture\DefaultValuesProvider
fixturesDataProcessor: la_fourchette.fixtures.data_processor
# data-processor must be a service declared in the app
Not required, but you can indicate for each loader in the config file, the provider to be used. See configuration format and nelmio/alice documentation section about providers : https://github.com/nelmio/alice/blob/master/doc/customizing-data-generation.md#add-a-custom-faker-provider-class
You can use a data processor for your fixtures. It's See configuration format and documentation of data processor here : https://github.com/nelmio/alice/blob/master/doc/processors.md
To load fixtures, you have to get the corresponding "loader" of your entityManager.
$fixturesLoaderRegistry = $this->container->get('fixtures.loader.registry');
$fixturesLoaderDefault = $fixturesLoaderRegistry->getLoader('default'););
Loader by default purge automaticaly all entities of database ( by do a TRUNCATE ! ) You can avoid these by passing the second argument to load method :
public function load(array $fixtures, $purge = true) {}
$fixturesLoaderDefault->load(['@MyBundle/Resources/fixtures/fixture']);
For example, you file : fixture.yml required an other fixture file : fixtureRequired.yml. You can load fixtureRequired.yml and after fixture.yml obviously.
But loader system include a dependency system. You can declare a dependency in your config file like this :
dependencies:
# indicate fixture dependencies, for each fixture
@MyBundle/Resources/fixtures/fixture
- @MyBundle/Resources/fixtures/fixtureRequired
And now if you do :
$fixturesLoaderDefault->load(['@MyBundle/Resources/fixtures/fixture']);
Then the loader load fixtureRequired.yml and after fixture.yml.
In supplement of declarating fixtures dependencies, you can also define a naming group of fixtures in your config file.
groups:
# you can declare a named group of fixtures
groupName:
- @MyBundle/Resources/fixtures/myfixture
- @MyBundle/Resources/fixtures/myfixture2
And to use it in the code, simply do :
$fixturesLoaderDefault->load(['@Group:groupName']);
Note : the dependencies are still in function in groups, so if dependencies are declared for myfixture2 or myfixture, they will be loaded in the good order. And you can also required a group in a dependency.
In some case groups is not enough, and you want to load fixtures according to a variable. We call it a SET of fixtures.
A Set is simply a group of fixture created for working together, but with the same dependencies and same group than all your fixtures. A set is not declared in the configuration, you just have to organise your fixtures files into the same directory.
Example, defining two sets : mySet1 and mySet2
src/MyBundle/Resources/fixtures/mySet1/fixture.yml
src/MyBundle/Resources/fixtures/mySet1/fixture1.yml
src/MyBundle/Resources/fixtures/mySet1/fixtureRequiredBy1.yml
src/MyBundle/Resources/fixtures/mySet2/fixture.yml
src/MyBundle/Resources/fixtures/mySet2/fixture1.yml
src/MyBundle/Resources/fixtures/mySet2/fixtureRequiredBy1.yml
Now if you want to load src/MyBundle/Resources/fixtures/mySet1/fixture.yml, you can do :
$fixturesLoaderDefault->load(['@MyBundle/Resources/fixtures/{set}/fixture:mySet1']);
The syntax of fixture path (if using set) is : path : setName
The {set} is automatically replaced by the required set.
The power of set, is that these syntax works also in the config file so you can have :
dependencies:
# indicate fixture dependencies, for each fixture
@MyBundle/Resources/fixtures/{set}/fixture
- @MyBundle/Resources/fixtures/{set}/fixtureRequired
- @MyBundle/Resources/fixtures/common/fixtureCommonOfAllSet
And now, you have declared dependencies for all your set, and you can have common fixture for all set.
Note : not emplemented yet
You can use our command line tools to load fixtures.
app/console lafourchette:fixtures:load defaultEm @MyBundle/Resources/fixtures/{set}/fixture:default
Note : not emplemented yet
The bundle provide a behat context to use fixtures loader system.
Add it to your behat config file : behat.yml
default:
suites:
default:
contexts:
- LaFourchette\Behat\Context\FixturesContext:
- "@fixtures.loader.registry"
Now you have new sentence available and it's really easy to load required fixture for each scenario. (to avoid scenario dependencies ...)
Feature: My feature
Background:
Given I have data in "default" database with:
|@Group:login:default|
|@MyBundle/Resources/fixtures/{set}/fixture:default|
...
Scenario: I do something with my fixture
...
Scenario: I re-do something and all fixtures are re-initialized
...
Available sentences :
# Load fixture sentence
Given I have data in "default" database with:
"""
|@Group:login:default|
|@MyBundle/Resources/fixtures/{set}/fixture:default|
"""
...
# Purge sentence
Given I purge data in "default" database
...