TDD, a starting point A PHP perspective... Francesco Fullone, Ideato.it ff AT ideato.it
May 17, 2015
TDD, a starting pointA PHP perspective...
Francesco Fullone, Ideato.itff AT ideato.it
Who am I
Francesco Fullone aka Fullo
- PHP developer since 1999
- President
- and Open Source Evangelist
- CEO @
- Nerd and geek
TDD ?
Test Driven Development
Why test the code?
Developers are humans, Humans are error-prone.
Software changes and grows.
We need to confirm that the code is working after any changes.
xUNIT TDD approach.
PHPUnit.de
Easy to writeEasy to read
IsolatedComposable
An example: The bowling kata
(courtesy grabbed from Sebastian Bergmann)
10 frames
2 rolls to knock down the 10 pins Score for a frame is the number of pins knocked down
Bonus for a spare (all 10 pins knocked down in two tries): next roll Bonus for a strike (all 10 pins knocked down in one try): next two rolls Extra rolls for spare or strike in the 10th frame
<?phprequire_once 'BowlingGame.php';
class BowlingGameTest extends PHPUnit_Framework_TestCase{
}?>
<?phprequire_once 'BowlingGame.php';
class BowlingGameTest extends PHPUnit_Framework_TestCase{
public function testScoreForGutterGameIs0(){
}
}
<?phprequire_once 'BowlingGame.php';
class BowlingGameTest extends PHPUnit_Framework_TestCase{
public function testScoreForGutterGameIs0(){
$game = new BowlingGame;for ($i = 0; $i < 20; $i++) {
$game->roll(0);}
$this->assertEquals(0, $game->score());}
}
fullo@teletran ~ % phpunit --skeleton-class BowlingGameTestPHPUnit 3.4.2 by Sebastian Bergmann.Wrote skeleton for "BowlingGame" to "BowlingGame.php".
<?phpclass BowlingGame{
public function roll() { // Remove the following line when you
// implement this method.
throw new RuntimeException('Not yet implemented.'); }
public function score() {
// Remove the following line when you // implement this method.
throw new RuntimeException('Not yet implemented.'); }}
fullo@teletran ~ % phpunit BowlingGameTestPHPUnit 3.4.2 by Sebastian Bergmann.
E
Time: 0 seconds
There was 1 error:
1) BowlingGameTest::testScoreForGutterGameIs0RuntimeException: Not yet implemented./home/fullo/BowlingGame.php:10/home/fullo/BowlingGameTest.php:11
FAILURES!Tests: 1, Assertions: 0, Errors: 1.
<?phpclass BowlingGame{
public function roll($pins) { }
public function score() {
return 0; }}?>
fullo@teletran ~ % phpunit --colors BowlingGameTestPHPUnit 3.4.2 by Sebastian Bergmann.
.
Time: 0 seconds
OK (1 test, 1 assertion)
We have to write the tests when the code is
fresh.
<?phprequire_once 'BowlingGame.php';
class BowlingGameTest extends PHPUnit_Framework_TestCase{
// …
public function testScoreForAllOnesIs20(){
$game = new BowlingGame;
for ($i = 0; $i < 20; $i++) { $game->roll(1); }
$this->assertEquals(20, $game->score());}
}
fullo@teletran ~ % phpunit –colors BowlingGameTestPHPUnit 3.4.2 by Sebastian Bergmann.
.F
Time: 0 seconds
There was 1 failure:
1) BowlingGameTest::testScoreForAllOnesIs20Failed asserting that <integer:0> matches expected value <integer:20>./home/fullo/BowlingGameTest.php:25
FAILURES!Tests: 2, Assertions: 2, Failures: 1.
<?phpclass BowlingGame{
protected $rolls = array();
public function roll($pins) { $this->rolls[] = $pins; }
public function score() {
return array_sum($this->rolls); } }
<?phprequire_once 'BowlingGame.php';
class BowlingGameTest extends PHPUnit_Framework_TestCase{
// …
public function testScoreForOneSpareAnd3Is16(){
$game = new BowlingGame;
$game->roll(5); $game->roll(5); $game->roll(3);
// a function to to roll X times $this->rollMany(17, 0); $this->assertEquals(16, $game->score());
}
}
fullo@teletran ~ % phpunit –colors BowlingGameTestPHPUnit 3.4.2 by Sebastian Bergmann.
..F
Time: 0 seconds
There was 1 failure:
1) BowlingGameTest::testScoreForOneSpareAnd3is16Failed asserting that <integer:13> matches expected value <integer:16>./home/fullo/BowlingGameTest.php:33
FAILURES!Tests: 2, Assertions: 2, Failures: 1.
Tests can serve as an executable
specification.
fullo@teletran ~ % phpunit --testdox BowlingGameTestPHPUnit 3.4.2 by Sebastian Bergmann.
BowlingGame [x] Score for gutter game is 0 [ ] Score for all ones is 20 [ ] Score for one spare and 3 is 16 [ ] Score for one strike and 3 and 4 is 24 [ ] Score for perfect game is 300
Why Unit Test.
To write only clean and useful code.
To easily iterate in development design.
To check for regressions.
?
For more info see Sebastian Bergmann's Bowling Kata
Workshop!
http://www.slideshare.net/sebastian_bergmann/quality-assurance-in-
php-projects-2164371
Francesco Fulloneff AT ideato.itskype: ffullone
via Quinto Bucci 20547023 Cesena (FC)
info AT ideato.itwww.ideato.it