Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
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

10,000 views

Published on

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

Published in: Technology
  • Be the first to comment

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>

×