The document discusses test-driven development for TYPO3 projects. It introduces the concept of unit testing and test-driven development. It describes how the TYPO3 phpunit extension and PHPUnit can be used to write unit tests and run them automatically. It provides examples of different types of tests and how the testing framework can fake database records, frontend pages and other elements to test code in isolation.
19. The phpunit extension
has it all
phpunit (TYPO3 extension)
PHPUnit (PEAR package)
Testrunner
(back-end-
module)
20. The phpunit extension
has it all
phpunit (TYPO3 extension)
PHPUnit (PEAR package)
Testrunner Testrunner
(back-end-
module) (CLI module)
21. The phpunit extension
has it all
phpunit (TYPO3 extension)
PHPUnit (PEAR package)
Testing framework for FE & DB
Testrunner Testrunner
(back-end-
module) (CLI module)
50. Use meaningful
unit test names
Name the
behavior. classCanBeInstantiated
51. Use meaningful
unit test names
Name the
behavior. classCanBeInstantiated
Mention the
method. setTitleSetsTitle
52. Use meaningful
unit test names
Name the
behavior. classCanBeInstantiated
Mention the
method. setTitleSetsTitle
Name the setSizeWithZeroThrowsException
preconditions. hasTitleForEmptyTitleReturnsFalse
53. Use meaningful
unit test names
Name the
behavior. classCanBeInstantiated
Mention the
method. setTitleSetsTitle
Name the setSizeWithZeroThrowsException
preconditions. hasTitleForEmptyTitleReturnsFalse
Dont‘t use
"works" or
"correctly".
54. Use meaningful
unit test names
Name the
behavior. classCanBeInstantiated
Mention the
method. setTitleSetsTitle
Name the setSizeWithZeroThrowsException
preconditions. hasTitleForEmptyTitleReturnsFalse
Dont‘t use
"works" or measureFrubbleWorksCorrectly
"correctly".
55. Use meaningful
unit test names
Name the
behavior. classCanBeInstantiated
Mention the
method. setTitleSetsTitle
Name the setSizeWithZeroThrowsException
preconditions. hasTitleForEmptyTitleReturnsFalse
Dont‘t use
"works" or measureFrubbleWorksCorrectly
"correctly".
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.
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);
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 controllers
class 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 controllers
class 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;
}
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);
}