Download - Behavioural Driven Development in Zf2
Behavior-Driven Development with Zend Framework 2
Zend Framework Day – Turin, Italy – 07/02/2014
DAVID CONTAVALLI
@mauipipe
2
3
CLEAN CODE ADEPT BDD FANATIC
4
CLEAN CODE ADEPT BDD FANATIC
WHAT IS BDD?
TDD Evolution
6
1. You are not allowed to write any production code
unless it is to make a failing unit test pass.
7
SAME RULES
1. You are not allowed to write any production code
unless it is to make a failing unit test pass.
2. You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
8
SAME RULES
1. You are not allowed to write any production code
unless it is to make a failing unit test pass.
2. You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
3. You are not allowed to write any more production code than is sufficient to pass the one failing unit test.
9
SAME RULES
WHAT’S THE DIFFERENCE?
TDD STARTS FROM COMPONENTS
12
CREATE THE TEST
private $calculator; function setUp(){ $this->calculator = new Calculator(); } function testSumTwoPositive(){ $expectedResult = 8; $result = $this->calculator(6,2); assertEquals($expectedResult,$result); }
13
14
WRITE QUICK, TEST VALIDATING CODE
class Calculator{ public function sum($num1, $num2){ return 8; } }
15
16
REFACTOR
class Calculator{ public function sum($num1, $num2){ $sum = $num1 + $num2; return $sum; } }
17
BDD STARTS FROM AN EXAMPLE
19
SPECIFICATION BY EXAMPLE
Scenario: Add two number Given I fill number1 field with 2 And I fill number2 field with 6 When I press Add button Then the result should be 8
20
A COMMON LANGUAGE
STAKEHOLDER
21
DEVELOPER
STAKEHOLDER
A COMMON LANGUAGE
22
DEVELOPER
STAKEHOLDER USER
A COMMON LANGUAGE
LIVING DOCUMENTATION
HOW IS STORY CODE RELATED?
25
GHERKIN
Scenario: Add two number Given I fill number1 field with 2 And I fill number2 field with 6 When I press Add button Then the result should be 8
26
Interpreted in many languages
27
GHERKIN
28
GHERKIN
WHAT IS BEHAT?
31
Scenario: Add two numbers Given I fill number1 field with value of 2
TRANSLATE
/** * @Given /^I fill ([^’’]*) with (\d+)$/ **/ public function iFieldFieldWith($number, $fieldName) { throw new PendingException(); }
32
EXECUTION
USERS WILL NOT READ STORIES
THEY WILL USE AN UI
BROWSER
36
HOW TO TEST BROWSER WITH BEHAT?
HERE IT COMES, MINK!
38
GHERKIN
+
39
GOUTTE • Headless Browser • No Javascript • Really fast
Web Acceptance Test
40
GOUTTE • Headless Browser • No Javascript • Really fast
SELENIUM • Can test Javascript • Really slow • Use Firefox as emulator
Web Acceptance Test
41
GOUTTE • Headless Browser • No Javascript • Really fast
SELENIUM • Can test Javascript • Really slow • Use Firefox as emulator
Zombie.js • Can test Javascript • Medium • Use Firefox as emulator
Web Acceptance Test
42
GOUTTE • Headless Browser • No Javascript • Really fast
SELENIUM • Can test Javascript • Really slow • Use Firefox as emulator
Zombie.js • Can test Javascript • Medium • Use Firefox as emulator
SAHI • Can test Javascript • slow • Emulate every Browser
Web Acceptance Test
43
/** * @When /^I press ‘’(/[^’’]*)’’ button$/ **/ public function iPressButton($buttonName) { $this->pressButton($buttonName); }
Scenario: Add two numbers Given I fill number1 field with 2 And I fill number2 field with 6 When I press Add button Then the result should be 8
44
+
How to install....
45
"require-dev " :{ ......... "behat/behat" : "2.4.*@stable", "behat/mink": "1.5.0", "behat/mink-extension":"*", "behat/mink-browserkit-driver":"dev-master", "behat/mink-goutte-driver":"*", "phpspec/phpspec":" 2.0.*@dev" }
46
Differs from documentation
because there is a fix for ZF2
multicheckbox selection
"require-dev " :{ ......... "behat/behat" : "2.4.*@stable", "behat/mink": "1.5.0", "behat/mink-extension":"*", "behat/mink-browserkit-driver":"dev-master", "behat/mink-goutte-driver":"*", "phpspec/phpspec":" 2.0.*@dev" }
47
default : extensions : Behat\MinkExtension\Extension : base_url : 'http://example.com' goutte : ~
behat.yml
Mink Setup
48
+
+
49
private static app; /** * @BeforeSuite **/ public static function initializeZf(){ If(self::$zendApp === null){ $path = __DIR__ .’/../../config/application.config.php’; self::app = \Zend\Mvc\Application::init(require $path); } }
Static method
ZF2 EXTENSION
51
"require-dev":{ ................ "mvlabs/zf2behat-extension":"dev-master" },
52
default : extensions : MvLabs\Zf2Extension\Zf2Extension : config : config/application.config.php module :
behat.yml
Zf2 Behat Extension
53
bin/behat --init ‘’module name’’ run from console
Zf2 Behat Extension
54
class FeatureContext extends MinkContext implements Zf2AwareContextInterface{ private $zf2MvcApplication; ......... public function setZf2App(Application $zf2MvcApplication) { $this->zf2MvcApplication = $zf2MvcApplication; } }
Implements Zf2AwareContextInterface
Feature Context
WE STILL NEED TO TEST OUR COMPONENTS
56
GHERKIN
+
57
WHY PHPSPEC?
BDD BASED ON BEHAVIOUR DESCRIPTION
Robert C. Martin
59
private $calculator; function setUp(){ $this->calculator = new Calculator(); } function testSumTwoPositive(){ $expectedResult = 8; $result = $this->calculator(6,2); assertEquals($expectedResult,$result); }
PHPUnit focus on testing code
60
function let(){ $this->shouldBeConstructed(); } function it_sum_two_positive_number(){ $this->sum(2,6)->shouldReturn(8); }
PHPSpec focus on code behavior
61
"It’s this unexisting object, on which you’re calling unexisting methods and assuming future outcomes. Most important thing? There could be only one SUS in specification" Kostantin Kudryashov
Subject under Specification
62
Developer Tool Vs Testing Framework
63
bin/phpspec desc ‘’Application\Controller\IndexController’’
Autogenerates classes & methods
PROMOTES CLEAN CODE
65
function let(){ $this->shouldBeConstructed(); } function it_sum_two_positive_number(){ $this->getPlayer()->getSword()->shouldBeInstanceOf(‘Sword’); }
Demeter Law's Violation
66
function let(){ $this->shouldBeConstructed(); } function it_sum_two_positive_number(){ $this->getPlayer()->getSword()->shouldBeInstanceOf(‘Sword’); }
Impossible
67
+
Add PHPSpec to Zf2
68
"require-dev":{ ........... "phpspec/phpspec" : "2.0.*@dev" }, "config": { "bin-dir": "bin/" }, "autoload": { "psr-0" { "Application" : " module/Application/src" } }
’’require-dev’’:{ ... "phpspec/phpspec":" 2.0.*@dev" }, "config": { "bin-dir": "bin« }, "autoload": { "psr-0": { "Application": "module/Application/src" } }
69
"require-dev":{ ........... "phpspec/phpspec" : "2.0.*@dev" }, "config": { "bin-dir": "bin/" }, "autoload": { "psr-0" { "Application" : " module/Application/src" } }
Add a single module
70
"require-dev":{ ........... "phpspec/phpspec" : "2.0.*@dev" }, "config": { "bin-dir": "bin/" }, "autoload": { "psr-0" { "Application" : " module/Application/src", "Calculator" : "module/Calculator/src" } }
Add more modules
71
formatter.name : progresssuites Application: namespace : Application spec_prefix : Spec src_path : 'module/Application/src/' spec_path : 'module/Application/' ModuleDemo: namespace : ModuleDemo spec_prefix : Spec src_path : 'module/ModuleDemo/src/' spec_path : 'module/ModuleDemo/'
Create phpspec.yml in project root
72
What to test with PHPSpec?
73
1.Model Logic
What to test with PHPSpec?
74
1.Model Logic
2.Factories
What to test with PHPSpec?
75
1.Model Logic
2.Factories
3.Validation
What to test with PHPSpec?
76
1.Verbose Stories
2.Using Mink to test REST calls
3.Testing every possible usages combination
4.Fixture loading within Context
Behat bad practices
WHY TESTING?
IT’S A TREND
RELAX
SOMEONE WILL READ YOUR CODE
IT COULD BE YOU SOME DAY
YOUR COLLEAGUES
84
OR
A VIOLENT PSYCHOPATH WHO KNOWS WHERE YOU LIVE
Thank you for your attention
David Contavalli @mauipipe
QUESTIONS?
@mauipipe [email protected]
90
Some readings
Credits
91
https://www.flickr.com/photos/42788859@N00/318947873
https://www.flickr.com/photos/79811974@N08/8895959339/
https://www.flickr.com/photos/wingedwolf/5471047557/
https://www.flickr.com/photos/21112928@N07/2922128673/
https://www.flickr.com/photos/23408922@N07/8220573257/
https://www.flickr.com/photos/11956371@N07/4146284063/
http://www.flickr.com/photos/chemicalbrother/2540855983/
http://www.flickr.com/photos/slworking/5757370044/
http://www.flickr.com/photos/ter-burg/5807937726/
http://www.flickr.com/photos/thyagohills/5023536434/
http://www.flickr.com/photos/jeremybrooks/2175042537/
http://www.flickr.com/photos/bowmanlibrary/941844481/
http://www.flickr.com/photos/webhamster/2476756607/
http://www.flickr.com/photos/nebirdsplus/5835963068/
http://www.flickr.com/photos/mistaboos/4348381987/
http://www.flickr.com/photos/moofbong/4207382992/
http://www.flickr.com/photos/ryanh/43936630/
http://www.flickr.com/photos/nathangibbs/98592171/
http://www.flickr.com/photos/71894657@N00/2553948289/
http://www.flickr.com/photos/ahia/3168219760/
http://www.flickr.com/photos/smileham/3559228586/
http://www.flickr.com/photos/kk/3834592792/
http://www.flickr.com/photos/enoughproject/5776533975/
http://www.flickr.com/photos/_flood_/8067625282/
http://www.flickr.com/photos/drooo/3114233333/
http://www.flickr.com/photos/84143785@N00/3559757811
David Contavalli @mauipipe