silverstripe/sapphire — pull request #1005 by chillu (2012-12-07 21:33:04+00:00)
Title: NEW FixtureFactory/FixtureBlueprint separated out from YamlFixture

Enables more generic use of the fixture facilities
without dependency on the YAML format, for example
when creating fixtures from Behat step definitions.
We have at least three different ways to create Behat fixtures
(requireDefaultRecords(), cucumber tables, inline "given there's a record" style).

One motivation was to keep DRY in Behat ([existing fixture handling](https://github.com/silverstripe-labs/silverstripe-behat-extension/blob/master/src/SilverStripe/BehatExtension/Context/SilverStripeContext.php#L205)).
But more importantly, I want to specify custom behaviour per-class on fixtures,
for example that pages should be published by default.
I could write slightly more specific Behat steps for each of those variations,
but that'll quickly turn unmaintainable.

Pull request is against 3.0 because that's what we're testing on in the short term.
I don't see any API changes, the `YamlFixture` class still behaves as usual,
just had most of implementation moved to new classes.
Only change: The YamlFixture class needs to be created via
Injector::inst()->create('YamlFixture') now, direct instantiation is no longer supported.
If that's a problem, I'll create a setFactory() with default DI setting.

The whole blueprint idea borrows from [factory_girl](https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md),
a popular fixture generator for Rails. There's a couple of PHP ports as well,
but they typically need to be told about the database structure for relation mapping etc,
so given our specific use case we can be less verbose in our definition requirements
by writing our own code. By the way, Michal from GSOC pointed me to factory_girl
before GSOC even started, but we decided that its a distraction for the original project
(which I still think was the right call).

One architectural weakness is that we need to pass the $fixture array
into various blueprint methods, because it needs to be centrally managed by the factory
for all fixture types (rather than just one type per blueprint).
We need all fixtures in the blueprint in order to set relations.
Does anybody have an idea on how to resolve this?

We'll rely on these features for the behat extension rework, and by proxy on our current newsletter testing. I expect that more flexible fixture generation will be a welcome addition to pretty much
any of our teams working with Behat, so ideally this PR gets reviewed quickly :)