diff --git a/docs/en/topics/testing/creating-a-functional-test.md b/docs/en/topics/testing/creating-a-functional-test.md index 239c73893..763c4ca4d 100644 --- a/docs/en/topics/testing/creating-a-functional-test.md +++ b/docs/en/topics/testing/creating-a-functional-test.md @@ -42,7 +42,7 @@ URLs. Here is an example from the subsites module: $this->assertTrue(strpos($response3->getBody(), 'assertTrue(strpos($response3->getBody(), ' '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 + } + } diff --git a/docs/en/topics/testing/index.md b/docs/en/topics/testing/index.md index 4181d28bf..6cadac8a7 100644 --- a/docs/en/topics/testing/index.md +++ b/docs/en/topics/testing/index.md @@ -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 \ No newline at end of file + http://localhost/dev/tests diff --git a/docs/en/topics/testing/testing-email.md b/docs/en/topics/testing/testing-email.md index d41417524..9097aa7f5 100644 --- a/docs/en/topics/testing/testing-email.md +++ b/docs/en/topics/testing/testing-email.md @@ -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: