November Camp - Spec BDD with PHPSpec 2

4,604 views
4,392 views

Published on

My slides on PHPSpec 2 from Symfony November Camp Stockholm.
www.symfony.se/november-camp/

November Camp - Spec BDD with PHPSpec 2

  1. 1. Spec BDD WITH 
 PHPSPEC 2 November Camp Stockholm 22/11/2013 flickr.com/arnolouise/3252847397/
  2. 2. Kacper Gunia @cakper Software Engineer @SensioLabsUK Symfony Certified Developer Polish Symfony Community Silesian PHP User Group
  3. 3. Softw are Quality flickr.com/adforce1/2462794123/
  4. 4. INTERNAL Quality flickr.com/ensh/5084228263/
  5. 5. EXTERNAL Quality flickr.com/arselectronicacenter/8695704856/
  6. 6. INTERNAL vs EXTERNAL
  7. 7. It’s NOT VS
  8. 8. It’s AND
  9. 9. InnerNAL And EXTERNAL flickr.com/pmiaki/6768810175/
  10. 10. How to ensure quality? Test
  11. 11. How to test? Automa te
  12. 12. So you WRITE your code…
  13. 13. …and your tests
  14. 14. HOW DARE YOU?
  15. 15. are YOU sure Tests ARE correct?
  16. 16. Test Driven Development
  17. 17. Red Refactor Green
  18. 18. BUT…
  19. 19. test Something tha doesn’t t exists? flickr.com/ucumari/580865728/
  20. 20. Test In TDD means
 Specifica tion
  21. 21. Specifica tion describes Beha vior
  22. 22. BeHa vior Driven Development
  23. 23. IMPROVED Naming Conventions Tools
  24. 24. TDD v2.0 ‘TDD DONE RIGHT’
  25. 25. Story BDD & Spec BDD
  26. 26. STORY BDD description of business-targeted application behavior
  27. 27. SPEC BDD specification for low-level implementation
  28. 28. Story BDD Failing Scenario Passing Scenario Failing Spec RefacTOR Passing Spec SPEC BDD
  29. 29. External quality Failing Scenario Passing Scenario Failing Spec RefacTOR Passing Spec INTERNAL QUALITY
  30. 30. BEHA 
 T (Story BDD) & PHPSpec 
 (Spec BDD)
  31. 31. BEHA 
 T (Story BDD) & PHPSpec 
 (Spec BDD)
  32. 32. PHPSPEC 2 FRAMEWORK SPEC BDD CREATED BY @_MD & @EVERZET
  33. 33. PHPSPEC 2 Bundled With Mocking Framework - Prophecy
  34. 34. BUT…
  35. 35. WHY NOT PHPUNIT?
  36. 36. PHPUNIT Is A TESTING TOOL
  37. 37. PHPSPEC Is A DESIGN TOOL
  38. 38. EVIDENCE?
  39. 39. PHPUNIT
  40. 40. PHPSPEC
  41. 41. Differences?
  42. 42. tEST Suite Specifica tion
  43. 43. tEST EXAMPLE
  44. 44. Assertion expect tion a
  45. 45. class  MovieSpec  extends  ObjectBehavior   {          function  it_returns_movie_title()          {                  $this-­‐>getTitle()                            -­‐>shouldReturn('Star  Wars');          }   }
  46. 46. Ma tchers
  47. 47. IDENTITY MATCHER class  MovieSpec  extends  ObjectBehavior   {      function  it_is_a_great_movie()      {          $this-­‐>getRating()-­‐>shouldBe(5);                        $this-­‐>getTitle()                    -­‐>shouldBeEqualTo('Star  Wars');                            $this-­‐>getReleaseDate()                    -­‐>shouldReturn(233366400);      }   }
  48. 48. COMPARISON MATCHER class  MovieSpec  extends  ObjectBehavior   {      function  it_is_great_movie()      {          $this-­‐>getRating()-­‐>shouldBeLike('5');      }   }
  49. 49. THROW MATCHER class  MovieSpec  extends  ObjectBehavior   {      function  it_does_not_allow_negative_ratings()      {          $this              -­‐>shouldThrow('InvalidArgumentException')            -­‐>duringSetRating(-­‐3);      }   }
  50. 50. THROW MATCHER class  MovieSpec  extends  ObjectBehavior   {      function  it_does_not_allow_negative_ratings()      {          $this-­‐>shouldThrow(                  new  InvalidArgumentException(                      "Invalid  rating”                  )              )-­‐>during('setRating',  array(-­‐3));          }   }
  51. 51. TYPE MATCHER class  MovieSpec  extends  ObjectBehavior   {      function  it_is_a_movie()      {          $this-­‐>shouldHaveType('Movie');          $this-­‐>shouldReturnAnInstanceOf('Movie');          $this-­‐>shouldBeAnInstanceOf('Movie');          $this-­‐>shouldImplement('Movie');      }   }
  52. 52. OBJECT-STATE MATCHER class  MovieSpec  extends  ObjectBehavior   {      function  it_is_available_on_cinemas()      {          $this-­‐>shouldBeAvailableOnCinemas();      }   }   ! class  Movie   {      public  function  isAvailableOnCinemas()      {  return  true;  }<?php   }
  53. 53. OBJECT-STATE MATCHER class  MovieSpec  extends  ObjectBehavior   {      function  it_has_a_soundtrack()      {          $this-­‐>shouldHaveSoundtrack();      }   }   ! class  Movie   {      public  function  hasSoundtrack()      {  return  true;  }   }
  54. 54. COUNT MATCHER class  MovieSpec  extends  ObjectBehavior   {      function  it_has_one_director()      {          $this-­‐>getDirectors()-­‐>shouldHaveCount(1);      }   }
  55. 55. SCALAR MATCHER class  MovieSpec  extends  ObjectBehavior   {      function  it_has_a_string_as_title()      {          $this-­‐>getTitle()-­‐>shouldBeString();      }   !    function  it_has_an_array_as_cast()      {          $this-­‐>getCast()-­‐>shouldBeArray();      }   }
  56. 56. INLINE MATCHER class  MovieSpec  extends  ObjectBehavior   {      function  it_has_default_options()      {          $this-­‐>getOptions()-­‐>shouldHaveKey('username');      }   !    public  function  getMatchers()      {          return  [              'haveKey'  =>  function($subject,  $key)  {                  return  array_key_exists($key,  $subject);              }          ];      }   }
  57. 57. BUT…
  58. 58. Softw are Design is about Messaging
  59. 59. TEST DOUBLES
  60. 60. DUMMIES class  CinemaSpec  extends  ObjectBehavior   {      /**        *  @param  BoxOffice  $boxOffice        */      function  it_is_a_cinema($boxOffice)      {          $this-­‐>beConstructedWith($boxOffice);          $this-­‐>shouldHaveType('Cinema');      }   }
  61. 61. STUBS class  CinemaSpec  extends  ObjectBehavior   {      /**        *  @param  Movie  $movie        */      function  it_displays_big_movie_title($movie)      {          $movie-­‐>getTitle()                      -­‐>willReturn('Star  Wars’);   !        $this-­‐>displayTitle($movie)                    -­‐>shouldReturn('<h1>Star  Wars</h1>');      }   }
  62. 62. MOCKS class  CinemaSpec  extends  ObjectBehavior   {      /**        *  @param  DvdPlayer  $dvdPlayer        *  @param  MovieDisc  $movieDisc        */      function  it_plays_movie($dvdPlayer,  $movieDisc)      {          $dvdPlayer-­‐>playDisc($movieDisc)                              -­‐>shouldBeCalled();   !        $this-­‐>setPlayer($dvdPlayer);          $this-­‐>playMovie($movieDisc);      }   }
  63. 63. SPIES class  CinemaSpec  extends  ObjectBehavior   {      /**        *  @param  DvdPlayer  $dvdPlayer        *  @param  MovieDisc  $movieDisc        */      function  it_plays_movie($dvdPlayer,  $movieDisc)      {          $this-­‐>setPlayer($dvdPlayer);          $this-­‐>playMovie($movieDisc);   !        $dvdPlayer-­‐>playDisc($movieDisc)                              -­‐>shouldHaveBeenCalled();      }   }
  64. 64. SET UP & TEAR DOWN class  CinemaSpec  extends  ObjectBehavior   {          /**            *  @param  BoxOffice  $boxOffice            */          function  let($boxOffice)          {                  $this-­‐>beConstructedWith($boxOffice);          }   !        function  letGo()          {                  $this-­‐>tellPeopleToGoHome();          }   }
  65. 65. BUT…
  66. 66. HOW TO ‘DESIGN’?
  67. 67. THREE RULES OF TDD 1. 2. 3. WRITE NO PRODUCTION CODE EXCEPT 
 TO PASS A FAILING TEST WRITE ONLY ENOUGH OF A TEST 
 TO DEMONSTRATE A FAILURE WRITE ONLY ENOUGH PRODUCTION 
 CODE TO PASS A TEST
  68. 68. 4 RULES OF SIMPLE DESIGN 1. 2. 3. 4. Passes all the tests Express every idea we need to express Contains no duplication Minimized the number of classes, methods and other moving parts
  69. 69. SMELLS 1. 2. 3. 4. CODE SMELLS TEST SMELLS DRY SMELLS …and others
  70. 70. And?
  71. 71. QUICK START {          "require-­‐dev":  {                  "phpspec/phpspec":  "2.0.*@dev"          },          "config":  {                  "bin-­‐dir":  "bin"          },          "autoload":  {"psr-­‐0":  {"":  "src"}}   } http://phpspec.net/
  72. 72. THANK YOU! ? JOIND.IN/10130

×