IT SHOULD! BDD IN PRACTICE
May 10, 2015
IT SHOULD!BDD IN PRACTICE
BEHAVIOR DRIVEN DEVELOPMENT=
TEST DRIVEN DEVELOPMENTexcept it's done right
TDDIS
CODE-CENTRICWHILE
BDDIS
COMMUNICATION-CENTRIC
IT'S LIKE COKE
PEPSI =
COCA-COLAexcept it's done right
BUT THIS IS NOT ABOUT WHAT BDD MEANS
THIS IS ALL ABOUT
TOOLS
AND ...
THE MURDER ON THE ORIENT EXPRESS
MA'AM! CAN YOU TEST WHO YOU SAW?"What do you mean test? I can describe it if you like" - Ma'am
./bin/phpspec desc Suspect
THE SUSPECTS"He was one of those types, you know" - Ma'am
namespace spec\OrientExpress\Suspect;
use PhpSpec\ObjectBehavior;use Prophecy\Argument;
class SuspectSpec extends ObjectBehavior{ function it_is_initializable() { $this->shouldHaveType('OrientExpress\Suspect\Suspect'); }}
THE SUSPECTS"Don't yell at me! Be a dear and help me out." - Ma'am
THE SUSPECTS
namespace spec\OrientExpress\Suspect;
use PhpSpec\ObjectBehavior;use Prophecy\Argument;
class SuspectSpec extends ObjectBehavior{ //...
function it_should_answer_questions() { $this->answer('Are you the killer?') ->shouldReturn('Nope, not me'); }}
THE SUSPECTS
THE SUSPECTSnamespace OrientExpress\Suspect;
class Suspect{ public function answer($question) { return 'Nope, not me'; }}
THE SUSPECTS - REFACTORING MADE EASY"Oh, I just remembered!" - Ma'am
namespace spec\OrientExpress\Suspect;
use PhpSpec\ObjectBehavior;use Prophecy\Argument;
class SuspectSpec extends ObjectBehavior{ // ... function it_should_not_confess_to_wrong_questions_if_guilty() { $this->setGuilty(true); $this->answer('Are you the killer?') ->shouldReturn('Nope, not me'); }}
THE SUSPECTS - REFACTORING MADE EASY"Oh, I just remembered!" - Ma'am
namespace spec\OrientExpress\Suspect;
use PhpSpec\ObjectBehavior;use Prophecy\Argument;
class SuspectSpec extends ObjectBehavior{ // ...
function it_should_confess_to_key_question_if_guilty() { $this->setGuilty(true); $this->answer('It was you!') ->shouldReturn('Mmmkay I confess'); }}
THE SUSPECTSnamespace OrientExpress\Suspect;
class Suspect{ protected $keyQuestion = 'It was you!';
protected $guilty = false;
public function answer($question) { if ($this->guilty && $question == $this->keyQuestion) { return 'Mmmkay I confess'; }
return 'Nope, not me'; }
// ...}
SIR! CAN YOU DESCRIBE WHO SOLVED IT?
./bin/phpspec desc Detective
THE OLDSCHOOL DETECTIVE // Oppa PHPUnit style function testSolve() { // ... $crime = $this->getMock('OrientExpress\Crime\Crime', array('getSuspects')); $crime->expects($this->any()) ->method('getSuspects') ->will($this->returnValue(array($suspect1, $suspect2)); // NoOoOoooOoOoOoo!!! }
THE DETECTIVEclass DetectiveSpec extends ObjectBehavior{ // ... /** * @param OrientExpress\Crime\Crime $crime * @param OrientExpress\Suspect\Suspect $suspect1 * @param OrientExpress\Suspect\Suspect $suspect2 */ function it_should_be_able_to_solve_crimes($crime, $suspect1, $suspect2) { $crime->getSuspects() ->willReturn(array($suspect1, $suspect2)); $suspect1->answer('It was you!') ->willReturn('Nope, not me'); $suspect2->answer('It was you!') ->willReturn('Mmmkay I confess');
$this->solve($crime)->shouldReturn($suspect2); }}
THE DETECTIVEnamespace OrientExpress\Investigators;
use OrientExpress\Crime\Crime;
class Detective{ public function solve(Crime $crime) { foreach ($crime->getSuspects() as $suspect) { $answer = $suspect->answer('It was you!'); if (preg_match('/confess/', $answer)) { return $suspect; } } }}
WORKS AS DESCRIBED
WHAT ABOUT THE SCOTLAND YARD?
DOES THE POLICE FUNCTION PROPERLY?Feature: In order to know the crimes on orient express As a Scotland Yard API client I want to get access to the archives
DOES THE POLICE FUNCTION PROPERLY?Background: Given the following crimes exist: | name | | "Murder on the Orient Express" | And the following detectives exist: | name | | "Herculse Poirot" | And the following suspects exist: | name | | "Princess Dragomiroff" | | "Count Adrenyi" |
DOES THE POLICE FUNCTION PROPERLY?
Scenario: Getting data from the Scotland Yard's archives Given crime "Murder on the Orient Express" was solved by "Hercules Poirot" And crime "Murder on the Orient Express" had suspects: | name | | "Princess Dragomiroff" | | "Count Adrenyi" | When I send GET request to "/api/crimes/ORIENT_EXPRESS_CRIME_ID" Then the response should contain json: """ { "crime": { "name": "Murder on the Orient Express", "detective": { "name": "Hercules Poirot" }, "suspects": [ { "name": "Princes Dragomiroff" }, { "name": "Count Adrenyi" } ] } } """
WHY IS THIS SO IMPORTANT?BECAUSE EVERY CODE TELLS A STORY
OR AT LEAST
IT SHOULD!
?PhpSpec: Behat:
Specs:
ABOUT MEKarol Sójko
Lead Software Architect @
Twitter: Github:
https://github.com/phpspec/phpspechttps://github.com/Behat/Behat
https://github.com/karolsojko/bdd-in-practice
The Comet Cult
@karolsojkokarolsojko