4. Set Up
For instant set up:
1) Copy code into a new vhost with the web root
pointing at the ‘public’ folder.
2) Uncomment line 13 in:
tests/acceptance/features/bootstrap/UIContext.php
3) Install Sahi from the misc folder.
Saturday, 29 October 11
5. Set Up
Goto: tests/acceptance/
If setting up today run the Behat command using
behat.phar
eg: php behat.phar --tags demo1
If you have previously set up, run the
behat command
eg: behat --tags demo1
Saturday, 29 October 11
6. Me
Software Engineer
PHP Developer
Sky Bet
PHP / MySQL Stack
PHPUnit / Selenium / Behat
Saturday, 29 October 11
7. Roadmap
•Intro To Behaviour Driven Development
•Introducing Behat
•Gherkin & Steps
•API / Service Layer Testing
•UI Testing
•Phabric - Dynamic Fixture Creation
Saturday, 29 October 11
8. joind.in
http://joind.in/talk/view/4328
Saturday, 29 October 11
21. Feature Files
Feature: Home Page
When visiting the PHPCon site
As a site visitor
I need to be able to see what
` conferences are coming up
Saturday, 29 October 11
Name of test
Description of test
22. Scenarios
Scenario: Get all conferences
Given there is conference data in the database
When I go to the homepage
Then I should see three conferences in a table
Saturday, 29 October 11
Scenario.
Multiple scenarios in a single feature file
23. Scenarios
Given
(Some Context)
When
(Some Event)
Then
(The Outcome)
Saturday, 29 October 11
Keywords.
Always follow the same formula
24. Given
(Some Context)
Given there is conference data in the database
Saturday, 29 October 11
Sets up some state or context
25. When
(Some Event)
When I go to the homepage
When I use the findConferences method
When I am on "/index.php"
When I fill in "search-text" with "PHP"
Saturday, 29 October 11
Executes whatever it is your testing.
A http call, a method invocation, a page load
26. Then
(The Outcome)
Then I should see three conferences in a table
Then I should get a array of three conferences
Then I should see "PHPNW"
Saturday, 29 October 11
An assertion.
Has it worked?
Are we seeing what we expect to see.
27. ConferenceService.feature
Feature: ConferenceService Class
In order to display conferences on
PHPCon site
As a developer
I need to be able to retrieve conferences
Scenario: Get all conferences
Given there is conference data in the database
When I use the findConferences method
Then I should get a array of three conferences
AND it should contain the conference “PHPNW”
Saturday, 29 October 11
Written By our TESTERS - Fed In From BAs
How is this feature executed?
Each step is reusable!
MENTION PHP METHODS + ANNOTATIONS!!!!
28. Class Methods & Annotations
Saturday, 29 October 11
Written By our TESTERS - Fed In From BAs
How is this feature executed?
Each step is reusable!
MENTION PHP METHODS + ANNOTATIONS!!!!
29. / Everybody Stand Back /
Behat Knows Regular Expressions
Saturday, 29 October 11
PHP Annotations used to map steps to lines
Behat supplies regex.
30. Demo One
Behat’s - Regex Fu
Saturday, 29 October 11
35. Fill in the Feature Context File
public function __construct(array $parameters)
{
$params = array(
'user' => $parameters['database']['username'],
'password' => $parameters['database']['password'],
'driver' => $parameters['database']['driver'],
'path' => $parameters['database']['dbPath'],
);
$con = DoctrineDBALDriverManager::getConnection($params);
$confMapper = new PHPConConferenceMapper($con);
$confService = new PHPConConferenceService($confMapper);
$this->service = $confService;
}
Saturday, 29 October 11
The Feature context file
- Ever feature gets a instance. Set up some
resources.
- Set up the object to test - similar to PHPUnit’s set
up method.
36. Fill in the Feature Context File
/**
* @Given /^there is conference data in the database$/
*/
public function thereIsConferneceDataInTheDatabase()
{
$fileName = self::$dataDir .
'sample-conf-session-data.sql';
self::executeQueriesInFile($fileName);
}
Saturday, 29 October 11
Remember - Given sets the state.
Loads an sql fixture to the DB.
37. Fill in the Feature Context File
/**
* @When /^I use the findConferences method$/
*/
public function iUseTheFindConferencesMethod()
{
$this->result = $this->service->findConferences();
}
Saturday, 29 October 11
Remember - When executes the thing you want to
test.
38. Fill in the Feature Context File
/**
*@Then /^I should get an array of (d+) conferences$/
*/
public function iShouldGetAnArrayOfConferences
($numberOfCons)
{
assertInternalType('array', $this->result);
assertEquals($numberOfCons, count($this->result));
}
Saturday, 29 October 11
Remember - This verifies the output
Also - identified a number. Passes the number into
the method.
39. /**
* @Then /^it should contain the
* conference "([^"]*)"$/
*/
public function itShouldContainTheConference
($confName)
{
$names = array();
foreach($this->result as $conf)
{
$names[$conf->getName()] = true;
}
if(!array_key_exists($confName, $names))
{
throw new Exception("Conference "
. $confName . " not found");
}
}
Saturday, 29 October 11
46. What about the UI?
Saturday, 29 October 11
We’ve covered testing a service class. But how do you test the UI?
47. Mink
Saturday, 29 October 11
Part of the Behat Project.
A abstraction over a number of different browser testing tools.
48. Mink
Goutte Sahi
Zombie.js
Saturday, 29 October 11
Goutte - headless browser
Sahi - like selenium
Zombie.js -
49. Extend Mink Context
Includes predefined steps
Use Bundled steps to create
higher level abstractions.
Saturday, 29 October 11
50. Back To:
My Amazing PHP Conference
Website!
Saturday, 29 October 11
We need a UI to test
introducing.....
51. Example
Using Minks Bundled Steps
Scenario: View all conferences on the homepage
Given there is conference data in the database
When I am on "/index.php"
Then I should see "PHPNW" in the ".conferences" element
And I should see "PHPUK" in the ".conferences" element
And I should see "PBC11" in the ".conferences" element
Saturday, 29 October 11
This is ok - but ties the feature to your implementation.
52. Link
FeatureContext.php
to
UIContext.php
Saturday, 29 October 11
This is ok - but ties the feature to your implementation.
53. class FeatureContext
public function __construct(array $parameters)
{
$this->useContext('subcontext_alias',
new UIContext($parameters));
! // REST OF FEATURE CONSTRUCTOR
}
# features/bootstrap/UIContext.php
use BehatBehatContextClosuredContextInterface,
BehatBehatContextBehatContext,
BehatBehatExceptionPendingException;
use BehatGherkinNodePyStringNode,
BehatGherkinNodeTableNode;
require_once 'mink/autoload.php';
class UIContext extends BehatMinkBehatContextMinkContext
{
}
Saturday, 29 October 11
1) Linking feature files
2) All steps included ‘out the box’
54. Demo Three
A Behat UI Test (Using Mink + Goutte)
Saturday, 29 October 11
This is ok - but ties the feature to your implementation.
55. Exercise Two
Testing the UI with Mink and
the headless browser Goutte.
Saturday, 29 October 11
56. Exercise Two
Open the PDF in the sources folder.
Read through Section Two.
Start Coding :)
Saturday, 29 October 11
57. Abstracting your scenario
Scenario: View all conferences on the homepage
Given there is conference data in the database
When I am on the "home" page
Then I should see "PHPNW" in the "conferences table”
And I should see "PHPUK" in the "conferences table”
And I should see "PBC11" in the "conferences table”
Saturday, 29 October 11
58. Mink Feature Context
class UIContext extends BehatMinkBehatContext
MinkContext
{
protected $pageList = array(
"home" => '/index.php');
protected $elementList = array(
"conferences table" => '.conferences');
Saturday, 29 October 11
A simple abstraction that makes a map of pages >
urls and elements > css selectors.
Example of step delegation.
Now you never change the feature file. Just steps.
59. /**
* @When /^I am on the "([^"]*)" page$/
*/
public function iAmOnThePage($pageName) {
if(!isset($this->pageList[$pageName])) {
throw new Exception(
'Page Name: not in page list');
}
$page = $this->pageList[$pageName];
return new When("I am on "$page"");
}
Saturday, 29 October 11
A simple abstraction that makes a map of pages >
urls and elements > css selectors.
Example of step delegation.
Now you never change the feature file. Just steps.
60. /**
* @Then /^I should see "([^"]*)" in the "([^"]*)"$/
*/
public function iShouldSeeInThe($text, $element) {
if(!isset($this->elementList[$element])) {
throw new Exception(
'Element: ' . $element . ‘not in element list');
}
$element = $this->elementList[$element];
return
new Then("I should see "$text" in the
"$element" element");
}
Saturday, 29 October 11
A simple abstraction that makes a map of pages >
urls and elements > css selectors.
Example of step delegation.
Now you never change the feature file. Just steps.
61. Demo Four
A Behat UI Test (Using Mink + Goutte)
UI implementation abstracted away from Gherkin.
Saturday, 29 October 11
This is ok - but ties the feature to your implementation.
62. Exercise Three
Abstracting the UI implementation away from the
Gherkin.
Saturday, 29 October 11
63. Exercise Three
Open the PDF in the sources folder.
Read through Section Three.
Start Coding :)
Saturday, 29 October 11
65. Back To:
My Amazing PHP Conference
Website!
Saturday, 29 October 11
We need a UI to test
introducing.....
66. Example
@javascript
Scenario: Use autocomplete functionality to
complete a input field
Given there is conference data in the
database
When I am on the "home" page
When I fill in "search-text" with "PHP"
And I wait for the suggestion box to appear
Then I should see "PHPNW"
Saturday, 29 October 11
Mention @tags
SO you need to test java script.
Headless browser isn’t suitable.
67. Great Reuse
@javascript
Scenario: Use autocomplete functionality to
complete a input field
Given there is conference data in the
database
When I am on the "home" page
When I fill in "search-text" with "PHP"
And I wait for the suggestion box to appear
Then I should see "PHPNW"
Saturday, 29 October 11
These are supplied by Mink. Woohoo!
REUSE
68. // In the UIContext class
/**
* @Given /^I wait for the suggestion box to appear$/
*/
public function iWaitForTheSuggestionBoxToAppear()
{
$this->getSession()->wait(5000,
"$('.suggestions-results').children().length > 0"
);
}
Saturday, 29 October 11
Get session - gets you mink
Wait,
Then execute jquery!
69. Demo Five
UI Testing With Sahi
Saturday, 29 October 11
This is ok - but ties the feature to your implementation.
76. Gherkin Tables
Scenario:
Given The following events exist
| Name | Date | Venue | Desc |
| PHPNW | 2011-10-08 09:00 | Ramada Hotel | Awesome conf! |
| PHPUK | 2012-02-27 09:00 | London Business Center | Quite good conf. |
Saturday, 29 October 11
77. Demo Five
Dynamic fixture creation with Phabric.
Saturday, 29 October 11
This is ok - but ties the feature to your implementation.
78. Case Study:
Behat at Sky Bet
Saturday, 29 October 11
Whats the problem we are solving.
Three elements of the team.
Delivering the product first time. Correctly.
79. The Problem
Saturday, 29 October 11
Whats the problem we are solving.
Three elements of the team.
Delivering the product first time. Correctly.
80. The Business
Analyst
Saturday, 29 October 11
BA / Product owner has all the knowledge
Write stories
82. The
Developer
Saturday, 29 October 11
Dev - write the code
Automate the process of testing if code meets the
requirements of a story
83. The Problem
Saturday, 29 October 11
Whats the problem we are solving.
Three elements of the team.
Delivering the product first time. Correctly.
84. BDD - Skybet Workflow
BA’s Write Stories
Testers Write Gherkin
Developers Write Steps + Code
Saturday, 29 October 11
Whats the problem we are solving.
Three elements of the team.
Delivering the product first time. Correctly.
85. BDD - Skybet Workflow
Less Defects
Fewer times through this cycle
Saturday, 29 October 11
Whats the problem we are solving.
Three elements of the team.
Delivering the product first time. Correctly.
86. The Place Of Acceptance &
Integration Tests
Saturday, 29 October 11
Whats the problem we are solving.
Three elements of the team.
Delivering the product first time. Correctly.
88. A whole world of trouble.
Saturday, 29 October 11
Takes a long time to run,
Harder to implement, when they break you have to do this again!
not as reassuring!
89. joind.in
http://joind.in/talk/view/4328
Saturday, 29 October 11