LET ME INTRODUCE MYSELF
• @Richard_Tuin
• Software developer from the Netherlands
• Particular interest in QA
• Working for
Saturday, May 18, 13
INEFFICIENCY
• Different view on scope and resulting product
• Clients don’t get a feel of how they will use the product
• “I like what you’ve built, but it doesn’t do what i meant”
• “Thanks for this new feature, but now x stopped working!”
Saturday, May 18, 13
INEFFICIENCY
• Different view on scope and resulting product
• Clients don’t get a feel of how they will use the product
• “I like what you’ve built, but it doesn’t do what i meant”
• “Thanks for this new feature, but now x stopped working!”
Saturday, May 18, 13
BECAUSE
• ... the dev team and the client have the same goal
• ... we want to know that what we build has value
• ... we want to deliver consistent quality
Saturday, May 18, 13
SOTHIS MEANS...
• ... we have to focus more on communication
• ... leave no room for misinterpretation
• ... we have to work together with the client
• ... we got to have a system
• ... we have to validate regularly if what we have built is still
according to acceptance criteria
Saturday, May 18, 13
SOTHIS MEANS...
• ... we have to focus more on communication
• ... leave no room for misinterpretation
• ... we have to work together with the client
• ... we got to have a system
• ... we have to validate regularly if what we have built is still
according to acceptance criteria
Automation?
Saturday, May 18, 13
WRITING REQUIREMENTS
• Describe how a problem will be solved
• Write them together with your client
• In the (technical) language of the client
• Try to describe the functional problem, not the technical one
Saturday, May 18, 13
FEATURE FILE LAYOUT
Feature: {feature description}
{intention}
As a {person}
I want {feature}
So that {intention}
Scenario: {specific scenario description}
Given {context}
And {more context}
When {action}
Then {result}
Scenario: ...
Information: http://dannorth.net/whats-in-a-story/
Saturday, May 18, 13
EXAMPLE FEATURE
Feature: Searching on the internet
As a google.com visitor
I want to use the search engine
So that i can find information on the internet
Scenario: Simple keyword search
Given I am on the homepage
When I fill in the search term “PHP”
And I press “Google search”
Then I should see search results containing “PHP”
Scenario: I feel lucky
Given I am on the homepage
When I fill in the search term “PHP”
And I press “I’m feeling lucky”
Then I should not be on google.com
And I should see “PHP”
Saturday, May 18, 13
STEPS? (TERMINOLOGY)
Feature: {feature description}
{intention}
As a {person}
I want {feature}
So that {intention}
Scenario: {specific scenario description}
Given {context}
And {more context}
When {action}
Then {result}
Scenario: ...
Saturday, May 18, 13
STEPS? (TERMINOLOGY)
Feature: {feature description}
{intention}
As a {person}
I want {feature}
So that {intention}
Scenario: {specific scenario description}
Given {context}
And {more context}
When {action}
Then {result}
Scenario: ...
Feature, user story, module
Saturday, May 18, 13
STEPS? (TERMINOLOGY)
Feature: {feature description}
{intention}
As a {person}
I want {feature}
So that {intention}
Scenario: {specific scenario description}
Given {context}
And {more context}
When {action}
Then {result}
Scenario: ...
Feature, user story, module
Scenario
Saturday, May 18, 13
STEPS? (TERMINOLOGY)
Feature: {feature description}
{intention}
As a {person}
I want {feature}
So that {intention}
Scenario: {specific scenario description}
Given {context}
And {more context}
When {action}
Then {result}
Scenario: ...
Feature, user story, module
Scenario
Steps
Saturday, May 18, 13
LIVING DOCUMENTATION
• All features and scenarios make great documentation!
• A change request starts with rewriting documentation
• Easy to see what functionality the application contains
• Easy to get a feel for the impact of a change
• Easy to get a new team member involved
Saturday, May 18, 13
COMPONENTS OF A BEHAT+MINK
FUNCTIONALTEST SUITE
• Features
• Feature parser
• Generic browser controller client
• Browser controller/simulator
• Executable code that controls the browser controller client
Saturday, May 18, 13
COMPONENTS OF A BEHAT+MINK
FUNCTIONALTEST SUITE
• Features
• Feature parser
• Generic browser controller client
• Browser controller/simulator
• Executable code that controls the browser controller client
Living documentation
Saturday, May 18, 13
COMPONENTS OF A BEHAT+MINK
FUNCTIONALTEST SUITE
• Features
• Feature parser
• Generic browser controller client
• Browser controller/simulator
• Executable code that controls the browser controller client
Living documentation
Behat
Saturday, May 18, 13
COMPONENTS OF A BEHAT+MINK
FUNCTIONALTEST SUITE
• Features
• Feature parser
• Generic browser controller client
• Browser controller/simulator
• Executable code that controls the browser controller client
Living documentation
Behat
Mink
Saturday, May 18, 13
COMPONENTS OF A BEHAT+MINK
FUNCTIONALTEST SUITE
• Features
• Feature parser
• Generic browser controller client
• Browser controller/simulator
• Executable code that controls the browser controller client
Living documentation
Behat
Mink
Selenium, Zombie.js, Goutte,
etc.
Saturday, May 18, 13
COMPONENTS OF A BEHAT+MINK
FUNCTIONALTEST SUITE
• Features
• Feature parser
• Generic browser controller client
• Browser controller/simulator
• Executable code that controls the browser controller client
Living documentation
Behat
Mink
Selenium, Zombie.js, Goutte,
etc.
MinkExtension
Saturday, May 18, 13
HELLO BEHAT
1. Initialize a Behat testsuite skeleton
$ bin/behat --init
2. Behat creates it’s standard project structure
Saturday, May 18, 13
MINKEXTENSION
1. Bridges the gap between Behat and Mink
2. Contains a set of predefined step definitions
3. Not all step definitions may be usable for all projects
4. Behat + Mink is easy:
use BehatMinkExtensionContextMinkContext;
class FeatureContext extends MinkContext
{
// ...
}
features/FeatureContext.php
Saturday, May 18, 13
MINKEXTENSION STEPS
Given /^(?:|I )am on (?:|the )homepage$/
When /^(?:|I )go to (?:|the )homepage$/
Given /^(?:|I )am on "(?P<page>[^"]+)"$/
When /^(?:|I )fill in "(?P<field>(?:[^"]|")*)" with "(?P<value>(?:[^"]|")*)"$/
When /^(?:|I )press "(?P<button>(?:[^"]|")*)"$/
When /^(?:|I )follow "(?P<link>(?:[^"]|")*)"$/
Then /^(?:|I )should be on "(?P<page>[^"]+)"$/
Then /^(?:|I )should see "(?P<text>(?:[^"]|")*)"$/
$ bin/behat -dl
/**
* Clicks link with specified id|title|alt|text.
*
* @When /^(?:|I )follow "(?P<link>(?:[^"]|")*)"$/
*/
public function clickLink($link)
{
$link = $this->fixStepArgument($link);
$this->getSession()->getPage()->clickLink($link);
}
Saturday, May 18, 13
BEHAT.YML
• Place for configuration options
• Basic Behat / Mink config
default:
extensions:
BehatMinkExtensionExtension:
base_url: "http://www.yourwebsite.com"
goutte: ~
selenium2: ~
Saturday, May 18, 13
EXAMPLE FEATURE
Feature: Search on the internet
As a google.com visitor
I want to use the search engine
So that i can find information on the internet
Scenario: Simple keyword search
Given I am on the homepage
When I fill in the search term “PHP”
And I press “Google search”
Then I should see search results containing “PHP”
features/search.feature
Saturday, May 18, 13
STEP DEFINITIONS
/**
* @When /^I fill in the search term "([^"]*)"$/
*/
public function iSearchTheTerm($arg1)
{
throw new PendingException();
}
Put these in your FeatureContext.php file.
$ bin/behat
Running Behat
Behat gives you step suggestions:
Saturday, May 18, 13
WRITING STEP DEFINITIONS
/**
* @When /^I search the term "([^"]*)"$/
*/
public function iSearchTheTerm($searchTerm)
{
$this->fillField('q', $searchTerm); // method from MinkExtension
$this->pressButton('Google search');
}
Saturday, May 18, 13
MINKTERMINOLOGY
• Driver = Browser controller/emulator
• Session = Browser
• Page = Document(Element)
• Element
• Selectors
• XPath
• CSS
• Named
Saturday, May 18, 13
PAGE/DOCUMENTTRAVERSAL
• Selection of elements on a page
• Selectors based on XPath, CSS, Names
$page = $this->getPage();
$elements = $page->findAll('xpath', './/div[@class="sa_mc"]');
$elements = $page->findAll('css', 'div[class="sa_mc"]');
Saturday, May 18, 13
ELEMENT ACTIONS
$page = $this->getSession()->getPage();
$loginLink = $page->find('css', '#login');
$loginLink->click();
->getValue();
->setValue();
->keyUp();
->press();
etcetera...
Saturday, May 18, 13
PROFILES
• Full configuration per environment
• Feature / Scenario selection based on filters
• Define them in behat.yml:
• Call the profile with: $ bin/behat --profile acceptance
default:
extension:
BehatMinkExtensionContextMinkContext
base_url: “http://www.example.org”
acceptance:
extension:
BehatMinkExtensionContextMinkContext
base_url: “http://acc.example.org”
Saturday, May 18, 13
TAGS
• Metadata for features and scenarios
• Via command line: $ bin/behat --tags “@smoke”
• Define as filter in profile
@smoke
Feature: Search on the www
@javascript
Scenario: ...
search.feature
smoke:
filters:
tags: “@smoke”
behat.yml
nojs:
filters:
tags: “~@javascript”
behat.yml
Saturday, May 18, 13
SCENARIO OUTLINES
Scenario Outline: Simple keyword search
Given I am on the homepage
When I search the term <searchterm>
Then I should see search results containing <searchterm>
Examples:
| searchterm |
| PHP |
| Java |
| Pie |
| This string is possibly too long and uncommon |
Saturday, May 18, 13
LOCALIZATION
• Write features in your own language
# language: it
Funzionalità: non so scrivere italiano
Scenario: ...
Dato ...
Quando ...
Allora ...
Schema dello scenario: ...
Dato ...
Quando ...
Allora ...
Esempi:
...
Saturday, May 18, 13
INTEGRATION WITH JENKINS
• Behat includes export to jUnit format
• Jenkins build step example
${WORKSPACE}/bin/behat --format junit --out ${WORKSPACE}/build
Saturday, May 18, 13
CONCLUSION
1. Writing examples is great to improve communication
2. Automating acceptance criteria = consistent quality
3. Behat and Mink are an excellent combination to do this
Saturday, May 18, 13