Case studies conducted at Microsoft and IBM indicate that teams that adopt TDD experience 40% to 90% bugs, which results in 15-35% additional development time.
"Imperfect tests, run frequently, are much better than perfect tests that are never written at all." - Martin Fowler
Behat is a BDD (Behavior Driven Development) framework written in PHP
There's the module for that, because of course there is
Drupal ExtensionComposer.json
"require": {
"behat/behat": "3.0.*@stable",
"drupal/drupal-extension": "3.0.*@dev"
}
Behat.yml
default:
suites:
default:
contexts:
- FeatureContext
- Drupal\DrupalExtension\Context\DrupalContext
extensions:
Behat\MinkExtension:
Use your google powers
Tests are saved in .feature files
I want to be able to log into my website in order to edit my content.
As a an anonymous user,
I want to be able to log into my website,
So that I can edit my content.
What does it mean to be logged in? How do we know that we are logged in?
Given I am an anonymous user
When I am at "user/login"
And I fill in "name" with "admin"
And I fill in "pass" with "admin"
And press "Log in"
Then I should see the link "Log out"
How do we check can edit content.
Given I am logged in as a user with the administrator role
When I am at "node/add/page"
Then I should see "Create Basic page"
And I should get a 200 HTTP response
Slap it in a feature file and boom you have your test.
#./features/user_login.feature
@api
Feature: User Login.
As a an anonymous user,
I want to be able to log into my website,
So that I can edit my content.
Scenario: I can log in.
Given I am an anonymous user
When I am at "user/login"
And I fill in "name" with "admin"
And I fill in "pass" with "admin"
And press "Log in"
Then I should see the link "Log out"
Scenario: I can edit content
Given I am logged in as a user with the administrator role
When I am at "node/add/page"
Then I should see "Create Basic page"
And I should get a 200 HTTP response
$ bin/behat features/user_login.feature
@api
Feature: Content Type Event
As an anonymous user
I want to view data related to an Event
So that I can decide it is something I would like to attend.
Scenario: Add an event node and verify that the necessary fields exist.
Given I am an anonymous user
And an "Event Terms" term with the name "camp"
And an "Event Terms" term with the name "drupal"
And "event" content:
| title | field_event_location | field_event_date | field_event_tags | status |
| Florida Drupal Camp | Orlando | 2015-04-11 9:00:00 | camp, drupal | 1 |
When I am at "content/florida-drupal-camp"
Then I should see the text "Florida Drupal Camp"
And I should see the text "Orlando"
And I should see the text "Saturday, April 11, 2015"
And I should see the text "camp"
And I should see the text "drupal"
Each scenario step maps to a function that performs the step
Given I am an anonymous user
/**
* @Given I am an anonymous user
* @Given I am not logged in
*/
public function assertAnonymousUser() {
// Verify the user is logged out.
if ($this->loggedIn()) {
$this->logout();
}
Out of the box the Mink and Drupal Drivers will provide a lot of step definitions that you can use.
$ behat -dl
default | When I visit the login page
default | Given I am an anonymous user
default | Given I am not logged in
default | Given I am logged in as a user with the :role role(s)
default | Given I am logged in as a user with the :role role(s) and I have the following fields:
default | Given I am logged in as :name
default | Given I am logged in as a user with the :permissions permission(s)
default | Then I should see (the text ):text in the ":rowText" row
default | Given I click :link in the :rowText row
Feature: Migrations
As an editor of the website
I want the workbench module enabled
So that I can create custom editing work flows
Scenario: Confirm the workbench module is installed
Given the "workbench" module is installed
Custom step definitions go in features/bootstrap/FeatureContext.php
//features/bootstrap/FeatureContext.php
use Drupal\DrupalExtension\Context\RawDrupalContext;
use Behat\Behat\Context\SnippetAcceptingContext;
use Behat\Gherkin\Node\PyStringNode;
use Behat\Gherkin\Node\TableNode;
/**
* Defines application features from the specific context.
*/
class FeatureContext extends RawDrupalContext implements SnippetAcceptingContext
{
}
/**
* Asserts that a given module exists and is enabled.
*
* @Given the :module module is installed
*/
public function assertModuleExists($module)
{
if (module_exists($module)) {
return TRUE;
}
$message = sprintf('Module "%s" is not installed.', $module);
throw new \Exception($message);
}
Then "events" migration is complete$/
/**
* Asserts the given migration is complete.
*
* @Then /^the "([^"]*)" migration is complete$/
*
* @throws /Exception if the migration did not complete.
*/
public function assertMigrationIsComplete($name)
{
$migration = Migration::getInstance($name);
if ($migration->isComplete()) {
return TRUE;
}
$message = sprintf('The "%s" migration is not complete.', $name);
throw new \Exception($message);
}
We use Mink to interact with the browser
Some common usages of the Mink API
$element = $session->getPage();
$element->findAll($selector, $locator);
$element->getText();
$element->getHtml();
$element->isVisible();
$element->click();
$element->press();
$element->check();
$element->uncheck();
Mink Cheat Sheet
- tests are awesome
- tests are good for you, the client, and the product
- Behat Documentation
- Behat in a box
- Follow me on twitter: @aczietlow