A tutorial given at PHPNW15 - October 2nd 2015. All references and examples use the following repository and Vagrant VM environment: https://github.com/pavlakis/phpnw15-behat-tutorial
6. The environment
• Legacy code - ZF1 (1.10.6) tutorial by Rob Allen
(@akrabat)
• Basic LAMP box with Ubuntu 12.04, PHP 5.5,
MySQL 5.5
7. Getting started
(1) git clone git@github.com:pavlakis/phpnw15-behat-tutorial.git
(2) vagrant up
(3) Add the following to your hosts file:
192.168.42.200 dev.legacy.com test.legacy.com
15. Features & Scenarios
Behat tests live inside .feature files
Behat tests are called Scenarios
Behat Scenarios use the Gherkin language, which
allows us to write English statements.
16. Definitions
A statement from a scenario that maps to a PHP
method and identified through the method’s
doc-block.
For available definitions, run:
$ ./behat --config=/var/www/tests/behat/behat.yml -dl
19. “Scenario: The homepage loads”
Create file: album.feature
tests/behat/features/bootstrap/album.feature
20. “Scenario: The homepage loads”
Feature: Albums
I can create, edit and delete albums
Scenario: The homepage loads
Given I am on the homepage
Then I should see text matching "My Album"
tests/behat/features/bootstrap/album.feature
23. “Scenario: Page does not exist”
Feature: Albums
I can create, edit and delete albums
Scenario: The homepage loads
Given I am on the homepage
Then I should see text matching "My Album”
Scenario: Page does not exist
Given I …
Then I …
tests/behat/features/bootstrap/album.feature
25. “Scenario: I can create an album”
• Possible steps:
• Navigate to the “create” page
• Add artist
• Add album
• Submit form
26. “Scenario: I can create an album”
Feature: Albums
I can create, edit and delete albums
Scenario: The homepage loads
Given I am on the homepage
Then I should see text matching “My Album”
Scenario: Page does not exist
Given I …
Then I …
Scenario: I can create an album
Given I am on the homepage
And I follow …
tests/behat/features/bootstrap/album.feature
27. “Scenario: I can create an album”
tests/behat/features/bootstrap/album.feature
Guidance.
Use the following definitions:
And /^(?:|I )follow "(?P<link>(?:[^"]|")*)"$/
And /^(?:|I )fill in "(?P<field>(?:[^"]|")*)" with "(?P<value>(?:[^"]|")*)"$/
And /^(?:|I )press "(?P<button>(?:[^"]|")*)"$/
30. “A solution…”
Feature: Albums
I can create, edit and delete albums
Scenario: The homepage loads
Given I am on the homepage
Then I should see text matching "My Album"
Scenario: Page does not exist
Given I am on "/notexist"
Then I should see text matching "Page not found"
Scenario: Can create an album
Given I am on the homepage
And I follow "Add new album"
And I fill in "artist" with "Queen"
And I fill in "title" with “A kind of magic"
And I press "Add"
Then I should see text matching "A kind of magic"
And I should be on the homepage
Scenario: Can edit an album
Given I am on the homepage
And I follow "Edit"
And I fill in "artist" with “Billy Joel"
And I fill in "title" with “An Innocent Man"
And I press "Save"
Then I should see text matching “An Innocent Man"
And I should be on the homepage
tests/behat/features/bootstrap/album.feature
35. Custom step
$ legacybehat
..................U------
5 scenarios (4 passed, 1 undefined)
25 steps (18 passed, 1 undefined, 6 skipped)
0m0.28s (14.25Mb)
--- FeatureContext has missing steps. Define them with these
snippets:
/**
* @Given I am on the add page
*/
public function iAmOnTheAddPage()
{
throw new PendingException();
}
terminal
36. Custom step definition
/**
* @Given I am on the add page
*/
public function iAmOnTheAddPage()
{
throw new PendingException();
}
tests/behat/features/bootstrap/FeatureContext.php
37. Custom step definition
/**
* @Given I am on the add page
*/
public function iAmOnTheAddPage()
{
$this->visit('/index/add');
}
tests/behat/features/bootstrap/FeatureContext.php
38. First iteration
Scenario: Can create a default album
Given I am on the add page
And I fill in "artist" with "test123"
And I fill in "title" with "test321"
And I press "Add"
Then I should see text matching "test123"
And I should be on the homepage
tests/behat/features/bootstrap/FeatureContext.php
40. Second iteration
Scenario: Can create a default album
Given I am on the add page
And I create a default album
Then The album has been created
tests/behat/features/bootstrap/FeatureContext.php
41. Exercise #6
Guidance.
Use the following methods:
$this->fillField($field, $value);
$this->pressButton($button);
$this->assertPageContainsText($text);
tests/behat/features/bootstrap/FeatureContext.php
42. Traversing Elements
Making sure you’re accessing the
element you want.
(Following, are examples from the http://mink.behat.org/ docs)
43. Selectors
css selector
Using CSS expressions to search the DOM
$title = $page->find('css', 'h1');
$buttonIcon = $page->find('css', '.btn > .icon');
45. Exercise #7
Using the CSS selector
(1) Edit a specific album
(2) Delete a specific album
46. A starting point
$page = $this->getMink()->getSession()->getPage();
tests/behat/features/bootstrap/FeatureContext.php
47. Can edit a specific album
/**
* @Given I go to edit album by title :title
*/
public function iGoToEditAlbumByTitle($title)
{
$page = $this->getMink()->getSession()->getPage();
$editLink = $page->find(…);
$this->visit($editLink);
}
tests/behat/features/bootstrap/FeatureContext.php
48. Can edit a specific album
/**
* @Given I go to edit album by title :title
*/
public function iGoToEditAlbumByTitle($title)
{
$page = $this->getMink()->getSession()->getPage();
$editLink = $page->find(
'css',
sprintf('table tr td:contains("%s")', $title)
)
->getParent()
->findLink('Edit')
->getAttribute('href');
$this->visit($editLink);
}
tests/behat/features/bootstrap/FeatureContext.php
59. Clean DB #2
use BehatBehatHookScopeBeforeFeatureScope;
…
/** @BeforeFeature */
public static function cleanDB(BeforeFeatureScope $scope)
{
// prepare system for the feature
$dbCreds = $scope->getSuite()->getSetting("contexts")[0]["FeatureContext"];
shell_exec("sh /var/www/scripts/db.sh clean {$dbCreds[0]} {$dbCreds[1]} {$dbCreds[2]}");
}
tests/behat/features/bootstrap/FeatureContext.php
61. Exercise #8
(1) Create a @BeforeFeature to populate
with test data (fixtures/seeders)
(2) Create an @AfterFeature to clean DB
62. Exercise #9
(1) Create a PDO object
(2) Create an album. Use PDO to
verify it exists in the DB
63. Connect to DB
public function __construct($username, $password, $dbName)
{
$this->db = new PDO("mysql:host=127.0.0.1;dbname={$dbName}", $username, $password);
}
tests/behat/features/bootstrap/FeatureContext.php
69. Tags - Features and Scenarios
@db
Feature: Albums
I can create, edit and delete albums
Scenario: Can create an album
Given I am on the homepage
And I follow "Add new album"
And I fill in "artist" with "Queen"
And I fill in "title" with “A kind of magic"
And I press "Add"
Then I should see text matching "A kind of magic"
And I should be on the homepage
@db
Scenario: Can edit an album
Given I am on the homepage
And I follow "Edit"
And I fill in "artist" with “Billy Joel"
And I fill in "title" with “An Innocent Man"
And I press "Save"
Then I should see text matching “An Innocent Man"
And I should be on the homepage
tests/behat/features/bootstrap/album.feature
70. Exercise #12
(1) Create a tag with a fixture to
populate DB with a default album.
(2) Create a scenario that edits the
above album.
72. “A Solution…”
@db
Feature: Albums
I can create, edit and delete albums
Scenario: Can create an album
Given I am on the homepage
And I follow "Add new album"
And I fill in "artist" with "Queen"
And I fill in "title" with “A kind of magic"
And I press "Add"
Then I should see text matching "A kind of magic"
And I should be on the homepage
@defaultAlbumFixture
Scenario: Can edit an album
Given I am on the homepage
And I follow "Edit"
And I fill in "artist" with “Billy Joel"
And I fill in "title" with “An Innocent Man"
And I press "Save"
Then I should see text matching “An Innocent Man"
And I should be on the homepage
tests/behat/features/bootstrap/album.feature