MINOR Improved testing docs

This commit is contained in:
Ingo Schommer 2012-06-02 12:56:10 +02:00
parent 460148c12a
commit 9898cd9a95
3 changed files with 57 additions and 35 deletions

View File

@ -5,20 +5,12 @@ provides us the basics of creating unit tests.
:::php
<?php
/**
* Tests for SiteTree
*/
class SiteTreeTest extends SapphireTest {
/**
* Define the fixture file to use for this test class
*/
// Define the fixture file to use for this test class
static $fixture_file = 'SiteTreeTest.yml';
/**
/**
* Test generation of the URLSegment values.
* - Turns things into lowercase-hyphen-format
* - Generates from Title by default, unless URLSegment is explicitly set
@ -49,32 +41,26 @@ There are a number of points to note in this code fragment:
* Your test is a **subclass of SapphireTest**. Both unit tests and functional tests are a subclass of `[api:SapphireTest]`.
* **static $fixture_file** is defined. The testing framework will automatically set up a new database for **each** of
your tests. The initial database content will be sourced from the YML file that you list in $fixture_file. You must
define this value. Note also that, for the time being, you can only point to one YML file for each test class.
your tests. The initial database content will be sourced from the YML file that you list in $fixture_file. The property can take an array of fixture paths.
* Each **method that starts with the word "test"** will be executed by the TestRunner. Define as many as you like; the
database will be rebuilt for each of these.
* **$this->objFromFixture($className, $identifier)** can be used to select one of the objects named in your fixture
file. To identify to the object, we provide a class name and an identifier. The identifier is specified in the YML
file but not saved in the database anywhere. objFromFixture() looks the `[api:DataObject]` up in memory rather than using the
database. This means that you can use it to test the functions responsible for looking up content in the database.
* **$this->assertEquals()** is one of the many assert... functions that PHPUnit provides us. See below for more
information.
## Assertion commands
**$this->assertEquals()** is an example of an assertion function. These functions form the basis of our tests - a test
**$this->assertEquals()** is an example of an assertion function.
These functions form the basis of our tests - a test
fails if and only if one or more of the assertions fail.
There are many assertions available:
* See [the PHPUnit manual chapter 22](http://www.phpunit.de/manual/current/en/api.html#api.assert)
See [the PHPUnit manual](http://www.phpunit.de/manual/current/en/api.html#api.assert)
for a listing of all PHPUnit's built-in assertions.
* **$this->assertEmailSent($to, $from, $subject, $content)**: When an email is "sent" during a test run, it's not
actually sent. Instead, it is logged in an internal register. You can use assertEmailSent() to verify that an email
was sent. Each of the arguments can be a string, for an exact match, or, a preg_match() compatible regular expression,
if it starts with "/".
The `[api:SapphireTest]` class comes with additional assertions which are more
specific to the framework, e.g. `[assertEmailSent](api:SapphireTest->assertEmailSent())`
which can simulate sending emails through the `Email->send()` API without actually
using a mail server (see the [testing emails](email-sending)) guide.
## The Database YAML file

View File

@ -8,8 +8,6 @@ The SilverStripe core contains various features designed to simplify the process
* [Troubleshooting](testing-guide-troubleshooting): Frequently asked questions list for testing issues
* [Why Unit Test?](why-test): Why should you test and how to start testing
## Introduction
If you are familiar with PHP coding but new to unit testing, you should read the [Introduction](/topics/testing) and
check out Mark's presentation [Getting to Grips with SilverStripe Testing](http://www.slideshare.net/maetl/getting-to-grips-with-silverstripe-testing).
@ -99,7 +97,6 @@ Some people may note that we have used the same naming convention as Ruby on Rai
Tutorials and recipes for creating tests using the SilverStripe framework:
* **[Create a SilverStripe Test](/topics/testing/create-silverstripe-test)**
* **Load Test Fixtures**
* **[Create a Functional Test](/topics/testing/create-functional-test)**
* **[Test Outgoing Email Sending](/topics/testing/email-sending)**
@ -145,9 +142,4 @@ understand the problem space and discover suitable APIs for performing specific
**Behavior Driven Development (BDD):** An extension of the test-driven programming style, where tests are used primarily
for describing the specification of how code should perform. In practice, there's little or no technical difference - it
all comes down to language. In BDD, the usual terminology is changed to reflect this change of focus, so *Specification*
is used in place of *Test Case*, and *should* is used in place of *expect* and *assert*.
## Feedback
If you have a topic you would like covered in these section please ask for it on our [Bug Tracker](http://open.silverstripe.org)
is used in place of *Test Case*, and *should* is used in place of *expect* and *assert*.

View File

@ -15,3 +15,47 @@ It can be fixed by running the following commands:
pear install -f phpunit/DbUnit
pear install -f phpunit/PHPUnit_MockObject
pear install -f phpunit/PHPUnit_Selenium
## My tests fail seemingly random when comparing database IDs
When defining fixtures in the YML format, you only assign aliases
for them, not direct database IDs. Even if you insert only one record
on a clean database, it is not guaranteed to produce ID=1 on every run.
So to make your tests more robust, use the aliases rather than hardcoded IDs.
Also, some databases don't return records in a consistent sort order
unless you explicitly tell them to. If you don't want to test sort order
but rather just the returned collection,
:::php
$myPage = $this->objFromFixture('Page', 'mypage');
$myOtherPage = $this->objFromFixture('Page', 'myotherpage');
$pages = DataObject::get('Page');
// Bad: Assumptions about IDs and their order
$this->assertEquals(array(1,2), $pages->column('ID'));
// Good: Uses actually created IDs, independent of their order
$this->assertContains($myPage->ID, $pages->column('ID'));
$this->assertContains($myOtherPage->ID, $pages->column('ID'));
## My fixtures are getting complicated, how do I inspect their database state?
Fixtures are great because they're easy to define through YML,
but sometimes can be a bit of a blackbox when it comes to the actual
database state they create. These are temporary databases, which are
destructed directly after the test run - which is intentional,
but not very helpful if you want to verify that your fixtures have been created correctly.
SilverStripe comes with a URL action called `dev/tests/startsession`.
When called through a web browser, it prompts for a fixture file
which it creates a new database for, and sets it as the current database
in this browser session until you call `dev/tests/endsession`.
For more advanced users, you can also have a look in the `[api:YamlFixture]`
class to see what's going on behind the scenes.
## My database server is cluttered with `tmpdb...` databases
This is a common problem due to aborted test runs,
which don't clean up after themselves correctly
(mostly because of a fatal PHP error in the tests).
The easiest way to get rid of them is a call to `dev/tests/cleanupdb`.