Getting to Grips with SilverStripe Testing Mark Rickerby May, 2008
Continuous Integration <ul><li>Project code stored in a central SVN repository </li></ul><ul><li>Repository synchronized w...
Sapphire Tools <ul><li>DevelopmentAdmin  and  TestRunner  linked into all projects by default </li></ul><ul><li>Execute vi...
Creating New Tests <ul><li>Each  SilverStripe  module has a test folder </li></ul><ul><ul><ul><li>/htdocs/project/tests </...
Running Tests <ul><li>Run a single test </li></ul><ul><ul><ul><li>http://project/dev/tests/only/MyTest </li></ul></ul></ul...
Writing Unit Tests <ul><li>Extend  SapphireTest  for unit tests </li></ul><ul><ul><ul><li>class MyTest extends SapphireTes...
Writing Unit Tests <ul><li>All methods prefixed with  test  are run as tests </li></ul><ul><ul><ul><li>class MyTest extend...
Assertions <ul><li>Assert methods generate a pass/fail statement </li></ul><ul><ul><ul><li>assertTrue($value) </li></ul></...
Testing Objects <ul><li>Testing a single subsystem (unit test) </li></ul><ul><ul><ul><li>$params = array('Amount' => 9.95,...
Testing Boundaries <ul><li>Testing an integration boundar y (smoke test) </li></ul><ul><ul><ul><li>$params = array('Amount...
Functional Tests <ul><li>Use  FunctionalTest  to browse web controllers </li></ul><ul><ul><ul><li>class PageTest extends F...
Functional Tests <ul><li>Navigate a website via URL requests </li></ul><ul><ul><ul><li>get($path) </li></ul></ul></ul><ul>...
When? <ul><li>Test Driven Development </li></ul><ul><li>–  test first, then code </li></ul><ul><li>Behavior Driven Develop...
Where? What? <ul><li>Individual object behavior </li></ul><ul><ul><li>–  validate pre- and post-conditions </li></ul></ul>...
Rules of Thumb <ul><li>Be aware of breaking existing behavior </li></ul><ul><ul><li>–  run full suite of tests at every co...
Questions? <ul><li>http://doc.silverstripe.com  - see  Testing Guide </li></ul><ul><li>http://www.phpunit.de </li></ul><ul...
Upcoming SlideShare
Loading in...5
×

Getting to Grips with SilverStripe Testing

8,453

Published on

An introduction to automated testing in SilverStripe and the Sapphire framework.

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
8,453
On Slideshare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
0
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Getting to Grips with SilverStripe Testing

  1. 1. Getting to Grips with SilverStripe Testing Mark Rickerby May, 2008
  2. 2. Continuous Integration <ul><li>Project code stored in a central SVN repository </li></ul><ul><li>Repository synchronized with a build server </li></ul><ul><ul><ul><li>Code builds on the server on every commit </li></ul></ul></ul><ul><ul><ul><li>All project tests are run at every build </li></ul></ul></ul><ul><ul><ul><li>Immediate notification of integration failures </li></ul></ul></ul><ul><li>Project code is always live, always tested </li></ul><ul><ul><ul><ul><ul><ul><ul><ul><ul><li>Go buildbot ! </li></ul></ul></ul></ul></ul></ul></ul></ul></ul>
  3. 3. Sapphire Tools <ul><li>DevelopmentAdmin and TestRunner linked into all projects by default </li></ul><ul><li>Execute via command line or web browser </li></ul><ul><li>CLI using sake (Sapphire Make) </li></ul><ul><ul><ul><li>/path/to/project$> sake test </li></ul></ul></ul><ul><li>Browse and run all the tests in the build path </li></ul><ul><ul><ul><li>http://project/dev/ </li></ul></ul></ul><ul><ul><ul><li>http://project/dev/tests </li></ul></ul></ul>
  4. 4. Creating New Tests <ul><li>Each SilverStripe module has a test folder </li></ul><ul><ul><ul><li>/htdocs/project/tests </li></ul></ul></ul><ul><ul><ul><li>/htdocs/module/tests </li></ul></ul></ul><ul><ul><ul><li>/htdocs/sapphire/tests </li></ul></ul></ul><ul><li>Test cases use standard PHP files </li></ul><ul><ul><ul><li>/sapphire/tests/DataObjectTest.php </li></ul></ul></ul><ul><li>DataObject fixtures use YAML files </li></ul><ul><ul><ul><li>/sapphire/tests/DataObjectTest.yml </li></ul></ul></ul>
  5. 5. Running Tests <ul><li>Run a single test </li></ul><ul><ul><ul><li>http://project/dev/tests/only/MyTest </li></ul></ul></ul><ul><li>Run all module tests </li></ul><ul><ul><ul><li>http://project/dev/tests/module/sapphire </li></ul></ul></ul><ul><li>Run all tests in the project path </li></ul><ul><ul><ul><li>http://project/dev/tests/all </li></ul></ul></ul><ul><ul><li>Green if Pass or Red if Fail </li></ul></ul>
  6. 6. Writing Unit Tests <ul><li>Extend SapphireTest for unit tests </li></ul><ul><ul><ul><li>class MyTest extends SapphireTest {} </li></ul></ul></ul><ul><li>Attach a DataObject fixture for the test </li></ul><ul><ul><ul><li>class MyTest extends SapphireTest { </li></ul></ul></ul><ul><ul><ul><li>static $fixture_file = 'MyTest.yml' </li></ul></ul></ul><ul><ul><ul><li>} </li></ul></ul></ul>
  7. 7. Writing Unit Tests <ul><li>All methods prefixed with test are run as tests </li></ul><ul><ul><ul><li>class MyTest extends SapphireTest </li></ul></ul></ul><ul><ul><ul><li>function testGetAndSet() { </li></ul></ul></ul><ul><ul><ul><li>$obj = new MyObj; </li></ul></ul></ul><ul><ul><ul><li>$obj->set('key', 'val'); </li></ul></ul></ul><ul><ul><ul><li>$this->assertEquals( </li></ul></ul></ul><ul><ul><ul><li>“ val”, </li></ul></ul></ul><ul><ul><ul><li>$obj->get('key') </li></ul></ul></ul><ul><ul><ul><li>); </li></ul></ul></ul><ul><ul><ul><li>}} </li></ul></ul></ul>
  8. 8. Assertions <ul><li>Assert methods generate a pass/fail statement </li></ul><ul><ul><ul><li>assertTrue($value) </li></ul></ul></ul><ul><ul><ul><li>assertFalse($value) </li></ul></ul></ul><ul><ul><ul><li>assertEquals($expected, $actual) </li></ul></ul></ul><ul><ul><ul><li>assertContains($needle, $haystack) </li></ul></ul></ul><ul><ul><ul><li>assertNotContains($needle, $haystack) </li></ul></ul></ul><ul><li>Type checking and object identity </li></ul><ul><ul><ul><li>assertType($expected, $actual) </li></ul></ul></ul><ul><ul><ul><li>assertSame($expected, $actual) </li></ul></ul></ul>
  9. 9. Testing Objects <ul><li>Testing a single subsystem (unit test) </li></ul><ul><ul><ul><li>$params = array('Amount' => 9.95, ... ); </li></ul></ul></ul><ul><ul><ul><li>$service = new PaymentProcessor(); </li></ul></ul></ul><ul><ul><ul><li>$service->connect(); </li></ul></ul></ul><ul><ul><ul><li>$rsp = $service->processPayment($params); </li></ul></ul></ul><ul><ul><ul><li>$this->assertTrue($rsp['success']); </li></ul></ul></ul><ul><ul><ul><li>$this->assertEquals(9.95, $rsp['amount']); </li></ul></ul></ul>
  10. 10. Testing Boundaries <ul><li>Testing an integration boundar y (smoke test) </li></ul><ul><ul><ul><li>$params = array('Amount' => 9.95, ... ); </li></ul></ul></ul><ul><ul><ul><li>$payment = Payment::processPayment($params); </li></ul></ul></ul><ul><ul><ul><li>$this->assertTrue($payment->isSuccess()); </li></ul></ul></ul><ul><ul><ul><li>$this->assertEquals(9.95, $payment->Amount); </li></ul></ul></ul><ul><li>Here, PaymentProcess is wrapped by Payment </li></ul><ul><ul><ul><ul><li>“ Where there's smoke, there's fire” </li></ul></ul></ul></ul>
  11. 11. Functional Tests <ul><li>Use FunctionalTest to browse web controllers </li></ul><ul><ul><ul><li>class PageTest extends FunctionalTest {} </li></ul></ul></ul><ul><li>Execute a fake web browser in memory </li></ul><ul><ul><ul><li>$this->get('pages/name-of-page'); </li></ul></ul></ul><ul><ul><ul><li>$this->assertExactMatchBySelector( </li></ul></ul></ul><ul><ul><ul><li>'#page h1', </li></ul></ul></ul><ul><ul><ul><li>'Name of Page' </li></ul></ul></ul><ul><ul><ul><li>); </li></ul></ul></ul>
  12. 12. Functional Tests <ul><li>Navigate a website via URL requests </li></ul><ul><ul><ul><li>get($path) </li></ul></ul></ul><ul><ul><ul><li>post($path, $data) </li></ul></ul></ul><ul><ul><ul><li>submitForm($formID, $data, $button) </li></ul></ul></ul><ul><li>Match HTML content against CSS selectors </li></ul><ul><ul><ul><li>assertExactMatchBySelector($css, $txt) </li></ul></ul></ul><ul><ul><ul><li>assertExactHTMLMatchBySelector($css, $htm) </li></ul></ul></ul><ul><ul><ul><li>assertPartialMatchBySelector($css, $txt) </li></ul></ul></ul><ul><ul><ul><li>assertPartialHTMLMatchBySelector($css, $htm) </li></ul></ul></ul>
  13. 13. When? <ul><li>Test Driven Development </li></ul><ul><li>– test first, then code </li></ul><ul><li>Behavior Driven Development </li></ul><ul><li>– write to specification of what the API should do </li></ul><ul><li>Characterisation Testing </li></ul><ul><li>– write tests to discover the behavior of a system or bring functionality under control </li></ul>
  14. 14. Where? What? <ul><li>Individual object behavior </li></ul><ul><ul><li>– validate pre- and post-conditions </li></ul></ul><ul><ul><li>- discover API as the code evolves </li></ul></ul><ul><li>System boundaries and flex points </li></ul><ul><ul><li>– confirmation that subsystems work together </li></ul></ul><ul><li>Web application control flow </li></ul><ul><ul><li>– validate HTTP and HTML responses </li></ul></ul><ul><ul><li>– form submission and session interactions </li></ul></ul>
  15. 15. Rules of Thumb <ul><li>Be aware of breaking existing behavior </li></ul><ul><ul><li>– run full suite of tests at every commit </li></ul></ul><ul><ul><li>– update all test code when the API changes </li></ul></ul><ul><li>Not everything is permanent </li></ul><ul><ul><li>– if a test is no longer relevant, delete it from the repository </li></ul></ul>
  16. 16. Questions? <ul><li>http://doc.silverstripe.com - see Testing Guide </li></ul><ul><li>http://www.phpunit.de </li></ul><ul><li>http://simpletest.org </li></ul><ul><li>http://maetl.coretxt.net.nz/testing </li></ul><ul><ul><ul><ul><ul><ul><ul><ul><ul><li>Happy coding! </li></ul></ul></ul></ul></ul></ul></ul></ul></ul>

×