behavior & specification driven development in php - #openwest

94
Behavior & Specication Driven Development in PHP Presented by Joshua Warren

Upload: joshua-warren

Post on 15-Aug-2015

582 views

Category:

Technology


1 download

TRANSCRIPT

Behavior & Specification Driven Development in PHP

Presented by Joshua Warren

OR:

I heard you like to code, so let’s write code that writes code while

you code.

About Me

PHP DeveloperWorking with PHP since 1999

Founder & CEOFounded Creatuity in 2008

PHP Development Firm

Focused on the Magento platform

Tink, a Creatuity shareholder

JoshuaWarren.com

@JoshuaSWarren

IMPORTANT!

• joind.in/14065

• Download slides

• Post comments

• Leave a rating!

What You Need To Know

ASSUMPTIONS

Today we assume you’re a PHP developer.

That you are familiar with test driven development.

And that you’ve at least tried PHPUnit, Selenium or another testing tool.

BDD - no, the B does not stand for beer, despite what a Brit might tell you

Behavior Driven Development

Think of BDD as stepping back a level from TDD.

TDD generally deals with functional units.

BDD steps back a level to consider complete features.

In BDD, you write feature files in the form of user stories that you test against.

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"

Behat

We implement BDD in PHP with a tool called Behat

Behat is a free, open source tool designed for BDD and PHP

behat.org

SpecBDD - aka, Testing Tongue Twisters

Specification Behavior Driven Development

Before you write a line of code, you write a specification for how that code should work

Focuses you on architectural decisions up-front

PHPSpec

Open Source tool for specification driven development in PHP

www.phpspec.net

Why Use Behat and PHPSpec?

These tools allow you to focus exclusively on logic

Helps build functional testing coverage

Guides planning and ensuring that all stakeholders are in agreement

Let’s Build Something!

… what we’re building …

Setting up Our Project

Setup a Laravel 5 project

Run composer require —dev

behat/behat

behat/mink

behat/mink-extensions

laracasts/behat-laravel-extension

phpspec/phpspec

benconstable/phpspec-laravel

Run:

vendor/bin/behat —init

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

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

Behat’s written code for us!

/features/bootstrap/FeatureContext.php

/** * @Given I am not logged in as :arg1 */public function iAmNotLoggedInAs($arg1){ throw new PendingException(); }

Behat writes just enough to get us show us where to add our logic.

Behat expects us to add logic to this function to detect the user is not logged in.

Before we do that, let’s finish out our feature file.

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"

Run vendor/bin/behat —append-snippets one more time

Now, let’s fill in the logic Behat needs us to add.

/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); }

We run vendor/bin/behat once more

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

A perfect failure!

These failures show us that Behat is testing our app properly, and now we just need to write the

application logic.

Specifications

Now we write specifications for how our Fitbit class should work.

These specifications should provide the logic to deliver the results that Behat is testing for.

vendor/bin/phpspec describe Fitbit

Specification for Fitbit created in <project root>/spec/FitbitSpec.php

PHPSpec generates a basic spec file for us

spec/FitbitSpec.phpnamespace spec; use PhpSpec\ObjectBehavior; use Prophecy\Argument; class FitbitSpec extends ObjectBehavior{ function it_is_initializable() { $this->shouldHaveType('Fitbit'); } }

This default spec tells PHPSpec to expect a class named Fitbit.

Now we add a bit more to the file so PHPSpec will understand what this class should do.

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]); }

Now we run PHPSpec once more…

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)

Lots of failures…

But wait a second - PHPSpec prompts us!

Do you want me to create `Fitbit` for you? [Y/n]

PHPSpec will create the class and the methods for us!

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}

And now, the easy part…

Implementation

Implement logic in the new Fitbit class in the locations directed by PHPSpec

Tie that logic into views in our application.

Once we’re done with the implementation, we move on to…

Testing

Once we’re done, running phpspec run should return green

Once phpspec returns green, run behat, which should return green as well

We now know that our new feature is working correctly without needing to open a web browser

PHPSpec gives us confidence that the application logic was implemented correctly.

Behat gives us confidence that the feature is being displayed properly to users.

Success!

The purpose of this talk is to get you hooked on Behat & PHPSpec and show you how easy it is to

get started.

Behat and PHPSpec are both powerful tools

PHPSpec can be used at a very granular level to ensure your application logic works correctly

Next week, setup Behat and PHPSpec on one of your projects and take it for a quick test by

implementing one short feature.

Keep In Touch!

• joind.in/14065

• @JoshuaSWarren

• JoshuaWarren.com