2. About Me
• Marcus Moore
• San Diego, CA
• Diego Dev Group
• San Diego PHP User Group co-organizer
2
3. Overview
• My history with Behavior Driven Development
• Behavior Driven Development
• Behavior Driven Development and Laravel
3
4. My History with BDD
• When I worked at a small school
• Gathering requirements was easy!
4
5. My History with BDD
• Working for an agency...
• Requirement gathering got harder...
• Many clients with many communication styles
• "Who has solved this?"
5
6. Behavior Driven Development
• Extension of Test Driven Development (TDD)
• BDD works closely with Unit Testing
• BDD is not about testing
• Helps you build the right thing
6
7. Communication is hard
• Ambiguities arise
• Assumptions are made
• Rework becomes inevitable
7
8. BDD's Goals
• Close communication gap between all stakeholders using
real examples
• Establish a shared understanding of the desired outcome
• Eliminate "rework"
8
10. Discovery
• Most important part!
• Enables stakeholders to have focused conversations
• Fills knowledge gaps
• Develops an understanding of how the software should
function using real examples
10
11. Methods of Discovery
• Discovery Workshops
• Example Mapping
• Event Storming
• etc...
11
12. Discovery Workshops
• AKA the Three Amigos
• Short and frequent meetings
• Different people with different perspectives
12
13. Three Amigos
1. Business Person (Product Owner)
• Determines "what"
• Expresses the user stories
2. Developer
• Determines "how"
• Looks for details and potential roadblocks
3. Quality Assurance
• Come up with the "what if's"
• Tries to determine what will break
13
15. Formulation
• Documentation of the concrete examples
• Written in natural language syntax
• Readable by humans and software
• .feature files
• Gherkin
15
16. Gherkin
• Tells the Story via a narrative
• Easy for non-technical people to read
16
17. Feature: Requesting rides
As a verified user
I want to request a ride
So that I can get to my destination on time
Rule: Unverified users cannot request rides
Rule: User cannot request ride for more than 5 people
Scenario: A user requests a ride for 4 people
Given I am a verified user
And there is a van with 5 seats nearby
And there is a car with 3 seats next to me
When I request a ride for 4 people
Then I should see I am being connected to the van
17
18. Given - Set the state of the world
Given I am a verified user
And there is a van with 5 seats nearby
And there is a car with 3 seats next to me
18
19. When - Interact with the application
When I request a ride for 4 people
19
20. Then - Check the outcome of the interaction
Then I should see I am being connected to the van
20
21. Feature: Requesting rides
As a verified user
I want to request a ride
So that I can get to my destination on time
Rule: Unverified users cannot request rides
Rule: User cannot request ride for more than 5 people
Scenario: A user requests a ride for 4 people
Given I am a verified user
And there is a van with 5 seats nearby
And there is a car with 3 seats next to me
When I request a ride for 4 people
Then I should see I am being connected to the van
21
22. Formulation Results
• Common terminology solidified
• Shared understanding is documented in feature files
• New people can understand the application
22
23. Automation
• Start to implement the features with BDD and TDD
• Double-Loop Workflow
• Implement the features with Behat
23
24. Behat
• The go-to BDD Framework for PHP
• Implementation of Cucumber
24
26. Installation and Setup
• Install via Composer
• vendor/bin/behat !"init
• Add your feature files to /features
• vendor/bin/behat !"append-snippets
26
27. Feature: Requesting rides
As a verified user
I want to request a ride
So that I can get to my destination on time
Rule: Unverified users cannot request rides
Rule: User cannot request ride for more than 5 people
Scenario: A user requests a ride for 4 people
Given I am a verified user
And there is a van with 5 seats nearby
And there is a car with 3 seats next to me
When I request a ride for 4 people
Then I should see I am being connected to the van
27
28. /**
* @Given I am a verified user
"#
public function iAmAVerifiedUser()
{
throw new PendingException();
}
28
29. /**
* @Given I am a verified user
"#
public function iAmAVerifiedUser()
{
$this"$actingUser = factory(User"%class)
"$state('verified')
"$create();
$this"$userLocation = [
'latitude' "& '32.7',
'longitude' "& '-117.1',
];
}
29
35. /**
* @And there is a van with :arg1 seats nearby
!"
public function thereIsAVanWithSeatsNearby($arg1)
{
throw new PendingException();
}
35
36. /**
* @And there is a van with :numberOfSeats seats nearby
!"
public function thereIsAVanWithSeatsNearby($numberOfSeats)
{
$this!#createVan($numberOfSeats, $distanceFromUser = 3);
}
36
37. /**
* @And there is a car with :numberOfSeats seats next to me
!"
public function thereIsACarWithSeatsNextToMe($numberOfSeats)
{
$this!#createCar($numberOfSeats, $distanceFromUser = 1);
}
37
39. Scenario: A user requests a ride for 4 people
Given I am a verified user
And there is a van with 5 seats nearby
And there is a car with 3 seats next to me
When I request a ride for 4 people
Then I should see I am being connected to the van
39
40. Scenario: A user requests a ride for 4 people
Given I am a verified user
And there is a "van" with "5" seats "nearby"
And there is a "car" with "3" seats "next to me"
When I request a ride for 4 people
Then I should see I am being connected to the van
40
41. /**
* @Given there is a :arg1 with :arg2 seats :arg3
!"
public function thereIsAWithSeats($arg1, $arg2, $arg3)
{
throw new PendingException();
}
41
42. /**
* @Given there is a :typeOfVehicle with :numberOfSeats seats :distanceFromUser
!"
public function thereIsAWithSeatsNearby($typeOfVehicle, $numberOfSeats, $distanceFromUser)
{
$distance = 3;
if ($distanceFromUser !!# 'next to me') {
$distance = 1;
}
$this!$vehicles[$typeOfVehicle] = $this!$createVehicle($typeOfVehicle, $numberOfSeats, $distance);
}
42
43. /**
* @When I request a ride for :numberOfPeople people
!"
public function iRequestARideForPeople($numberOfPeople)
{
$this!#response = $this!#actingAs($this!#actingUser)
!#json(
'POST',
'/api/get-ride',
[
'location' !% $this!#userLocation,
'number_of_seats' !% $numberOfPeople
]
);
}
43
44. !" Controller does some work to match user and driver
!" Good time to TDD a service!
return response()!#json([
'message' !$ $closestVehicle!#driver . ' will pick you up soon!',
]);
44
45. /**
* @Then I should see I am being connected to the van
!"
public function iShouldSeeIAmBeingConnectedToTheVan()
{
$messageFromResponse = $this!#response!#decodeResponseJson('message');
$nameOfVanDriver = $this!#vehicles['van']['driver'];
$this!#assertTrue(Str!$contains($messageFromResponse, $nameOfVanDriver));
}
45