silverstripe-framework/docs/en/topics/testing/creating-a-functional-test.md
Sean Harvey 0ee3a683a5 Better support for overloading start and destroy methods in Session
Move functionality from static start and destroy functions into instance
methods, allowing these to be overloaded. This works the same way as
calling Session::set() which then in turn calls inst_set()

Additionally use Injector to create the default Session instance to
allow the class to be swapped out.
2014-06-20 10:35:53 +12:00

70 lines
3.0 KiB
Markdown

# Creating a functional tests
Functional tests test your controllers. The core of these are the same as unit tests:
* Create a subclass of `[api:SapphireTest]` in the `mysite/tests` or `(module)/tests` folder.
* Define static $fixture_file to point to a database YAML file.
* Create methods that start with "test" to create your tests.
* Assertions are used to work out if a test passed or failed.
The code of the tests is a little different. Instead of examining the behaviour of objects, we example the results of
URLs. Here is an example from the subsites module:
:::php
class SubsiteAdminTest extends SapphireTest {
private static $fixture_file = 'subsites/tests/SubsiteTest.yml';
/**
* Return a session that has a user logged in as an administrator
*/
public function adminLoggedInSession() {
return Injector::inst()->create('Session', array(
'loggedInAs' => $this->idFromFixture('Member', 'admin')
));
}
/**
* Test generation of the view
*/
public function testBasicView() {
// Open the admin area logged in as admin
$response1 = Director::test('admin/subsites/', null, $this->adminLoggedInSession());
// Confirm that this URL gets you the entire page, with the edit form loaded
$response2 = Director::test('admin/subsites/show/1', null, $this->adminLoggedInSession());
$this->assertTrue(strpos($response2->getBody(), 'id="Root_Configuration"') !== false);
$this->assertTrue(strpos($response2->getBody(), '<head') !== false);
// Confirm that this URL gets you just the form content, with the edit form loaded
$response3 = Director::test('admin/subsites/show/1', array('ajax' => 1), $this->adminLoggedInSession());
$this->assertTrue(strpos($response3->getBody(), 'id="Root_Configuration"') !== false);
$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)**
Director::test() lets us execute a URL and see what happens. It bypasses HTTP, instead relying on the cleanly
encapsulated execution model of `[api:Controller]`.
It takes 3 arguments:
* $url: The URL to execute
* $postVars: Post variables to pass to the URL
* $sessionObj: A Session object representing the current session.
And it returns an `[api:HTTPResponse]` object, which will give you the response headers (including redirection), status code,
and body.
We can use string processing on the body of the response to then see if it fits with our expectations.
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
[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.