Behavior-Driven Development
with Zend Framework 2

Zend Framework Day – Turin, Italy – 07/02/2014
DAVID CONTAVALLI

@mauipipe

2
CLEAN CODE ADEPT
BDD FANATIC

3
CLEAN CODE ADEPT
BDD FANATIC

4
WHAT IS BDD?
TDD Evolution

6
SAME RULES
1.

7

You are not allowed to write any production code
unless it is to make a failing unit test pass.
SAME RULES
1.

2.

8

You are not allowed to write any production code
unless it is to make a failing unit test pass.
You are not allowed to write any more of a unit test
than is sufficient to fail; and compilation failures are
failures.
SAME RULES
1.

2.

You are not allowed to write any more of a unit test
than is sufficient to fail; and compilation failures are
failures.

3.

9

You are not allowed to write any production code
unless it is to make a failing unit test pass.

You are not allowed to write any more production code
than is sufficient to pass the one failing unit test.
WHAT’S THE DIFFERENCE?
TDD STARTS FROM COMPONENTS
CREATE THE TEST
private $calculator;
function setUp(){
$this->calculator = new Calculator();
}
function testSumTwoPositive(){
$expectedResult = 8;
$result = $this->calculator(6,2);
assertEquals($expectedResult,$result);
}

12
13
WRITE QUICK, TEST VALIDATING CODE

class Calculator{
public function sum($num1, $num2){
return 8;
}
}

14
15
REFACTOR

class Calculator{
public function sum($num1, $num2){
$sum = $num1 + $num2;
return $sum;
}
}

16
17
BDD STARTS FROM AN EXAMPLE
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

19
A COMMON LANGUAGE

STAKEHOLDER
20
A COMMON LANGUAGE

DEVELOPER
STAKEHOLDER
21
A COMMON LANGUAGE

DEVELOPER
STAKEHOLDER
22

USER
LIVING DOCUMENTATION
HOW IS STORY CODE RELATED?
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

25
Interpreted in many languages

26
GHERKIN

27
GHERKIN

28
WHAT IS BEHAT?
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();
}
31
EXECUTION

32
USERS WILL NOT READ STORIES
THEY WILL USE AN UI
BROWSER
HOW TO TEST BROWSER WITH BEHAT?

36
HERE IT COMES, MINK!
GHERKIN

+

38
Web Acceptance Test

GOUTTE
• Headless Browser
• No Javascript
• Really fast

39
Web Acceptance Test

GOUTTE
• Headless Browser
• No Javascript
• Really fast

40

SELENIUM
• Can test Javascript
• Really slow
• Use Firefox as emulator
Web Acceptance Test

GOUTTE
• Headless Browser
• No Javascript
• Really fast

41

SELENIUM
• Can test Javascript
• Really slow
• Use Firefox as emulator
Zombie.js
• Can test Javascript
• Medium
• Use Firefox as emulator
Web Acceptance Test

GOUTTE
• Headless Browser
• No Javascript
• Really fast

42

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
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
/**
* @When /^I press ‘’(/[^’’]*)’’ button$/
**/
public function iPressButton($buttonName)
{
$this->pressButton($buttonName);
}

43
How to install....

+

44
"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"
}
45
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"
}
46
Mink Setup
behat.yml
default :
extensions :
BehatMinkExtensionExtension :
base_url : 'http://example.com'
goutte : ~

47
+
+
48
Static method
private static app;
/**
* @BeforeSuite
**/
public static function initializeZf(){
If(self::$zendApp === null){
$path = __DIR__ .’/../../config/application.config.php’;
self::app = ZendMvcApplication::init(require $path);
}
}
49
ZF2 EXTENSION
"require-dev":{
................
"mvlabs/zf2behat-extension":"dev-master"
},
51
Zf2 Behat Extension
behat.yml
default :
extensions :
MvLabsZf2ExtensionZf2Extension :
config : config/application.config.php
module :

52
Zf2 Behat Extension

run from console

bin/behat --init ‘’module name’’

53
Feature Context
Implements Zf2AwareContextInterface
class FeatureContext extends MinkContext implements
Zf2AwareContextInterface{
private $zf2MvcApplication;
.........
public function setZf2App(Application $zf2MvcApplication) {
$this->zf2MvcApplication = $zf2MvcApplication;
}

}

54
WE STILL NEED TO TEST
OUR COMPONENTS
GHERKIN

+

56
WHY PHPSPEC?

57
BDD BASED ON BEHAVIOUR
DESCRIPTION
Robert C. Martin
PHPUnit focus on testing code
private $calculator;

function setUp(){
$this->calculator = new Calculator();
}
function testSumTwoPositive(){
$expectedResult = 8;
$result = $this->calculator(6,2);
assertEquals($expectedResult,$result);
}
59
PHPSpec focus on code behavior
function let(){
$this->shouldBeConstructed();
}

function it_sum_two_positive_number(){
$this->sum(2,6)->shouldReturn(8);
}

60
Subject under Specification
"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

61
Developer Tool Vs Testing Framework

62
Autogenerates classes & methods
bin/phpspec desc ‘’ApplicationControllerIndexController’’

63
PROMOTES CLEAN CODE
Demeter Law's Violation
function let(){
$this->shouldBeConstructed();
}
function it_sum_two_positive_number(){
$this->getPlayer()->getSword()->shouldBeInstanceOf(‘Sword’);
}

65
Impossible
function let(){
$this->shouldBeConstructed();
}
function it_sum_two_positive_number(){
$this->getPlayer()->getSword()->shouldBeInstanceOf(‘Sword’);
}

66
Add PHPSpec to Zf2

+

67
"require-dev":{
...........
"phpspec/phpspec" : "2.0.*@dev"
},
"config": {
"bin-dir": "bin/"
},
"autoload": {
"psr-0" {
"Application" : " module/Application/src"
}
}
68
Add a single module

’’require-dev’’:{
"require-dev":{
...........
...
"phpspec/phpspec" : "2.0.*@dev"
"phpspec/phpspec":" 2.0.*@dev"
},
},
"config": {
"config": {
"bin-dir": "bin/"
"bin-dir": "bin«
},
},
"autoload": { {
"autoload":
"psr-0" { {
"psr-0":
"Application" : " module/Application/src"
"Application": "module/Application/src"
} }
}}
69
Add more modules

"require-dev":{
...........
"phpspec/phpspec" : "2.0.*@dev"
},
"config": {
"bin-dir": "bin/"
},
"autoload": {
"psr-0" {
"Application" : " module/Application/src",
"Calculator" : "module/Calculator/src"
}
}
70
Create phpspec.yml in project root
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/'
71
What to test with PHPSpec?

72
What to test with PHPSpec?
1.Model Logic

73
What to test with PHPSpec?
1.Model Logic
2.Factories

74
What to test with PHPSpec?
1.Model Logic
2.Factories

3.Validation

75
Behat bad practices
1. Verbose Stories

2. Using Mink to test REST calls
3. Testing every possible usages combination
4. Fixture loading within Context

76
WHY TESTING?
IT’S A TREND
RELAX
SOMEONE WILL READ YOUR CODE
IT COULD BE YOU SOME DAY
YOUR COLLEAGUES
OR
84
A VIOLENT PSYCHOPATH WHO
KNOWS WHERE YOU LIVE
Thank you for your attention

David Contavalli
@mauipipe
QUESTIONS?
@mauipipe
mauipipe@gmail.com
Some readings

90
Credits
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

91
David Contavalli
@mauipipe

Behavioural Driven Development in Zf2