Merge pull request #2454 from dangerdan/doc_corrections

Don't think the syntax highlighter likes my indentation with spaces.
This commit is contained in:
Ingo Schommer 2013-09-24 13:15:37 -07:00
commit 7da1340cbb
4 changed files with 163 additions and 163 deletions

View File

@ -42,7 +42,7 @@ URLs. Here is an example from the subsites module:
$this->assertTrue(strpos($response3->getBody(), '<form') === false);
$this->assertTrue(strpos($response3->getBody(), '<head') === false);
}
}
We are using a new static method here: **Director::test($url, $postVars, $sessionObj)**
@ -64,6 +64,6 @@ We can use string processing on the body of the response to then see if it fits
If you're testing for natural language responses like error messages, make sure to use [i18n](/topics/i18n) translations through
the *_t()* method to avoid tests failing when i18n is enabled.
Note that for a more highlevel testing approach, SilverStripe also supports
Note that for a more highlevel testing approach, SilverStripe also supports
[behaviour-driven testing through Behat](https://github.com/silverstripe-labs/silverstripe-behat-extension). It interacts
directly with your website or CMS interface by remote controlling an actual browser, driven by natural language assertions.

View File

@ -16,48 +16,48 @@ so it is ideal for fixture generation.
Say we have the following two DataObjects:
:::php
class Player extends DataObject {
static $db = array (
'Name' => 'Varchar(255)'
);
:::php
class Player extends DataObject {
static $db = array (
'Name' => 'Varchar(255)'
);
static $has_one = array(
'Team' => 'Team'
);
}
static $has_one = array(
'Team' => 'Team'
);
}
class Team extends DataObject {
static $db = array (
'Name' => 'Varchar(255)',
'Origin' => 'Varchar(255)'
);
class Team extends DataObject {
static $db = array (
'Name' => 'Varchar(255)',
'Origin' => 'Varchar(255)'
);
static $has_many = array(
'Players' => 'Player'
);
}
static $has_many = array(
'Players' => 'Player'
);
}
We can represent multiple instances of them in `YAML` as follows:
:::yml
Player:
john:
Name: John
Team: =>Team.hurricanes
joe:
Name: Joe
Team: =>Team.crusaders
jack:
Name: Jack
Team: =>Team.crusaders
Team:
hurricanes:
Name: The Hurricanes
Origin: Wellington
crusaders:
Name: The Crusaders
Origin: Bay of Plenty
:::yml
Player:
john:
Name: John
Team: =>Team.hurricanes
joe:
Name: Joe
Team: =>Team.crusaders
jack:
Name: Jack
Team: =>Team.crusaders
Team:
hurricanes:
Name: The Hurricanes
Origin: Wellington
crusaders:
Name: The Crusaders
Origin: Bay of Plenty
Our `YAML` is broken up into three levels, signified by the indentation of each line.
In the first level of indentation, `Player` and `Team`,
@ -86,23 +86,23 @@ This style of relationship declaration can be used for both a `has-one` and a `m
For `many-many` relationships, we specify a comma separated list of values.
For example we could just as easily write the above as:
:::yml
Player:
john:
Name: John
joe:
Name: Joe
jack:
Name: Jack
Team:
hurricanes:
Name: The Hurricanes
Origin: Wellington
Players: =>Player.john
crusaders:
Name: The Crusaders
Origin: Bay of Plenty
Players: =>Player.joe,=>Player.jack
:::yml
Player:
john:
Name: John
joe:
Name: Joe
jack:
Name: Jack
Team:
hurricanes:
Name: The Hurricanes
Origin: Wellington
Players: =>Player.john
crusaders:
Name: The Crusaders
Origin: Bay of Plenty
Players: =>Player.joe,=>Player.jack
A crucial thing to note is that **the YAML file specifies DataObjects, not database records**.
The database is populated by instantiating DataObject objects and setting the fields declared in the YML,
@ -123,18 +123,18 @@ One common example here is publishing pages (page fixtures aren't published by d
You can always resort to creating objects manually in the test setup phase.
Since the test database is cleared on every test method, you'll get a fresh set of test instances every time.
:::php
class SiteTreeTest extends SapphireTest {
function setUp() {
parent::setUp();
:::php
class SiteTreeTest extends SapphireTest {
function setUp() {
parent::setUp();
for($i=0; $i<100; $i++) {
$page = new Page(array('Title' => "Page $i"));
$page->write();
$page->publish('Stage', 'Live');
}
}
}
for($i=0; $i<100; $i++) {
$page = new Page(array('Title' => "Page $i"));
$page->write();
$page->publish('Stage', 'Live');
}
}
}
## Fixture Factories
@ -156,69 +156,69 @@ This factory can have so called "blueprints" defined on it, which tells the fact
Since blueprints are auto-created for all available DataObject subclasses,
you only need to instantiate a factory to start using it.
:::php
$factory = Injector::inst()->create('FixtureFactory');
$obj = $factory->createObject('MyClass', 'myobj1');
:::php
$factory = Injector::inst()->create('FixtureFactory');
$obj = $factory->createObject('MyClass', 'myobj1');
It is important to remember that fixtures are referenced by arbitrary
identifiers ('myobj1'). These are internally mapped to their database identifiers.
:::
$databaseId = $factory->getId('MyClass', 'myobj1');
:::php
$databaseId = $factory->getId('MyClass', 'myobj1');
In order to create an object with certain properties, just add a second argument:
:::php
$obj = $factory->createObject('MyClass', 'myobj1', array('MyProperty' => 'My Value'));
:::php
$obj = $factory->createObject('MyClass', 'myobj1', array('MyProperty' => 'My Value'));
#### Default Properties
Blueprints can be overwritten in order to customize their behaviour,
for example with default properties in case none are passed into `createObject()`.
:::php
$factory->define('MyObject', array(
'MyProperty' => 'My Default Value'
));
:::php
$factory->define('MyObject', array(
'MyProperty' => 'My Default Value'
));
#### Dependent Properties
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
$factory->define('Member', array(
'Email' => function($obj, $data, $fixtures) {
if(isset($data['FirstName']) {
$obj->Email = strtolower($data['FirstName']) . '@example.org';
}
},
'Score' => function($obj, $data, $fixtures) {
$obj->Score = rand(0,10);
}
));
:::php
$factory->define('Member', array(
'Email' => function($obj, $data, $fixtures) {
if(isset($data['FirstName']) {
$obj->Email = strtolower($data['FirstName']) . '@example.org';
}
},
'Score' => function($obj, $data, $fixtures) {
$obj->Score = rand(0,10);
}
));
#### Relations
Model relations can be expressed through the same notation as in the YAML fixture format
described earlier, through the `=>` prefix on data values.
:::php
$obj = $factory->createObject('MyObject', 'myobj1', array(
'MyHasManyRelation' => '=>MyOtherObject.obj1,=>MyOtherObject.obj2'
));
:::php
$obj = $factory->createObject('MyObject', 'myobj1', array(
'MyHasManyRelation' => '=>MyOtherObject.obj1,=>MyOtherObject.obj2'
));
#### Callbacks
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
$blueprint = Injector::inst()->create('FixtureBlueprint', 'Member');
$blueprint->addCallback('afterCreate', function($obj, $identifier, $data, $fixtures) {
$obj->publish('Stage', 'Live');
});
$page = $factory->define('Page', $blueprint);
:::php
$blueprint = Injector::inst()->create('FixtureBlueprint', 'Member');
$blueprint->addCallback('afterCreate', function($obj, $identifier, $data, $fixtures) {
$obj->publish('Stage', 'Live');
});
$page = $factory->define('Page', $blueprint);
Available callbacks:
@ -232,43 +232,43 @@ 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
$memberBlueprint = Injector::inst()->create('FixtureBlueprint', 'Member', 'Member');
$adminBlueprint = Injector::inst()->create('FixtureBlueprint', 'AdminMember', 'Member');
$adminBlueprint->addCallback('afterCreate', function($obj, $identifier, $data, $fixtures) {
if(isset($fixtures['Group']['admin'])) {
$adminGroup = Group::get()->byId($fixtures['Group']['admin']);
$obj->Groups()->add($adminGroup);
}
});
:::php
$memberBlueprint = Injector::inst()->create('FixtureBlueprint', 'Member', 'Member');
$adminBlueprint = Injector::inst()->create('FixtureBlueprint', 'AdminMember', 'Member');
$adminBlueprint->addCallback('afterCreate', function($obj, $identifier, $data, $fixtures) {
if(isset($fixtures['Group']['admin'])) {
$adminGroup = Group::get()->byId($fixtures['Group']['admin']);
$obj->Groups()->add($adminGroup);
}
});
$member = $factory->createObject('Member'); // not in admin group
$admin = $factory->createObject('AdminMember'); // in admin group
$member = $factory->createObject('Member'); // not in admin group
$admin = $factory->createObject('AdminMember'); // in admin group
### Full Test Example
:::php
class MyObjectTest extends SapphireTest {
:::php
class MyObjectTest extends SapphireTest {
protected $factory;
protected $factory;
function __construct() {
parent::__construct();
function __construct() {
parent::__construct();
$factory = Injector::inst()->create('FixtureFactory');
// Defines a "blueprint" for new objects
$factory->define('MyObject', array(
'MyProperty' => 'My Default Value'
));
$this->factory = $factory;
}
$factory = Injector::inst()->create('FixtureFactory');
// Defines a "blueprint" for new objects
$factory->define('MyObject', array(
'MyProperty' => 'My Default Value'
));
$this->factory = $factory;
}
function testSomething() {
$MyObjectObj = $this->factory->createObject(
'MyObject',
array('MyOtherProperty' => 'My Custom Value')
);
// $myPageObj->MyProperty = My Default Value
// $myPageObj->MyOtherProperty = My Custom Value
}
}
function testSomething() {
$MyObjectObj = $this->factory->createObject(
'MyObject',
array('MyOtherProperty' => 'My Custom Value')
);
// $myPageObj->MyProperty = My Default Value
// $myPageObj->MyOtherProperty = My Custom Value
}
}

View File

@ -23,21 +23,21 @@ Unit tests are not included in the normal SilverStripe downloads, you are expect
Once you've got the project up and running, check out the additional requirements to run unit tests:
composer update --dev
composer update --dev
This will install (among other things) the [PHPUnit](http://www.phpunit.de/) dependency, which is the framework we're
building our unit tests on. Composer installs it alongside the required PHP classes into the `vendor/bin/` directory.
You can either use it through its full path (`vendor/bin/phpunit`), or symlink it into the root directory of your website:
ln -s vendor/bin/phpunit phpunit
ln -s vendor/bin/phpunit phpunit
### Via PEAR
Alternatively, you can check out PHPUnit globally via the PEAR packanage manager
([instructions](https://github.com/sebastianbergmann/phpunit/)).
pear config-set auto_discover 1
pear install pear.phpunit.de/PHPUnit
pear config-set auto_discover 1
pear install pear.phpunit.de/PHPUnit
## Configuration
@ -90,20 +90,20 @@ Tutorials and recipes for creating tests using the SilverStripe framework:
The `phpunit` binary should be used from the root directory of your website.
# Runs all tests defined in phpunit.xml
phpunit
# Runs all tests defined in phpunit.xml
phpunit
# Run all tests of a specific module
phpunit framework/tests/
# Run all tests of a specific module
phpunit framework/tests/
# Run specific tests within a specific module
phpunit framework/tests/filesystem
# Run specific tests within a specific module
phpunit framework/tests/filesystem
# Run a specific test
phpunit framework/tests/filesystem/FolderTest.php
# Run a specific test
phpunit framework/tests/filesystem/FolderTest.php
# Run tests with optional `$_GET` parameters (you need an empty second argument)
phpunit framework/tests '' flush=all
# Run tests with optional `$_GET` parameters (you need an empty second argument)
phpunit framework/tests '' flush=all
All command-line arguments are documented on
[phpunit.de](http://www.phpunit.de/manual/current/en/textui.html).
@ -115,20 +115,20 @@ The [sake](/topics/commandline) executable that comes with SilverStripe can trig
While the custom test runner a handy tool, its also more limited than using `phpunit` directly,
particularly around formatting test output.
# Run all tests
sake dev/tests/all
# Run all tests
sake dev/tests/all
# Run all tests of a specific module (comma-separated)
sake dev/tests/module/framework,cms
# Run all tests of a specific module (comma-separated)
sake dev/tests/module/framework,cms
# Run specific tests (comma-separated)
sake dev/tests/FolderTest,OtherTest
# Run specific tests (comma-separated)
sake dev/tests/FolderTest,OtherTest
# Run tests with optional `$_GET` parameters
sake dev/tests/all flush=all
# Run tests with optional `$_GET` parameters
sake dev/tests/all flush=all
# Skip some tests
sake dev/tests/all SkipTests=MySkippedTest
# Skip some tests
sake dev/tests/all SkipTests=MySkippedTest
### Via Web Browser
@ -136,4 +136,4 @@ Executing tests from the command line is recommended, since it most closely refl
test runs in any automated testing environments. If for some reason you don't have
access to the command line, you can also run tests through the browser.
http://localhost/dev/tests
http://localhost/dev/tests

View File

@ -8,19 +8,19 @@ For this to work, you need to send emails using the `Email` class,
which is generally the way that we recommend you send emails in your SilverStripe application.
Here is a simple example of how you might do this:
:::php
$e = new Email();
$e->To = "someone@example.com";
$e->Subject = "Hi there";
$e->Body = "I just really wanted to email you and say hi.";
$e->send();
:::php
$e = new Email();
$e->To = "someone@example.com";
$e->Subject = "Hi there";
$e->Body = "I just really wanted to email you and say hi.";
$e->send();
Normally, the `send()` method would send an email using PHP's `mail()` function.
However, if you are running a `[api:SapphireTest]` test, then it holds off actually sending the email,
and instead lets you assert that an email was sent using this method.
:::php
$this->assertEmailSent("someone@example.com", null, "/th.*e$/");
:::php
$this->assertEmailSent("someone@example.com", null, "/th.*e$/");
The arguments are `$to`, `$from`, `$subject`, `$body`, and can take one of the three following types: