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 ...
SAME RULES
1.

2.

You are not allowed to write any more of a unit test
than is sufficient to fail; and compilation failur...
WHAT’S THE DIFFERENCE?
TDD STARTS FROM COMPONENTS
CREATE THE TEST
private $calculator;
function setUp(){
$this->calculator = new Calculator();
}
function testSumTwoPositive...
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 ...
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 butto...
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+)$/...
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 ...
Web Acceptance Test

GOUTTE
• Headless Browser
• No Javascript
• Really fast

41

SELENIUM
• Can test Javascript
• Really ...
Web Acceptance Test

GOUTTE
• Headless Browser
• No Javascript
• Really fast

42

SELENIUM
• Can test Javascript
• Really ...
Scenario: Add two numbers
Given I fill number1 field with 2
And I fill number2 field with 6
When I press Add button
Then t...
How to install....

+

44
"require-dev " :{
.........
"behat/behat" : "2.4.*@stable",
"behat/mink": "1.5.0",
"behat/mink-extension":"*",
"behat/mink...
Differs from documentation
because there is a fix for ZF2
multicheckbox selection

"require-dev " :{
.........
"behat/beha...
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...
ZF2 EXTENSION
"require-dev":{
................
"mvlabs/zf2behat-extension":"dev-master"
},
51
Zf2 Behat Extension
behat.yml
default :
extensions :
MvLabsZf2ExtensionZf2Extension :
config : config/application.config.p...
Zf2 Behat Extension

run from console

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

53
Feature Context
Implements Zf2AwareContextInterface
class FeatureContext extends MinkContext implements
Zf2AwareContextInt...
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 tes...
PHPSpec focus on code behavior
function let(){
$this->shouldBeConstructed();
}

function it_sum_two_positive_number(){
$th...
Subject under Specification
"It’s this unexisting object, on which you’re
calling unexisting methods and assuming future
o...
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->getP...
Impossible
function let(){
$this->shouldBeConstructed();
}
function it_sum_two_positive_number(){
$this->getPlayer()->getS...
Add PHPSpec to Zf2

+

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

’’require-dev’’:{
"require-dev":{
...........
...
"phpspec/phpspec" : "2.0.*@dev"
"phpspec/phpspec":"...
Add more modules

"require-dev":{
...........
"phpspec/phpspec" : "2.0.*@dev"
},
"config": {
"bin-dir": "bin/"
},
"autoloa...
Create phpspec.yml in project root
formatter.name : progresssuites
Application:
namespace : Application
spec_prefix : Spec...
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. F...
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:...
David Contavalli
@mauipipe
Behavioural Driven Development in Zf2
Behavioural Driven Development in Zf2
Behavioural Driven Development in Zf2
Upcoming SlideShare
Loading in...5
×

Behavioural Driven Development in Zf2

1,623

Published on

A quick introduction on how to setup a zf2 project using Behat and Phpspec.

Published in: Technology

Behavioural Driven Development in Zf2

  1. 1. Behavior-Driven Development with Zend Framework 2 Zend Framework Day – Turin, Italy – 07/02/2014
  2. 2. DAVID CONTAVALLI @mauipipe 2
  3. 3. CLEAN CODE ADEPT BDD FANATIC 3
  4. 4. CLEAN CODE ADEPT BDD FANATIC 4
  5. 5. WHAT IS BDD?
  6. 6. TDD Evolution 6
  7. 7. SAME RULES 1. 7 You are not allowed to write any production code unless it is to make a failing unit test pass.
  8. 8. 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.
  9. 9. 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.
  10. 10. WHAT’S THE DIFFERENCE?
  11. 11. TDD STARTS FROM COMPONENTS
  12. 12. 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. 13. 13
  14. 14. WRITE QUICK, TEST VALIDATING CODE class Calculator{ public function sum($num1, $num2){ return 8; } } 14
  15. 15. 15
  16. 16. REFACTOR class Calculator{ public function sum($num1, $num2){ $sum = $num1 + $num2; return $sum; } } 16
  17. 17. 17
  18. 18. BDD STARTS FROM AN EXAMPLE
  19. 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 19
  20. 20. A COMMON LANGUAGE STAKEHOLDER 20
  21. 21. A COMMON LANGUAGE DEVELOPER STAKEHOLDER 21
  22. 22. A COMMON LANGUAGE DEVELOPER STAKEHOLDER 22 USER
  23. 23. LIVING DOCUMENTATION
  24. 24. HOW IS STORY CODE RELATED?
  25. 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 25
  26. 26. Interpreted in many languages 26
  27. 27. GHERKIN 27
  28. 28. GHERKIN 28
  29. 29. WHAT IS BEHAT?
  30. 30. 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
  31. 31. EXECUTION 32
  32. 32. USERS WILL NOT READ STORIES
  33. 33. THEY WILL USE AN UI
  34. 34. BROWSER
  35. 35. HOW TO TEST BROWSER WITH BEHAT? 36
  36. 36. HERE IT COMES, MINK!
  37. 37. GHERKIN + 38
  38. 38. Web Acceptance Test GOUTTE • Headless Browser • No Javascript • Really fast 39
  39. 39. Web Acceptance Test GOUTTE • Headless Browser • No Javascript • Really fast 40 SELENIUM • Can test Javascript • Really slow • Use Firefox as emulator
  40. 40. 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
  41. 41. 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
  42. 42. 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
  43. 43. How to install.... + 44
  44. 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
  45. 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
  46. 46. Mink Setup behat.yml default : extensions : BehatMinkExtensionExtension : base_url : 'http://example.com' goutte : ~ 47
  47. 47. + + 48
  48. 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
  49. 49. ZF2 EXTENSION
  50. 50. "require-dev":{ ................ "mvlabs/zf2behat-extension":"dev-master" }, 51
  51. 51. Zf2 Behat Extension behat.yml default : extensions : MvLabsZf2ExtensionZf2Extension : config : config/application.config.php module : 52
  52. 52. Zf2 Behat Extension run from console bin/behat --init ‘’module name’’ 53
  53. 53. Feature Context Implements Zf2AwareContextInterface class FeatureContext extends MinkContext implements Zf2AwareContextInterface{ private $zf2MvcApplication; ......... public function setZf2App(Application $zf2MvcApplication) { $this->zf2MvcApplication = $zf2MvcApplication; } } 54
  54. 54. WE STILL NEED TO TEST OUR COMPONENTS
  55. 55. GHERKIN + 56
  56. 56. WHY PHPSPEC? 57
  57. 57. BDD BASED ON BEHAVIOUR DESCRIPTION Robert C. Martin
  58. 58. 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
  59. 59. PHPSpec focus on code behavior function let(){ $this->shouldBeConstructed(); } function it_sum_two_positive_number(){ $this->sum(2,6)->shouldReturn(8); } 60
  60. 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
  61. 61. Developer Tool Vs Testing Framework 62
  62. 62. Autogenerates classes & methods bin/phpspec desc ‘’ApplicationControllerIndexController’’ 63
  63. 63. PROMOTES CLEAN CODE
  64. 64. Demeter Law's Violation function let(){ $this->shouldBeConstructed(); } function it_sum_two_positive_number(){ $this->getPlayer()->getSword()->shouldBeInstanceOf(‘Sword’); } 65
  65. 65. Impossible function let(){ $this->shouldBeConstructed(); } function it_sum_two_positive_number(){ $this->getPlayer()->getSword()->shouldBeInstanceOf(‘Sword’); } 66
  66. 66. Add PHPSpec to Zf2 + 67
  67. 67. "require-dev":{ ........... "phpspec/phpspec" : "2.0.*@dev" }, "config": { "bin-dir": "bin/" }, "autoload": { "psr-0" { "Application" : " module/Application/src" } } 68
  68. 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
  69. 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
  70. 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
  71. 71. What to test with PHPSpec? 72
  72. 72. What to test with PHPSpec? 1.Model Logic 73
  73. 73. What to test with PHPSpec? 1.Model Logic 2.Factories 74
  74. 74. What to test with PHPSpec? 1.Model Logic 2.Factories 3.Validation 75
  75. 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
  76. 76. WHY TESTING?
  77. 77. IT’S A TREND
  78. 78. RELAX
  79. 79. SOMEONE WILL READ YOUR CODE
  80. 80. IT COULD BE YOU SOME DAY
  81. 81. YOUR COLLEAGUES
  82. 82. OR 84
  83. 83. A VIOLENT PSYCHOPATH WHO KNOWS WHERE YOU LIVE
  84. 84. Thank you for your attention David Contavalli @mauipipe
  85. 85. QUESTIONS?
  86. 86. @mauipipe mauipipe@gmail.com
  87. 87. Some readings 90
  88. 88. 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
  89. 89. David Contavalli @mauipipe
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×