mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge pull request #5906 from robingram/fixture-doc-update
Change order of fixtures in example
This commit is contained in:
commit
0ab33b205d
@ -3,20 +3,20 @@ summary: Populate test databases with fake seed data.
|
||||
|
||||
# Fixtures
|
||||
|
||||
To test functionality correctly, we must use consistent data. If we are testing our code with the same data each
|
||||
time, we can trust our tests to yield reliable results and to identify when the logic changes. Each test run in
|
||||
To test functionality correctly, we must use consistent data. If we are testing our code with the same data each
|
||||
time, we can trust our tests to yield reliable results and to identify when the logic changes. Each test run in
|
||||
SilverStripe starts with a fresh database containing no records. `Fixtures` provide a way to describe the initial data
|
||||
to load into the database. The [api:SapphireTest] class takes care of populating a test database with data from
|
||||
to load into the database. The [api:SapphireTest] class takes care of populating a test database with data from
|
||||
fixtures - all we have to do is define them.
|
||||
|
||||
Fixtures are defined in `YAML`. `YAML` is a markup language which is deliberately simple and easy to read, so it is
|
||||
Fixtures are defined in `YAML`. `YAML` is a markup language which is deliberately simple and easy to read, so it is
|
||||
ideal for fixture generation. Say we have the following two DataObjects:
|
||||
|
||||
:::php
|
||||
<?php
|
||||
|
||||
class Player extends DataObject {
|
||||
|
||||
|
||||
private static $db = array (
|
||||
'Name' => 'Varchar(255)'
|
||||
);
|
||||
@ -43,6 +43,13 @@ We can represent multiple instances of them in `YAML` as follows:
|
||||
**mysite/tests/fixtures.yml**
|
||||
|
||||
:::yml
|
||||
Team:
|
||||
hurricanes:
|
||||
Name: The Hurricanes
|
||||
Origin: Wellington
|
||||
crusaders:
|
||||
Name: The Crusaders
|
||||
Origin: Canterbury
|
||||
Player:
|
||||
john:
|
||||
Name: John
|
||||
@ -53,18 +60,11 @@ We can represent multiple instances of them in `YAML` as follows:
|
||||
jack:
|
||||
Name: Jack
|
||||
Team: =>Team.crusaders
|
||||
Team:
|
||||
hurricanes:
|
||||
Name: The Hurricanes
|
||||
Origin: Wellington
|
||||
crusaders:
|
||||
Name: The Crusaders
|
||||
Origin: Canterbury
|
||||
|
||||
This `YAML` is broken up into three levels, signified by the indentation of each line. In the first level of
|
||||
This `YAML` is broken up into three levels, signified by the indentation of each line. In the first level of
|
||||
indentation, `Player` and `Team`, represent the class names of the objects we want to be created.
|
||||
|
||||
The second level, `john`/`joe`/`jack` & `hurricanes`/`crusaders`, are **identifiers**. Each identifier you specify
|
||||
The second level, `john`/`joe`/`jack` & `hurricanes`/`crusaders`, are **identifiers**. Each identifier you specify
|
||||
represents a new object and can be referenced in the PHP using `objFromFixture`
|
||||
|
||||
:::php
|
||||
@ -72,10 +72,10 @@ represents a new object and can be referenced in the PHP using `objFromFixture`
|
||||
|
||||
The third and final level represents each individual object's fields.
|
||||
|
||||
A field can either be provided with raw data (such as the names for our Players), or we can define a relationship, as
|
||||
A field can either be provided with raw data (such as the names for our Players), or we can define a relationship, as
|
||||
seen by the fields prefixed with `=>`.
|
||||
|
||||
Each one of our Players has a relationship to a Team, this is shown with the `Team` field for each `Player` being set
|
||||
Each one of our Players has a relationship to a Team, this is shown with the `Team` field for each `Player` being set
|
||||
to `=>Team.` followed by a team name.
|
||||
|
||||
<div class="info" markdown="1">
|
||||
@ -84,10 +84,14 @@ sets the `has_one` relationship for John with with the `Team` object `hurricanes
|
||||
</div>
|
||||
|
||||
<div class="hint" markdown='1'>
|
||||
Note that we use the name of the relationship (Team), and not the name of the
|
||||
Note that we use the name of the relationship (Team), and not the name of the
|
||||
database field (TeamID).
|
||||
</div>
|
||||
|
||||
<div class="hint" markdown='1'>
|
||||
Also be aware the target of a relationship must be defined before it is referenced, for example the `hurricanes` team must appear in the fixture file before the line `Team: =>Team.hurricanes`.
|
||||
</div>
|
||||
|
||||
This style of relationship declaration can be used for any type of relationship (i.e `has_one`, `has_many`, `many_many`).
|
||||
|
||||
We can also declare the relationships conversely. Another way we could write the previous example is:
|
||||
@ -110,8 +114,8 @@ We can also declare the relationships conversely. Another way we could write the
|
||||
Origin: Canterbury
|
||||
Players: =>Player.joe,=>Player.jack
|
||||
|
||||
The database is populated by instantiating `DataObject` objects and setting the fields declared in the `YAML`, then
|
||||
calling `write()` on those objects. Take for instance the `hurricances` record in the `YAML`. It is equivalent to
|
||||
The database is populated by instantiating `DataObject` objects and setting the fields declared in the `YAML`, then
|
||||
calling `write()` on those objects. Take for instance the `hurricances` record in the `YAML`. It is equivalent to
|
||||
writing:
|
||||
|
||||
:::php
|
||||
@ -125,18 +129,18 @@ writing:
|
||||
$team->Players()->add($john);
|
||||
|
||||
<div class="notice" markdown="1">
|
||||
As the YAML fixtures will call `write`, any `onBeforeWrite()` or default value logic will be executed as part of the
|
||||
As the YAML fixtures will call `write`, any `onBeforeWrite()` or default value logic will be executed as part of the
|
||||
test.
|
||||
</div>
|
||||
|
||||
### Defining many_many_extraFields
|
||||
|
||||
`many_many` relations can have additional database fields attached to the relationship. For example we may want to
|
||||
`many_many` relations can have additional database fields attached to the relationship. For example we may want to
|
||||
declare the role each player has in the team.
|
||||
|
||||
:::php
|
||||
class Player extends DataObject {
|
||||
|
||||
|
||||
private static $db = array (
|
||||
'Name' => 'Varchar(255)'
|
||||
);
|
||||
@ -160,7 +164,7 @@ declare the role each player has in the team.
|
||||
"Players" => array(
|
||||
"Role" => "Varchar"
|
||||
)
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
To provide the value for the `many_many_extraField` use the YAML list syntax.
|
||||
@ -176,13 +180,13 @@ To provide the value for the `many_many_extraField` use the YAML list syntax.
|
||||
Team:
|
||||
hurricanes:
|
||||
Name: The Hurricanes
|
||||
Players:
|
||||
Players:
|
||||
- =>Player.john:
|
||||
Role: Captain
|
||||
|
||||
crusaders:
|
||||
Name: The Crusaders
|
||||
Players:
|
||||
Players:
|
||||
- =>Player.joe:
|
||||
Role: Captain
|
||||
- =>Player.jack:
|
||||
@ -190,20 +194,20 @@ To provide the value for the `many_many_extraField` use the YAML list syntax.
|
||||
|
||||
## Fixture Factories
|
||||
|
||||
While manually defined fixtures provide full flexibility, they offer very little in terms of structure and convention.
|
||||
While manually defined fixtures provide full flexibility, they offer very little in terms of structure and convention.
|
||||
|
||||
Alternatively, you can use the [api:FixtureFactory] class, which allows you to set default values, callbacks on object
|
||||
Alternatively, you can use the [api:FixtureFactory] class, which allows you to set default values, callbacks on object
|
||||
creation, and dynamic/lazy value setting.
|
||||
|
||||
<div class="hint" markdown='1'>
|
||||
SapphireTest uses FixtureFactory under the hood when it is provided with YAML based fixtures.
|
||||
</div>
|
||||
|
||||
The idea is that rather than instantiating objects directly, we'll have a factory class for them. This factory can have
|
||||
*blueprints* defined on it, which tells the factory how to instantiate an object of a specific type. Blueprints need a
|
||||
The idea is that rather than instantiating objects directly, we'll have a factory class for them. This factory can have
|
||||
*blueprints* defined on it, which tells the factory how to instantiate an object of a specific type. Blueprints need a
|
||||
name, which is usually set to the class it creates such as `Member` or `Page`.
|
||||
|
||||
Blueprints are auto-created for all available DataObject subclasses, you only need to instantiate a factory to start
|
||||
Blueprints are auto-created for all available DataObject subclasses, you only need to instantiate a factory to start
|
||||
using them.
|
||||
|
||||
:::php
|
||||
@ -219,7 +223,7 @@ In order to create an object with certain properties, just add a third argument:
|
||||
));
|
||||
|
||||
<div class="warning" markdown="1">
|
||||
It is important to remember that fixtures are referenced by arbitrary identifiers ('hurricanes'). These are internally
|
||||
It is important to remember that fixtures are referenced by arbitrary identifiers ('hurricanes'). These are internally
|
||||
mapped to their database identifiers.
|
||||
</div>
|
||||
|
||||
@ -241,7 +245,7 @@ name, we can set the default to be `Unknown Team`.
|
||||
|
||||
### Dependent Properties
|
||||
|
||||
Values can be set on demand through anonymous functions, which can either generate random defaults, or create composite
|
||||
Values can be set on demand through anonymous functions, which can either generate random defaults, or create composite
|
||||
values based on other fixture data.
|
||||
|
||||
:::php
|
||||
@ -258,7 +262,7 @@ values based on other fixture data.
|
||||
|
||||
### Relations
|
||||
|
||||
Model relations can be expressed through the same notation as in the YAML fixture format described earlier, through the
|
||||
Model relations can be expressed through the same notation as in the YAML fixture format described earlier, through the
|
||||
`=>` prefix on data values.
|
||||
|
||||
:::php
|
||||
@ -268,7 +272,7 @@ Model relations can be expressed through the same notation as in the YAML fixtur
|
||||
|
||||
#### Callbacks
|
||||
|
||||
Sometimes new model instances need to be modified in ways which can't be expressed in their properties, for example to
|
||||
Sometimes new model instances need to be modified in ways which can't be expressed in their properties, for example to
|
||||
publish a page, which requires a method call.
|
||||
|
||||
:::php
|
||||
@ -287,8 +291,8 @@ Available callbacks:
|
||||
|
||||
### Multiple Blueprints
|
||||
|
||||
Data of the same type can have variations, for example forum members vs. CMS admins could both inherit from the `Member`
|
||||
class, but have completely different properties. This is where named blueprints come in. By default, blueprint names
|
||||
Data of the same type can have variations, for example forum members vs. CMS admins could both inherit from the `Member`
|
||||
class, but have completely different properties. This is where named blueprints come in. By default, blueprint names
|
||||
equal the class names they manage.
|
||||
|
||||
:::php
|
||||
|
Loading…
Reference in New Issue
Block a user