acceptance & integration testing with behat (phpnw2011)
DESCRIPTION
The slides from my talk 'Acceptance and integration Testing Using Behat'. Given at PHPNW11 08/10/11.TRANSCRIPT
Acceptance & Integration
Testing Using Behat
Ben WaineEmail: [email protected]
Twitter: @bwaine
Sunday, 9 October 11
Roadmap•Intro To Behaviour Driven Development
•Problems We Are Trying to solve at Sky With BDD
•Behat
•API Testing with Behat
•UI Testing with Behat
•Data Driven Testing
•Is Behat solving our problem?
Sunday, 9 October 11
Me
Sky BetPHP / MySQL Stack
PHPUnit / Selenium / Behat
Software EngineerPHP Developer
Sunday, 9 October 11
BehaviourDriven Development
(BDD)
Sunday, 9 October 11
Behaviour-driven development (BDD) takes the position that you can turn an idea for a requirement into implemented, tested, production-ready code simply and effectively, as long as .... everyone knows what’s going on.
- Dan North
Sunday, 9 October 11
- Drinkwater et al 2011
Writing tests first in a customer friendly language
Sunday, 9 October 11
The Problem
Sunday, 9 October 11
The Business Analyst
Sunday, 9 October 11
The Tester
Sunday, 9 October 11
The Developer
Sunday, 9 October 11
The Problem
Sunday, 9 October 11
Behat
Sunday, 9 October 11
Resistance is futile.......Sunday, 9 October 11
What Does It Test?
ScriptsAPI’s
Web PagesModels
Sunday, 9 October 11
Integration Testing !=
Unit Testing
Sunday, 9 October 11
Anatomy Of A Behat Test
Sunday, 9 October 11
Sunday, 9 October 11
Sunday, 9 October 11
My Amazing PHP Conference Website!
Sunday, 9 October 11
Writing Behat Tests
$ben > cd /path/to/projects/tests$ben > behat --init
Sunday, 9 October 11
Writing Behat Tests
Sunday, 9 October 11
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
Sunday, 9 October 11
ScenariosScenario: 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
Sunday, 9 October 11
ScenariosGiven
(Some Context)
When (Some Event)
Then (The Outcome)
Sunday, 9 October 11
Given (Some Context)
Given there is conference data in the database
Sunday, 9 October 11
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"
Sunday, 9 October 11
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"
Sunday, 9 October 11
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”
Sunday, 9 October 11
Class Methods & Annotations
Sunday, 9 October 11
/ Everybody Stand Back /
Behat Knows Regular Expressions
Sunday, 9 October 11
Sunday, 9 October 11
Sunday, 9 October 11
Sunday, 9 October 11
Sunday, 9 October 11
Copy and paste these methods into FeatureContext.php
Sunday, 9 October 11
Sunday, 9 October 11
Sunday, 9 October 11
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 = \Doctrine\DBAL\DriverManager::getConnection($params);
$confMapper = new \PHPCon\Conference\Mapper($con); $confService = new \PHPCon\Conference\Service($confMapper);
$this->service = $confService; }
Sunday, 9 October 11
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); }
Sunday, 9 October 11
Fill in the Feature Context File
/** * @When /^I use the findConferences method$/ */ public function iUseTheFindConferencesMethod() { $this->result = $this->service->findConferences();
}
Sunday, 9 October 11
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)); }
Sunday, 9 October 11
/** * @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"); } }
Sunday, 9 October 11
Ready to run the tests again.....
Sunday, 9 October 11
Sunday, 9 October 11
Sunday, 9 October 11
Failing Test
Sunday, 9 October 11
Add some application code.....
Sunday, 9 October 11
Sunday, 9 October 11
Sunday, 9 October 11
Sunday, 9 October 11
Passing Test!
Sunday, 9 October 11
What about the UI?
Sunday, 9 October 11
Mink
Sunday, 9 October 11
Mink
Goutte Sahi
Zombie.js
Sunday, 9 October 11
Extend Mink Context
Use Bundled steps to create higher level abstractions.
Includes predefined steps
Sunday, 9 October 11
Back To: My Amazing PHP Conference
Website!
Sunday, 9 October 11
Example
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
Using Minks Bundled Steps
Sunday, 9 October 11
# features/bootstrap/UIContext.php
use Behat\Behat\Context\ClosuredContextInterface, Behat\Behat\Context\BehatContext, Behat\Behat\Exception\PendingException;
use Behat\Gherkin\Node\PyStringNode, Behat\Gherkin\Node\TableNode;
require_once 'mink/autoload.php';
class UIContext extends Behat\Mink\Behat\Context\MinkContext{
}
class FeatureContext
public function __construct(array $parameters) { $this->useContext('subcontext_alias', new UIContext($parameters));
! // REST OF FEATURE CONSTRUCTOR
}
Sunday, 9 October 11
Sunday, 9 October 11
Sunday, 9 October 11
Sunday, 9 October 11
Sunday, 9 October 11
Powerful Headless UI Testing Out The Box
Sunday, 9 October 11
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
Abstracting your scenario
Sunday, 9 October 11
class UIContext extends Behat\Mink\Behat\Context\MinkContext{ protected $pageList = array( "home" => '/index.php'); protected $elementList = array( "conferences table" => '.conferences');
Mink Feature Context
Sunday, 9 October 11
/** * @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\""); }
Sunday, 9 October 11
/** * @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 then\"$element\" element"); }
Sunday, 9 October 11
Javascript Testing with.....
Sahi
Sunday, 9 October 11
Back To: My Amazing PHP Conference
Website!
Sunday, 9 October 11
@javascriptScenario: 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"
Example
Sunday, 9 October 11
@javascriptScenario: 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"
Great Reuse
Sunday, 9 October 11
// 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" ); }
Sunday, 9 October 11
Sunday, 9 October 11
Data
Sunday, 9 October 11
SQL Fixture
Sunday, 9 October 11
Phabric
Sunday, 9 October 11
Phabric
Inserting Data From Gherkin Tables
INSERT INTO event `Name`, `Date`, `Venue`, `Desc`VALUE(‘PHPNW’, ‘2011-10-08 09:00’, ‘Ramada Hotel’, ‘Awesome Conf!’)
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. |
Sunday, 9 October 11
Phabric
Transforming Table Headings to DB col names
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. |
INSERT INTO event `name`, `date`, `venue`, `description`VALUE(‘PHPNW’, ‘2011-10-08 09:00’, ‘Ramada Hotel’, ‘Awesome Conf!’)
Sunday, 9 October 11
Phabric
Transforming Table data using user defined callbacks
Scenario: Given The following events exist | Name | Date | Venue | Desc | | PHPNW | 08/10/2011 09:00 | Ramada Hotel | Awesome conf! | | PHPUK | 27/02/2012 09:00 | London Business Center | Quite good conf. |
INSERT INTO event `name`, `date`, `venue`, `description`VALUE(‘PHPNW’, ‘2011-10-08 09:00’, ‘Ramada Hotel’, ‘Awesome Conf!’)
Sunday, 9 October 11
PhabricInserting Relational Data
Scenario: Given the following sessions exist | Session Code | name | time | description | | BDD | BDD with behat | 12:50 | TDD is cool! | | CI | Continous Integration | 13:30 | Integrate this! | And the following attendees exist | name | | Jack The Lad | | Simple Simon | | Peter Pan | And the following votes exist | Attendee | Session Code | Vote | | Jack The Lad | BDD | UP | | Simple Simon | BDD | UP | | Peter Pan | BDD | UP |
Sunday, 9 October 11
Back To Our Problem At Sky
Sunday, 9 October 11
Balance.
Sunday, 9 October 11
A whole world of trouble.
Sunday, 9 October 11
Questions?
Sunday, 9 October 11
Behat Github Page: https://github.com/Behat/Behat
Mink On Github: https://github.com/Behat/Mink
Website: http://behat.org/
Phabric On Github: https://github.com/benwaine/Phabric
Links
joind.in: http://joind.in/3592 Sunday, 9 October 11