Behavior & Specification Driven Development in PHP - #OpenWest
-
Upload
joshua-warren -
Category
Technology
-
view
583 -
download
1
Transcript of Behavior & Specification Driven Development in PHP - #OpenWest
Founder & CEOFounded Creatuity in 2008
PHP Development Firm
Focused on the Magento platform
Tink, a Creatuity shareholder
BDD - no, the B does not stand for beer, despite what a Brit might tell you
Behavior Driven Development
Graphic thanks to BugHuntress
BDD uses a ubiquitous language - basically, a language that business stakeholders, project managers, developers
and our automated tools can all understand.
Sample Behat Feature File
Feature: Laravel Test In order to demonstrate Laravel and Behat As a user I need to be able to visit the homepage of a new Laravel app Scenario: Homepage Given I am on the homepage Then I should see "Laravel 5"
Run composer require —dev
behat/behat
behat/mink
behat/mink-extensions
laracasts/behat-laravel-extension
phpspec/phpspec
benconstable/phpspec-laravel
Create /behat.yaml
default: extensions: Laracasts\Behat: ~ Behat\MinkExtension\ServiceContainer\MinkExtension: default_session: laravel laravel: ~
Create /phpspec.yamlsuites:
main:
namespace: App
psr4_prefix: App
src_path: app
extensions:
- PhpSpec\Laravel\Extension\LaravelExtension
features/fitbit.featureFeature: Fitbit IntegrationIn order to obtain Fitbit dataAs a userI need to be able to authenticate with Fitbit
Scenario: Not yet authenticated Given I am not logged in as “[email protected]” When I go to "/fitbit/" Then I should see "Please authenticate"
vendor/bin/behat —append-snippets
Scenario: Not yet authenticated:6 Given I am not logged in as “[email protected] When I go to "/fitbit/" Then I should see "Please authenticate" 1 scenario (1 undefined) 3 steps (1 undefined, 2 skipped) 0m0.48s (11.00Mb)
u features/bootstrap/FeatureContext.php - `I am not logged in as` definition added
/features/bootstrap/FeatureContext.php
/** * @Given I am not logged in as :arg1 */public function iAmNotLoggedInAs($arg1){ throw new PendingException(); }
features/fitbit.feature continuedScenario: I have authenticatedGiven I am logged in as “[email protected]” When I go to "/fitbit/"Then I should see "Welcome back"
Scenario: I have sleep dataGiven I am logged in as “[email protected]” When I go to "/fitbit/sleep/"Then I should see "Sleep Report"
/features/bootstrap/FeatureContext.php
/** * @Given I am not logged in as :email */public function iAmNotLoggedInAs($email) { // We completely log out // Destroy the previous session if (Session::isStarted()) { Session::regenerate(true); } else { Session::start(); } }
/features/bootstrap/FeatureContext.phppublic function iAmLoggedInAs($email) { // Destroy the previous session if (Session::isStarted()) { Session::regenerate(true); } else { Session::start(); } // Login the user and since the driver and this code now // share a session this will also login the driver session $user = User::where('email', $email)->firstOrFail(); Auth::login($user); // Save the session data to disk or to memcache Session::save(); // Hack for Selenium // Before setting a cookie the browser needs to be launched if ($this->getSession()->getDriver() instanceof \Behat\Mink\Driver\Selenium2Driver) { $this->visit('login'); } // Get the session identifier for the cookie $encryptedSessionId = Crypt::encrypt(Session::getId()); $cookieName = Session::getName(); // Set the cookie $minkSession = $this->getSession(); $minkSession->setCookie($cookieName, $encryptedSessionId); }
vendor/bin/behat…
Scenario: I have sleep data Given I am logged in as "[email protected]" When I go to "/fitbit/sleep/" Then I should see "Sleep Report" The text "Sleep Report" was not found anywhere in the text of the current page. (Behat\Mink\Exception\ResponseTextException)
--- Failed scenarios: features/fitbit.feature:6 features/fitbit.feature:11 features/fitbit.feature:16
These failures show us that Behat is testing our app properly, and now we just need to write the
application logic.
vendor/bin/phpspec describe Fitbit
Specification for Fitbit created in <project root>/spec/FitbitSpec.php
spec/FitbitSpec.phpnamespace spec; use PhpSpec\ObjectBehavior; use Prophecy\Argument; class FitbitSpec extends ObjectBehavior{ function it_is_initializable() { $this->shouldHaveType('Fitbit'); } }
spec/FitbitSpec.php continuedfunction it_connects_to_fitbit($email) { $this->connect($email)->shouldReturn('Success'); } function it_returns_sleep_data($email) { $this->sleepData($email)->shouldReturn([8, 8, 8, 8, 8]); }
vendor/bin/phpspec run 10 ! is initializable (142ms) class Fitbit does not exist. 15 ! connects to fitbit (100ms) class Fitbit does not exist. 20 ! returns sleep data class Fitbit does not exist.
---- broken examples
Fitbit 10 ! is initializable (142ms) class Fitbit does not exist.
Fitbit 15 ! connects to fitbit (100ms) class Fitbit does not exist.
Fitbit 20 ! returns sleep data class Fitbit does not exist.
1 specs 3 examples (3 broken)
This is very powerful with frameworks like Laravel and Magento, which have PHPSpec plugins that help PHPSpec know where class files should be
located.
Fitbit.php - class Fitbit {
function connect($email) { // TODO: write logic here} function sleepData($email) { // TODO: write logic here}
The purpose of this talk is to get you hooked on Behat & PHPSpec and show you how easy it is to
get started.
Next week, setup Behat and PHPSpec on one of your projects and take it for a quick test by
implementing one short feature.