Your SlideShare is downloading. ×
Test-Driven Development for TYPO3
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Test-Driven Development for TYPO3

1,755
views

Published on

Published in: Technology, Business

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,755
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
16
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Transcript

    • 1. Test-Driven Developmentfor TYPO3Oliver Klee, 2011-12-13 and 2011-12-14typo3-coding@oliverklee.de
    • 2. Unittests?
    • 3. Manual testing is cumbersome
    • 4. Automatedtesting isfast
    • 5. Unit tests for the Realty Manager extension
    • 6. more than1600 tests
    • 7. in less than 60 seconds
    • 8. Verify that your codedoes what you expect
    • 9. Make sure that yourchanges won‘t break anything
    • 10. Keep other codersfrom breaking your code
    • 11. Don‘t break anythingeven in complex projects
    • 12. Create asafety net for refactoring
    • 13. Green feels good!
    • 14. Green feels good!
    • 15. Know your tools
    • 16. The phpunit extension has it all
    • 17. The phpunit extension has it allphpunit (TYPO3 extension)
    • 18. The phpunit extension has it allphpunit (TYPO3 extension) PHPUnit (PEAR package)
    • 19. The phpunit extension has it allphpunit (TYPO3 extension) PHPUnit (PEAR package) Testrunner (back-end- module)
    • 20. The phpunit extension has it allphpunit (TYPO3 extension) PHPUnit (PEAR package) Testrunner Testrunner (back-end- module) (CLI module)
    • 21. The phpunit extension has it allphpunit (TYPO3 extension) PHPUnit (PEAR package) Testing framework for FE & DB Testrunner Testrunner (back-end- module) (CLI module)
    • 22. Let‘s getsome terms straight
    • 23. Two testsmeet in a bar ...
    • 24. Two testsTest meet in a bar ...
    • 25. Two tests Test meet in aAssertion bar ...
    • 26. Two tests Test meet in aAssertion bar ... Test Test
    • 27. Two tests Test meet in aAssertion bar ... Test TestTest case
    • 28. Two tests Test meet in aAssertion bar ... Test TestTest caseTest case
    • 29. Two tests Test meet in aAssertion bar ... Test TestTest caseTest caseTest suite
    • 30. Code test-first
    • 31. Code test-first
    • 32. Code test-firstwritetest
    • 33. Code test-firstwritetest
    • 34. Code test-firstwrite writetest code
    • 35. Code test-firstwrite writetest code
    • 36. Code test-firstwrite writetest code
    • 37. Code test-firstwrite writetest code refactor
    • 38. Code test-firstwrite writetest code refactor
    • 39. The life cycle unit test of a
    • 40. The life cycle unit test of a
    • 41. The life cycle unit test of a new FooTest();
    • 42. The life cycle unit test of a new FooTest();
    • 43. The life cycle unit test of a new FooTest(); setUp();
    • 44. The life cycle unit test of a new FooTest(); setUp(); /** @test */ lifeIsGood();
    • 45. The life cycle unit test of a new FooTest(); setUp(); /** @test */ lifeIsGood();
    • 46. The life cycle unit test of a new FooTest(); setUp(); /** @test */ lifeIsGood(); tearDown();
    • 47. The life cycle unit test of a new FooTest(); setUp(); /** @test */ lifeIsGood(); tearDown();
    • 48. The life cycle unit test of a new FooTest(); setUp(); /** @test */ lifeIsGood(); tearDown();
    • 49. Use meaningful unit test names
    • 50. Use meaningful unit test namesName thebehavior. classCanBeInstantiated
    • 51. Use meaningful unit test names Name the behavior. classCanBeInstantiatedMention the method. setTitleSetsTitle
    • 52. Use meaningful unit test names Name the behavior. classCanBeInstantiatedMention the method. setTitleSetsTitle Name the setSizeWithZeroThrowsExceptionpreconditions. hasTitleForEmptyTitleReturnsFalse
    • 53. Use meaningful unit test names Name the behavior. classCanBeInstantiatedMention the method. setTitleSetsTitle Name the setSizeWithZeroThrowsExceptionpreconditions. hasTitleForEmptyTitleReturnsFalse Dont‘t use "works" or "correctly".
    • 54. Use meaningful unit test names Name the behavior. classCanBeInstantiatedMention the method. setTitleSetsTitle Name the setSizeWithZeroThrowsExceptionpreconditions. hasTitleForEmptyTitleReturnsFalse Dont‘t use "works" or measureFrubbleWorksCorrectly "correctly".
    • 55. Use meaningful unit test names Name the behavior. classCanBeInstantiatedMention the method. setTitleSetsTitle Name the setSizeWithZeroThrowsExceptionpreconditions. hasTitleForEmptyTitleReturnsFalse Dont‘t use "works" or measureFrubbleWorksCorrectly "correctly".
    • 56. ContinuousIntegration
    • 57. ContinuousIntegration =
    • 58. ContinuousIntegration =checking inmore often
    • 59. The continuous integration server monitors the code Checkin Repository (SVN)
    • 60. The continuous integration server monitors the code Checkin hook Repository (SVN) SVN
    • 61. The continuous integration server monitors the code Checkin hook Repository (SVN) SVN continuous integration server
    • 62. The continuous integration server monitors the code Checkin hook Repository (SVN) SVN Hey, a change! continuous integration server
    • 63. The continuous integration server monitors the code Checkin hook Repository (SVN) SVN Hey, a change! continuous integration run the unit server tests etc.
    • 64. The continuous integration server monitors the code Checkin hook Repository (SVN) SVN Hey, a change! continuous integration run the unit Report server tests etc.
    • 65. There are small and huge tests
    • 66. Unit tests are small and fast
    • 67. Integration tests test the complete thing
    • 68. Automated click tests test the interface
    • 69. Automated click tests test the interface Selenium
    • 70. Blackbox tests test the public interface
    • 71. Whitebox tests test the inner workings
    • 72. The testing framework is created quickly /** * @var Tx_Phpunit_Framework */ protected $testingFramework = NULL; public function setUp() { $this->testingFramework = new Tx_Phpunit_Framework(tx_news2); } public function tearDown() { $this->testingFramework->cleanUp(); unset($this->testingFramework); }
    • 73. The testing framework is created quickly /** * @var Tx_Phpunit_Framework */ protected $testingFramework = NULL; public function setUp() { $this->testingFramework = new Tx_Phpunit_Framework(tx_news2); } discard the FE, public function tearDown() { delete DB records, $this->testingFramework->cleanUp(); unset($this->testingFramework); delete files }
    • 74. The testing framework is created quickly /** * @var Tx_Phpunit_Framework */ protected $testingFramework = NULL; public function setUp() { $this->testingFramework = new Tx_Phpunit_Framework(tx_news2); } discard the FE, public function tearDown() { delete DB records, $this->testingFramework->cleanUp(); unset($this->testingFramework); delete files }CREATE TABLE tx_news2_domain_model_news ( … is_dummy_record tinyint(1) unsigned DEFAULT 0 NOT NULL, …
    • 75. The testing framework can fake almost everything
    • 76. The testing framework can fake almost everything $recordUid = $tf->createRecord($tableName, array $recordData = array());
    • 77. The testing framework can fake almost everything $recordUid = $tf->createRecord($tableName, array $recordData = array()); $tf->changeRecord($tableName, $uid, array $recordData);
    • 78. The testing framework can fake almost everything $recordUid = $tf->createRecord($tableName, array $recordData = array()); $tf->changeRecord($tableName, $uid, array $recordData); $tf->deleteRecord($tableName, $uid);
    • 79. The testing framework can fake almost everything $recordUid = $tf->createRecord($tableName, array $recordData = array()); $tf->changeRecord($tableName, $uid, array $recordData); $tf->deleteRecord($tableName, $uid); $tf->createRelation($tableName, $uidLocal, $uidForeign, $sorting = 0);
    • 80. The testing framework can fake almost everything $recordUid = $tf->createRecord($tableName, array $recordData = array()); $tf->changeRecord($tableName, $uid, array $recordData); $tf->deleteRecord($tableName, $uid); $tf->createRelation($tableName, $uidLocal, $uidForeign, $sorting = 0);$tf->createRelationAndUpdateCounter($tableName, $uidLocal, $uidForeign, $columnName);
    • 81. The testing framework can fake almost everything $recordUid = $tf->createRecord($tableName, array $recordData = array()); $tf->changeRecord($tableName, $uid, array $recordData); $tf->deleteRecord($tableName, $uid); $tf->createRelation($tableName, $uidLocal, $uidForeign, $sorting = 0);$tf->createRelationAndUpdateCounter($tableName, $uidLocal, $uidForeign, $columnName); $tf->removeRelation($tableName, $uidLocal, $uidForeign);
    • 82. The testing framework can fake almost everything $recordUid = $tf->createRecord($tableName, array $recordData = array()); $tf->changeRecord($tableName, $uid, array $recordData); $tf->deleteRecord($tableName, $uid); $tf->createRelation($tableName, $uidLocal, $uidForeign, $sorting = 0);$tf->createRelationAndUpdateCounter($tableName, $uidLocal, $uidForeign, $columnName); $tf->removeRelation($tableName, $uidLocal, $uidForeign); $numberOfRecords = $tf->countRecords($tableName, $whereClause = );
    • 83. The testing framework can fake almost everything $recordUid = $tf->createRecord($tableName, array $recordData = array()); $tf->changeRecord($tableName, $uid, array $recordData); $tf->deleteRecord($tableName, $uid); $tf->createRelation($tableName, $uidLocal, $uidForeign, $sorting = 0);$tf->createRelationAndUpdateCounter($tableName, $uidLocal, $uidForeign, $columnName); $tf->removeRelation($tableName, $uidLocal, $uidForeign); $numberOfRecords = $tf->countRecords($tableName, $whereClause = ); $success = $tf->existsRecord($tableName, $whereClause = );
    • 84. The testing framework can fake almost everything $recordUid = $tf->createRecord($tableName, array $recordData = array()); $tf->changeRecord($tableName, $uid, array $recordData); $tf->deleteRecord($tableName, $uid); $tf->createRelation($tableName, $uidLocal, $uidForeign, $sorting = 0);$tf->createRelationAndUpdateCounter($tableName, $uidLocal, $uidForeign, $columnName); $tf->removeRelation($tableName, $uidLocal, $uidForeign); $numberOfRecords = $tf->countRecords($tableName, $whereClause = ); $success = $tf->existsRecord($tableName, $whereClause = ); $success = $tf->existsExactlyOneRecord($tableName, $whereClause = );
    • 85. The testing framework can fake almost everything $recordUid = $tf->createRecord($tableName, array $recordData = array()); $tf->changeRecord($tableName, $uid, array $recordData); $tf->deleteRecord($tableName, $uid); $tf->createRelation($tableName, $uidLocal, $uidForeign, $sorting = 0);$tf->createRelationAndUpdateCounter($tableName, $uidLocal, $uidForeign, $columnName); $tf->removeRelation($tableName, $uidLocal, $uidForeign); $numberOfRecords = $tf->countRecords($tableName, $whereClause = ); $success = $tf->existsRecord($tableName, $whereClause = ); $success = $tf->existsExactlyOneRecord($tableName, $whereClause = ); $success = $tf->existsRecordWithUid($tableName, $uid);
    • 86. The testing framework can fake almost everything
    • 87. The testing framework can fake almost everything $pageUid = $tf->createFrontEndPage($parentId = 0, array $recordData = array());
    • 88. The testing framework can fake almost everything $pageUid = $tf->createFrontEndPage($parentId = 0, array $recordData = array()); $pageUid = $tf->createSystemFolder($parentId = 0, array $recordData = array());
    • 89. The testing framework can fake almost everything $pageUid = $tf->createFrontEndPage($parentId = 0, array $recordData = array()); $pageUid = $tf->createSystemFolder($parentId = 0, array $recordData = array()); $elementUid = $tf->createContentElement($pageId = 0, array $recordData = array());
    • 90. The testing framework can fake almost everything $pageUid = $tf->createFrontEndPage($parentId = 0, array $recordData = array()); $pageUid = $tf->createSystemFolder($parentId = 0, array $recordData = array()); $elementUid = $tf->createContentElement($pageId = 0, array $recordData = array()); $tf->createTemplate($pageId, array $recordData = array());
    • 91. The testing framework can fake almost everything $pageUid = $tf->createFrontEndPage($parentId = 0, array $recordData = array()); $pageUid = $tf->createSystemFolder($parentId = 0, array $recordData = array()); $elementUid = $tf->createContentElement($pageId = 0, array $recordData = array()); $tf->createTemplate($pageId, array $recordData = array()); $pageUid = $tf->createFakeFrontEnd($pageUid = 0);
    • 92. The testing framework can fake almost everything $pageUid = $tf->createFrontEndPage($parentId = 0, array $recordData = array()); $pageUid = $tf->createSystemFolder($parentId = 0, array $recordData = array()); $elementUid = $tf->createContentElement($pageId = 0, array $recordData = array()); $tf->createTemplate($pageId, array $recordData = array()); $pageUid = $tf->createFakeFrontEnd($pageUid = 0); $tf->discardFakeFrontEnd();
    • 93. The testing framework can fake almost everything $pageUid = $tf->createFrontEndPage($parentId = 0, array $recordData = array()); $pageUid = $tf->createSystemFolder($parentId = 0, array $recordData = array()); $elementUid = $tf->createContentElement($pageId = 0, array $recordData = array()); $tf->createTemplate($pageId, array $recordData = array()); $pageUid = $tf->createFakeFrontEnd($pageUid = 0); $tf->discardFakeFrontEnd(); $groupUid = $tf->createFrontEndUserGroup(array $recordData = array());
    • 94. The testing framework can fake almost everything $pageUid = $tf->createFrontEndPage($parentId = 0, array $recordData = array()); $pageUid = $tf->createSystemFolder($parentId = 0, array $recordData = array()); $elementUid = $tf->createContentElement($pageId = 0, array $recordData = array()); $tf->createTemplate($pageId, array $recordData = array()); $pageUid = $tf->createFakeFrontEnd($pageUid = 0); $tf->discardFakeFrontEnd(); $groupUid = $tf->createFrontEndUserGroup(array $recordData = array()); $userUid = $tf->createFrontEndUser($groups = , array $recordData = array());
    • 95. The testing framework can fake almost everything $pageUid = $tf->createFrontEndPage($parentId = 0, array $recordData = array()); $pageUid = $tf->createSystemFolder($parentId = 0, array $recordData = array()); $elementUid = $tf->createContentElement($pageId = 0, array $recordData = array()); $tf->createTemplate($pageId, array $recordData = array()); $pageUid = $tf->createFakeFrontEnd($pageUid = 0); $tf->discardFakeFrontEnd(); $groupUid = $tf->createFrontEndUserGroup(array $recordData = array()); $userUid = $tf->createFrontEndUser($groups = , array $recordData = array()); $tf->loginFrontEndUser($userId);
    • 96. The testing framework can fake almost everything $pageUid = $tf->createFrontEndPage($parentId = 0, array $recordData = array()); $pageUid = $tf->createSystemFolder($parentId = 0, array $recordData = array()); $elementUid = $tf->createContentElement($pageId = 0, array $recordData = array()); $tf->createTemplate($pageId, array $recordData = array()); $pageUid = $tf->createFakeFrontEnd($pageUid = 0); $tf->discardFakeFrontEnd(); $groupUid = $tf->createFrontEndUserGroup(array $recordData = array()); $userUid = $tf->createFrontEndUser($groups = , array $recordData = array()); $tf->logoutFrontEndUser(); $tf->loginFrontEndUser($userId);
    • 97. The testing framework can fake almost everything $pageUid = $tf->createFrontEndPage($parentId = 0, array $recordData = array()); $pageUid = $tf->createSystemFolder($parentId = 0, array $recordData = array()); $elementUid = $tf->createContentElement($pageId = 0, array $recordData = array()); $tf->createTemplate($pageId, array $recordData = array()); $pageUid = $tf->createFakeFrontEnd($pageUid = 0); $tf->discardFakeFrontEnd(); $groupUid = $tf->createFrontEndUserGroup(array $recordData = array()); $userUid = $tf->createFrontEndUser($groups = , array $recordData = array()); $tf->logoutFrontEndUser(); $tf->loginFrontEndUser($userId);$userUid = $tf->createAndLoginFrontEndUser($groups = , array $recordData = array());
    • 98. The testing framework can fake almost everything $pageUid = $tf->createFrontEndPage($parentId = 0, array $recordData = array()); $pageUid = $tf->createSystemFolder($parentId = 0, array $recordData = array()); $elementUid = $tf->createContentElement($pageId = 0, array $recordData = array()); $tf->createTemplate($pageId, array $recordData = array()); $pageUid = $tf->createFakeFrontEnd($pageUid = 0); $tf->discardFakeFrontEnd(); $groupUid = $tf->createFrontEndUserGroup(array $recordData = array()); $userUid = $tf->createFrontEndUser($groups = , array $recordData = array()); $tf->logoutFrontEndUser(); $tf->loginFrontEndUser($userId);$userUid = $tf->createAndLoginFrontEndUser($groups = , array $recordData = array()); $isLoggedIn = $tf->isLoggedIn();
    • 99. The testing framework can fake almost everything
    • 100. The testing framework can fake almost everything $recordUid = $tf->createBackEndUser(array $recordData = array());
    • 101. The testing framework can fake almost everything $recordUid = $tf->createBackEndUser(array $recordData = array()); $recordUid = $tf->createBackEndUserGroup(array $recordData = array());
    • 102. The testing framework can fake almost everything
    • 103. The testing framework can fake almost everything $path = $tf->createDummyFile($fileName = test.txt, $content = );
    • 104. The testing framework can fake almost everything $path = $tf->createDummyFile($fileName = test.txt, $content = );$path = $tf->createDummyZipArchive($fileName = test.zip, array $filesToAdd = array());
    • 105. The testing framework can fake almost everything $path = $tf->createDummyFile($fileName = test.txt, $content = );$path = $tf->createDummyZipArchive($fileName = test.zip, array $filesToAdd = array()); $tf->deleteDummyFile($fileName);
    • 106. The testing framework can fake almost everything $path = $tf->createDummyFile($fileName = test.txt, $content = );$path = $tf->createDummyZipArchive($fileName = test.zip, array $filesToAdd = array()); $tf->deleteDummyFile($fileName); $path = $tf->createDummyFolder($folderName);
    • 107. The testing framework can fake almost everything $path = $tf->createDummyFile($fileName = test.txt, $content = );$path = $tf->createDummyZipArchive($fileName = test.zip, array $filesToAdd = array()); $tf->deleteDummyFile($fileName); $path = $tf->createDummyFolder($folderName); $tf->deleteDummyFolder($folderName);
    • 108. How to your test extbase controllersclass Tx_Coffee_Controller_CoffeeControllerTest extends Tx_Extbase_Tests_Unit_BaseTestCase { /** @var Tx_Coffee_Controller_CoffeeController */ protected $fixture; /** @var Tx_Fluid_View_TemplateView */ protected $view = NULL; /** @var Tx_Coffee_Domain_Repository_CoffeeRepository */ protected $coffeeRepository = NULL; public function setUp() { $this->fixture = new Tx_Coffee_Controller_CoffeeController(); $this->view = $this->getMock(Tx_Fluid_View_TemplateView, array(), array(), , FALSE); $this->fixture->setView($this->view); $this->objectManager = $this->getMock(Tx_Extbase_Object_ObjectManagerInterface); $this->fixture->injectObjectManager($this->objectManager); $this->coffeeRepository = $this->getMock( Tx_Coffee_Domain_Repository_CoffeeRepository, array(findAll, findByBrand), array($this->objectManager) ); $this->fixture->injectCoffeeRepository($this->coffeeRepository); }
    • 109. How to your test extbase controllersclass Tx_Coffee_Controller_CoffeeControllerTest extends Tx_Extbase_Tests_Unit_BaseTestCase { /** @var Tx_Coffee_Controller_CoffeeController */ protected $fixture; /** @var Tx_Fluid_View_TemplateView */ protected $view = NULL; /** @var Tx_Coffee_Domain_Repository_CoffeeRepository */ protected $coffeeRepository = NULL; public function setUp() { $this->fixture = new Tx_Coffee_Controller_CoffeeController(); $this->view = $this->getMock(Tx_Fluid_View_TemplateView, array(), array(), , FALSE); $this->fixture->setView($this->view); $this->objectManager = $this->getMock(Tx_Extbase_Object_ObjectManagerInterface); $this->fixture->injectObjectManager($this->objectManager); $this->coffeeRepository = $this->getMock( Tx_Coffee_Domain_Repository_CoffeeRepository, array(findAll, findByBrand), array($this->objectManager) ); $this->fixture->injectCoffeeRepository($this->coffeeRepository); } class Tx_Coffee_Controller_CoffeeController extends Tx_Extbase_MVC_Controller_ActionController { /** * Sets the view. * * This function is intended to be used for unit testing purposes only. * * @param Tx_Fluid_View_TemplateView $view the new view * * @return void */ public function setView(Tx_Fluid_View_TemplateView $view) { $this->view = $view; }
    • 110. How to test your extbase controllers
    • 111. How to your test extbase controllers/** * @test */public function indexActionAssignsAllCoffeesToView() { $models = $this->getMock(Tx_Extbase_Persistence_QueryResultInterface); $this->coffeeRepository->expects($this->once())->method(findAll) ->will($this->returnValue($models)); $this->view->expects($this->at(0))->method(assign)->with(coffees, $models); $this->fixture->indexAction();}
    • 112. How to your test extbase controllers/** * @test */public function indexActionAssignsAllCoffeesToView() { $models = $this->getMock(Tx_Extbase_Persistence_QueryResultInterface); $this->coffeeRepository->expects($this->once())->method(findAll) ->will($this->returnValue($models)); $this->view->expects($this->at(0))->method(assign)->with(coffees, $models); $this->fixture->indexAction();}/** * @test */public function showActionAssignsModelToView() { $model = clone new Tx_Coffee_Domain_Model_Coffee(); $this->view->expects($this->at(0))->method(assign)->with(coffee, $model); $this->fixture->showAction($model);}

    ×