BDD For Zend Framework With PHPSpec
Upcoming SlideShare
Loading in...5
×
 

BDD For Zend Framework With PHPSpec

on

  • 5,175 views

Talk delivered at PHP Barcelona Conference 2011. Using PHPSpec and Zend Tool together to demonstrate BDD in a PHP MVC context.

Talk delivered at PHP Barcelona Conference 2011. Using PHPSpec and Zend Tool together to demonstrate BDD in a PHP MVC context.

Statistics

Views

Total Views
5,175
Views on SlideShare
5,162
Embed Views
13

Actions

Likes
8
Downloads
55
Comments
0

3 Embeds 13

http://www.php-talks.com 10
http://www.linkedin.com 2
https://twitter.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

BDD For Zend Framework With PHPSpec BDD For Zend Framework With PHPSpec Presentation Transcript

  • BDD for with PHPSpec 29th October 2011 Marcello DuarteSaturday, 29 October 2011
  • whoami Marcello Duarte Head of Training @ Ibuildings UK Lead developer @ PHPSpec Twitter @_mdSaturday, 29 October 2011
  • In the beginning there was... TDD credits: http://www.flickr.com/photos/improveit/1574023621Saturday, 29 October 2011
  • They saw that it was goodSaturday, 29 October 2011
  • $thou->shalt->test credits: http://www.flickr.com/photos/36829113@N05/3392940179/Saturday, 29 October 2011
  • BDD credits: http://www.flickr.com/photos/psd/424257767/Saturday, 29 October 2011
  • BDD A way of teaching TDD credits: http://www.flickr.com/photos/psd/424257767/Saturday, 29 October 2011
  • What to test? H Where to begin? ow m uchSaturday, 29 October 2011 to test i ? What to call my test? How do I name my test? n one go?
  • BDD credits: http://www.flickr.com/photos/psd/424257767/Saturday, 29 October 2011
  • BDD Offers a common language credits: http://www.flickr.com/photos/psd/424257767/Saturday, 29 October 2011
  • business user developerSaturday, 29 October 2011
  • business user developer behaviorSaturday, 29 October 2011
  • Saturday, 29 October 2011 © Manuscripts and Archives, Yale University Library. Sapir-Whorf hypothesis
  • Language to express truth vs...Saturday, 29 October 2011
  • Language to discover truthSaturday, 29 October 2011
  • Language influence thoughtSaturday, 29 October 2011
  • BDD credits: http://www.flickr.com/photos/psd/424257767/Saturday, 29 October 2011
  • BDD A way to discover what is useful to deliver credits: http://www.flickr.com/photos/psd/424257767/Saturday, 29 October 2011
  • Saturday, 29 October 2011
  • BDD Outside in Gherkin Behat PHPSpecSaturday, 29 October 2011
  • GherkinSaturday, 29 October 2011
  • Feature: Organizers can open a call for paper As an event organizer I want a way to publish a centralized cfp form So that it’s easier for speakers to submit Scenario: Creation form with valid attributes Given I am in on "call-for-papers/add" When I fill in the following: | event | PHPLondon Conference| | start_date | 2012-02-06 | | limit_abstract_wc | 500 | | why_you_field | 1 | | offer_hotel | 1 | | offer_travel | 0 | And I press "Create" Then I should see "The cfp was created successfully"Saturday, 29 October 2011
  • behat.orgSaturday, 29 October 2011
  • Saturday, 29 October 2011
  • words matterSaturday, 29 October 2011
  • $this->assertTrue(...Saturday, 29 October 2011
  • $this->assertTrue(... What am I going to test?Saturday, 29 October 2011
  • $report = new Report; $this->assertTrue($report instanceof Report);Saturday, 29 October 2011
  • / / $report = new Report; $this->assertTrue($report instanceof Report);Saturday, 29 October 2011
  • $employee->should->...Saturday, 29 October 2011
  • $employee->should->... What is the expected behavior?Saturday, 29 October 2011
  • Use Gherkin and Behat for specifying scenarios ∫ Use PHPSpec for specifying classesSaturday, 29 October 2011
  • expressivenessSaturday, 29 October 2011
  • $this->assertTrue($employee->reportsTo($manager)); $employee->should->reportTo($manager);Saturday, 29 October 2011
  • phpspec.netSaturday, 29 October 2011
  • Installing $ sudo pear channel-discover pear.phpspec.net $ sudo pear install --alldeps phpspec/PHPSpecSaturday, 29 October 2011
  • “Specification, not verification” (Uncle Bob) $this->assertEquals(0, $result); becomes $result->should->be(0);Saturday, 29 October 2011
  • class CalculatorTest becomes class DescribeCalculatorSaturday, 29 October 2011
  • function testAddWithNoArguments() becomes function itReturnsZeroWithNoArguments()Saturday, 29 October 2011
  • All together class DescribeStringCalculator extends PHPSpecContext { function itReturnsZeroWithNoArguments() { $calculator = $this->spec(new StringCalculator); $result = $calculator->add(); $result->should->be(0); } }Saturday, 29 October 2011
  • Hooks before() after() beforeAll() afterAll()Saturday, 29 October 2011
  • Setting initial state with before hook class DescribeStringCalculator extends PHPSpecContext { function before() { $this->calculator = $this->spec(new StringCalculator); } function itReturnsZeroWithNoArguments() { $result = $this->calculator->add(); $result->should->be(0); } }Saturday, 29 October 2011
  • class DescribeStringCalculator extends PHPSpecContext { private $calculator; function before() { $this->calculator = $this->spec(new StringCalculator); } function itReturnsZeroWithNoArguments() { $this->calculator->add()->should->equal(0); } function itReturnsTheBareNumber() { $this->calculator->add(42)->should->equal(42); } }Saturday, 29 October 2011
  • Formatters progress documentation html coming soon: junitSaturday, 29 October 2011
  • Progress Formatter $ phpspec StringCalculatorSpec.php -c .*.F Pending: String Calculator returns the bare number # Waiting to clarify the spec # ./spec/StringCalculatorSpec.php:19 Failures: 1) String Calculator returns the sum of space separate string expected 42, got 0 (using be()) # .spec/StringCalculatorSpec.php:28 2) StringCalculator returns the sum of any white space separated string Failure/Error: Just because Finished in 0.056134 seconds 4 examples, 1 failure, 1 pendingSaturday, 29 October 2011
  • HTML FormatterSaturday, 29 October 2011
  • Documentation FormatterSaturday, 29 October 2011
  • MatchersSaturday, 29 October 2011
  • be($match) equal($match) beEqualTo($match) beAnInstanceOf($match) beEmpty() beFalse() beGreaterThan($match) beGreaterThanOrEqualTo($match)Saturday, 29 October 2011
  • And more matchers...Saturday, 29 October 2011
  • beInteger() beLessThan($match) beLessThanOrEqualTo($match) beNull() beString() beTrue() throwException($match)Saturday, 29 October 2011
  • Predicate MatchersSaturday, 29 October 2011
  • $cell = $this->spec(new Cell); $cell->should->beAlive(); class Cell { protected $alive = true; public function isAlive() { return $this->alive; } ... }Saturday, 29 October 2011
  • $newNode = $this->spec(new Node); $newNode->shouldNot->haveChildren(); class Node { protected $children = array(); public function hasChildren() { return count($this->children) > 0; } ... }Saturday, 29 October 2011
  • Custom MatchersSaturday, 29 October 2011
  • PHPSpecMatcherdefine(reportTo, function($supervisor) { return array ( match => function($supportEngineer) use ($supervisor) { return $supportEngineer->reportsTo($supervisor); }, failure_message_for_should => function($supportEngineer) use ($supervisor) { return "expected " . $supervisor->getName() . " to report to " . $supervisor->getName(); } ); }); class DescribeSupportEngineer extends PHPSpecContext { ... function itAddsNewCourses() { $john = new Supervisor("John Smith"); $john->addToTeam($this->supportEngineer); $this->supportEngineer->should->reportTo($john); } }Saturday, 29 October 2011
  • PHPSpec &Saturday, 29 October 2011
  • Tool framework.zend.comSaturday, 29 October 2011
  • Installing $ sudo pear channel-discover pear.zfcampus.org $ sudo pear install zfcampus/zf $ zf create config $ vi ~/.zf.iniSaturday, 29 October 2011
  • .zf.ini php.include_path = ".:/usr/share/pear" basicloader.classes.1 = "Akrabat_Tool_DatabaseSchemaProvider" basicloader.classes.2 = "PHPSpec_Context_Zend_Tool_Provider_Phpspec" basicloader.classes.3 = "PHPSpec_Context_Zend_Tool_Provider_ModelSpec" basicloader.classes.4 = "PHPSpec_Context_Zend_Tool_Provider_ViewSpec" basicloader.classes.5 = "PHPSpec_Context_Zend_Tool_Provider_ControllerSpec" basicloader.classes.6 = "PHPSpec_Context_Zend_Tool_Provider_ActionSpec" basicloader.classes.7 = "PHPSpec_Context_Zend_Tool_Provider_Behat"Saturday, 29 October 2011
  • create a project $ zf create project callconf Creating project at /var/www/callconf Note: This command created a web project, for more information setting up your VHOST, please see docs/READMESaturday, 29 October 2011
  • initialize PHPSpec $ cd callconf $ zf generate phpspec create spec create spec/SpecHelper.php create spec/.phpspec create spec/models create spec/views create spec/controllersSaturday, 29 October 2011
  • initialize Behat $ zf generate behat +d features - place your *.feature files here +d features/bootstrap - place bootstrap scripts and static files here +f features/bootstrap/FeatureContext.php - place your feature related code hereSaturday, 29 October 2011
  • Saturday, 29 October 2011
  • ViewsSaturday, 29 October 2011
  • why specify the view?Saturday, 29 October 2011
  • Controller and model to the point Ensure we are focused on what matters Sustainable paceSaturday, 29 October 2011
  • create a view specSaturday, 29 October 2011
  • create a view spec $ zf create view-spec add CallForPapersSaturday, 29 October 2011
  • create a view spec $ zf create view-spec add CallForPapers Creating a view script in location /var/www/callconf/ application/views/scripts/call-for-papers/add.phtml Creating a spec at /var/www/callconf/spec/views/call-for- papers/AddSpec.phpSaturday, 29 October 2011
  • Saturday, 29 October 2011
  • Spec created by default <?php namespace CallForPapers; require_once __DIR__ . /../../SpecHelper.php; use PHPSpecContextZendView as ViewContext; class DescribeAdd extends ViewContext { function itRendersTheDefaultContent() { $this->render(); $this->rendered->should->contain(CallForPapers); $this->rendered->should->contain(add); } }Saturday, 29 October 2011
  • what behaviors can we describe in the view spec?Saturday, 29 October 2011
  • Variables we need assigned What content was rendered (We can use selectors)Saturday, 29 October 2011
  • Assigning Variables function itRendersTheTalkAbstract() { $marcello = $this->mock(Speaker, array(isVegetarian => true)); $this->assign(speaker, $marcello); $this->render(); $this->rendered->should->contain(diet restrictions: vegetarian); }Saturday, 29 October 2011
  • ControllersSaturday, 29 October 2011
  • create a controller specSaturday, 29 October 2011
  • create a controller spec $ zf create controller-spec CallForPapers add,createSaturday, 29 October 2011
  • create a controller spec $ zf create controller-spec CallForPapers add,create Creating a controller at /private/var/www/callconf/ application/controllers/CallForPapersController.php Creating an add action method in controller CallForPapers Creating an create action method in controller CallForPapers Creating a spec at /private/var/www/callconf/spec/ controllers/CallForPapersSpec.phpSaturday, 29 October 2011
  • Saturday, 29 October 2011
  • Spec created by default <?php require_once __DIR__ . /../SpecHelper.php; class DescribeCallForPapers extends PHPSpecContextZendController { function itShouldBeSuccessfulToGetAdd() { $this->get(call-for-papers/add); $this->response->should->beSuccess(); } }Saturday, 29 October 2011
  • what behaviors do we want to describe in the controller spec?Saturday, 29 October 2011
  • How do we want to route to its actions What view variables we need assigned What view we want renderedSaturday, 29 October 2011
  • Routing and assigning function itShouldRouteToTheAddAction() { $this->routeFor(array( controller => call-for-papers, action => add ))->should->be(/call-for-papers/add); } function itAssignsAddSubmissionFormVariable() { $this->get(/call-for-papers/add); $this->assigns(addSubmissionForm)->should->beAnInstanceOf( Application_Form_AddSubmissionForm ); }Saturday, 29 October 2011
  • ModelsSaturday, 29 October 2011
  • create a model specSaturday, 29 October 2011
  • create a model spec $ zf create model-spec Speaker name:string,email:stringSaturday, 29 October 2011
  • create a model spec $ zf create model-spec Speaker name:string,email:string Creating a model at /private/var/www/callconf/application/ models/Speaker.php Creating a db table at /private/var/www/callconf/ application/models/DbTable/Speakers.php Creating a mapper at /private/var/www/callconf/application/ models/SpeakerMapper.php Creating a spec at /private/var/www/callconf/spec/models/ SpeakerSpec.php Creating migration scripts at /private/var/www/callconf/db/ migrate/001-CreateSpeakersTable.php Updating project profile /private/var/www/ callconf/.zfproject.xmlSaturday, 29 October 2011
  • Saturday, 29 October 2011
  • Spec created by default<?phprequire_once __DIR__ . /../SpecHelper.php;use Application_Model_Speaker as Speaker;class DescribeSpeaker extends PHPSpecContext{ function before() { $this->validAttributes = array( name => value for name, email => value for email, ); } function itShouldCreateANewInstanceGivenValidAttributes() { $this->speaker = $this->spec(Speaker::create($this->validAttributes)); $this->speaker->should->beValid(); }}Saturday, 29 October 2011
  • what behaviors can we describe in the model spec?Saturday, 29 October 2011
  • Business logic Validation Spying results from data source operationsSaturday, 29 October 2011
  • Business Logicclass DescribeSpeaker extends PHPSpecContext{ function before() { $this->validAttributes = array( name => Marcello Duarte, email => marcello@ibuildings.com, diet_restriction => vegetarian, ); $this->speaker = $this->spec(Speaker::create($this->validAttributes)); } function itGetsExtraRatingPointsForTalkIfVegetarian() { $this->speaker->should->haveExtraPoints(); }}Saturday, 29 October 2011
  • Business Logicclass Speaker{ //... other methods function hasExtraPoints() { return stripos($this->getDietRestrictions(), vegetarian) !== false; }}Saturday, 29 October 2011
  • Real database hits?Saturday, 29 October 2011
  • Avoid Sometimes, for confidence When testing data access objectsSaturday, 29 October 2011
  • Dependency chainsSaturday, 29 October 2011
  • Dependencies can be hard to manageclass DescribeEvent extends PHPSpecContext{ function itDoesSomethingWhenYouHaveSpeakerAllocated() { $event = new Event( new Organizer(John Smith, new Organization(Ibuildings) ) ); $event->addSpeaker(new Speaker(Rowan), new Slot(’10:30’), new Room(A)); $event->addSpeaker(new Speaker(Ben), new Slot(’10:30’), new Room(B)); // specify expected behavior }}Saturday, 29 October 2011
  • Usually dependencies are replaced with doubles when writing specs We can use a framework like Mockery But if you really need the real thingSaturday, 29 October 2011
  • Object MotherSaturday, 29 October 2011
  • Dependencies can be hard to manageclass DescribeEvent extends PHPSpecContext{ function itDoesSomethingWhenYouHaveSpeakerAllocated() { $exampleEvent = ExampleEvent::newWithSimultaneousSpeakers(); // specify expected event behavior }}Saturday, 29 October 2011
  • Code duplication Too many methodsSaturday, 29 October 2011
  • Test Data BuilderSaturday, 29 October 2011
  • Is created with save “empty” objects Has a fluent interface Has a build methodSaturday, 29 October 2011
  • Dependencies can be hard to manageclass DescribeEvent extends PHPSpecContext{ function itDoesSomethingWhenYouHaveSpeakerAllocated() { $eventBuilder = new EventBuilder(); $organizerBuilder = new OrganizerBuilder(); $event = $eventBuilder->withOrganizer( $organizerBuilder->withOrganization()->build() )->withConflictingSpeakers() ->build(); // specify expected event behavior }}Saturday, 29 October 2011
  • phactory.orgSaturday, 29 October 2011
  • installingSaturday, 29 October 2011
  • installing $ sudo pear channel-discover pearhub.orgSaturday, 29 October 2011
  • installing $ sudo pear channel-discover pearhub.org $ sudo pear install pearhub/PhactorySaturday, 29 October 2011
  • Needs a Pdo connection Get from default adapterSaturday, 29 October 2011
  • Create a connection protected function _initPhactory() { Phactory::setConnection( Zend_Db_Table_Abstract::getDefaultAdapter()); return Phactory::getConnection(); }Saturday, 29 October 2011
  • Define table blueprints // spec/factories.php Phactory::define(speaker, array( name => John Smith, email => john@smith.com));Saturday, 29 October 2011
  • Create objects // in one of my specs $ben = Phactory::create(speaker, array(name => Rowan)); $rowan = Phactory::create(speaker, array(name => Ben)); // Phactory_Row objects echo $ben->name // prints BenSaturday, 29 October 2011
  • Questions? 223Saturday, 29 October 2011
  • Thank you! http://joind.in/4318 http://slidesha.re/tcGM93 Marcello Duarte @_md is hiring. Come talk to me. 224Saturday, 29 October 2011