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 £20

Something 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