

About ME

- Señor Developer @ Orba
- self-proclaimed code magician
- mentor & consultant
- devThursday keeper


What is Behat?
Behat is a tool to close the Behavior-Driven Development communication loop in PHP
BDD - Behavior Driven Development
Unit Tests for business processes
BDD - Behavior Driven Development
- The basis of the process is the creation of requirements
- Main trait of process is his behavior
- Process description is understandable for client, analitics and programmers
- Automation
Gherkin
- Non-technical language for business
- Describe system behaviour
- Bridge between business and programmer
Story Syntax
- Tittle
- Narration
- Acceptance criteria
Feature: Listing command
In order to change the structure of the folder I am currently in
As a UNIX user
I need to be able see the currently available files and folders there
Scenario: Listing two files in a directory
Given I am in a directory "test"
And I have a file named "foo"
And I have a file named "bar"
When I run "ls"
Then I should get:
"""
bar
foo
"""Narration
- Describe feature (what to do)
- Describe who is user
- Describe what is the advantage
Feature: Listing command
In order to change the structure of the folder I am currently in
As a UNIX user
I need to be able see the currently available files and folders there
Acceptance Criteria
- Given - describe the initial conditions
(descibe an actor state) - When - describe actions (what actor do)
- Then - describe awaiting results
(what actor see/have)
Given I am in a directory "test"
And I have a file named "foo"
And I have a file named "bar"
When I run "ls"
Then I should get:
"""
bar
foo
"""The feature scenario
Story- Building steps
- Step should be generic
- Step should be understable
- Step should contain information about what to do
- Step should be written in correct English
- Steps should be consistent with each other (the way of building sentences)
Example
Feature: Product basket
In order to buy products
As a customer
I need to be able to put interesting products into a basket
Rules:
- VAT is 20%
- Delivery for basket under £10 is £3
- Delivery for basket over £10 is £2
Scenario: Buying a single product under £10
Given there is a "Sith Lord Lightsaber", which costs £5
When I add the "Sith Lord Lightsaber" to the basket
Then I should have 1 product in the basket
And the overall basket price should be £9
Scenario: Buying a single product over £10
Given there is a "Sith Lord Lightsaber", which costs £15
When I add the "Sith Lord Lightsaber" to the basket
Then I should have 1 product in the basket
And the overall basket price should be £20
Scenario: Buying two products over £10
Given there is a "Sith Lord Lightsaber", which costs £10
And there is a "Jedi Lightsaber", which costs £5
When I add the "Sith Lord Lightsaber" to the basket
And I add the "Jedi Lightsaber" to the basket
Then I should have 2 products in the basket
And the overall basket price should be £20Something for devs ;)
<?php
use Behat\Behat\Context\Context;
use PHPUnit\Framework\Assert;
final class Shelf
{
private $priceMap = array();
public function setProductPrice($product, $price)
{
$this->priceMap[$product] = $price;
}
public function getProductPrice($product)
{
return $this->priceMap[$product];
}
}
final class Basket implements \Countable
{
private $shelf;
private $products;
private $productsPrice = 0.0;
public function __construct(Shelf $shelf)
{
$this->shelf = $shelf;
}
public function addProduct($product)
{
$this->products[] = $product;
$this->productsPrice += $this->shelf->getProductPrice($product);
}
public function getTotalPrice()
{
return $this->productsPrice
+ ($this->productsPrice * 0.2)
+ ($this->productsPrice > 10 ? 2.0 : 3.0);
}
public function count()
{
return count($this->products);
}
}
/**
* Defines application features from the specific context.
*/
class FeatureContext implements Context
{
private $shelf;
private $basket;
/**
* Initializes context.
*
* Every scenario gets its own context instance.
* You can also pass arbitrary arguments to the
* context constructor through behat.yml.
*/
public function __construct()
{
$this->shelf = new Shelf();
$this->basket = new Basket($this->shelf);
}
/**
* @Given there is a(n) :product, which costs £:price
*/
public function thereIsAWhichCostsPs($product, $price)
{
$this->shelf->setProductPrice($product, floatval($price));
}
/**
* @When I add the :product to the basket
*/
public function iAddTheToTheBasket($product)
{
$this->basket->addProduct($product);
}
/**
* @Then I should have :count product in the basket
*/
public function iShouldHaveProductInTheBasket($count)
{
Assert::assertCount(
intval($count),
$this->basket
);
}
/**
* @Then the overall basket price should be £:price
*/
public function theOverallBasketPriceShouldBePs($price)
{
Assert::assertSame(
floatval($price),
$this->basket->getTotalPrice()
);
}
/**
* @Then I should have :count products in the basket
*/
public function iShouldHaveProductsInTheBasket($count)
{
Assert::assertCount(
intval($count),
$this->basket
);
}
}Result
$ vendor/bin/behat
Feature: Product basket
In order to buy products
As a customer
I need to be able to put interesting products into a basket
Rules:
- VAT is 20%
- Delivery for basket under £10 is £3
- Delivery for basket over £10 is £2
Scenario: Buying a single product under £10
Given there is a "Sith Lord Lightsaber", which costs £5
When I add the "Sith Lord Lightsaber" to the basket
Then I should have 1 product in the basket
And the overall basket price should be £9
Scenario: Buying a single product over £10
Given there is a "Sith Lord Lightsaber", which costs £15
When I add the "Sith Lord Lightsaber" to the basket
Then I should have 1 product in the basket
And the overall basket price should be £20
Scenario: Buying two products over £10
Given there is a "Sith Lord Lightsaber", which costs £10
And there is a "Jedi Lightsaber", which costs £5
When I add the "Sith Lord Lightsaber" to the basket
And I add the "Jedi Lightsaber" to the basket
Then I should have 2 products in the basket
And the overall basket price should be £20
3 scenarios (3 passed)
14 steps (14 passed)
0m0.15s (7.49Mb)Pros
For All:
- living documentation
- collaboration, early discovery of unknowns
- enforce building domain vocabulary and semi formal language (DSL) to express system behaviour consistently within the organization.
Pros
For devs:
- like TDD, it helps to think in chunks, create nice and testable code.
- write code for what is needed only (build the right thing)
- better coordination between different dev teams developing similar features with different technologies.
Pros
For QA:
- ready acceptance criteria
- ready building blocks for all kind of tests
- test what is exactly need (test the right thing)
Pros
For Product Owner:
- think and reason features in detail thus produce better specification
- better visual and coordination with other Managers and Product owners
- better visual and understanding on Devs and QAs output/report due to the same source/format of specs
Cons?
- Team can consider it as a waste of time
- Anticipation by developers the concept of "Testing"
- The test can be targeted on verification of classes and methods and not on what the code really should do
Q&A ?
Behat
By Paweł Radzikowski
Behat
- 305