SlideShare una empresa de Scribd logo
1 de 118
BDD   в php
      и ZF
Я
кто
      такой




  @everzet
         senior from-birth web
                   developer в
Я
кто
         такой



      International speaker
      Разработчик Behat, Mink                       http://github.com/everzet
      Разработчик capifony                           http://card.everzet.com
      Разработчик jade.php                           everzet@knplabs.com
      Контрибьютор Symfony2 framework
      Разработчик плагинов для symfony и Symfony2




  @everzet      senior from-birth web
                          developer в
BDD, Symfony2 эксперты

 Активные контрибуторы open-source проектов

 Консультанты, аудиторы, тренеры



http://knplabs.com
История
 тестирования
История



          UnitTest
                     Автоматизация тестов
TDD
                     Тесты вперед
История



          UnitTest
                     Автоматизация тестов
BDD




                     Dan North
          TDD
                     Тесты вперед
История



          UnitTest
                     Автоматизация тестов
BDD ⎯ эволюция TDD
- Эволюция-хренолюция...
  Что не так с TDD?
Test-Driven Development
Мы на самом деле говорим о тестах???
    Но каким образом тестировать то, чего еще нет?




Test-Driven Development
На самом деле, мы говорим о дизайне




  Test-Driven Development
Behavior
Test-Driven Development
            © 2003, Dan North
BDD   был создан как набор
         конвенций поверх    TDD
BDD         был создан как набор
                         конвенций поверх    TDD
Тест-кейсы должы составлять предложения
testFindsCustomerById()
testFailsForDuplicateCustomers()
BDD          был создан как набор
                          конвенций поверх       TDD
Тест-кейсы должы составлять предложения
testFindsCustomerById()
testFailsForDuplicateCustomers()

Тест-кейсы должны начинаться со слова “should”
shouldFindCustomerById()
shouldFailForDuplicateCustomers()
BDD          был создан как набор
                          конвенций поверх       TDD
Тест-кейсы должы составлять предложения
testFindsCustomerById()
testFailsForDuplicateCustomers()

Тест-кейсы должны начинаться со слова “should”
shouldFindCustomerById()
shouldFailForDuplicateCustomers()

Класс тест-кейсов должен представлять из себя существительное для кейсов
class CustomerTableTest extends PHPUnitTestCase
{
    /**
     * @Test
     */
    shouldFindCustomerById()
    ...
}
АССЕРШЕНЫ
     тоже TEST-ориентированы

               ТЕСТируем

     assertEquals($expected, $actual)

assertGreaterThan($expected, $actual)

    assertInstanceOf($class, $actual)
АССЕРШЕНЫ
     тоже TEST-ориентированы

               ТЕСТируем                Описываем

     assertEquals($expected, $actual)   $actual should be Equals to $expected

assertGreaterThan($expected, $actual)   $actual should be GreaterThan $expected

    assertInstanceOf($class, $actual)   $actual should be InstanceOf $class
История

                                         Сначала дизайн Spec BDD




 UnitTest                 TDD             BDD
                          Тесты вперед
   Автоматизация тестов




                                           Dan North
Specификационные
  BDD Фрэймворки
*Spec


  RSpec   by Dave Astels
*Spec


  RSpec   by Dave Astels



  JSpec   by TJ Holowaychuk
*Spec


  RSpec   by Dave Astels



  JSpec   by TJ Holowaychuk



  Fabulous      by Alex Rudakov
RSpec

    # bowling_spec.rb
    require 'bowling'

    describe Bowling, "#score" do
      it "returns 0 for all gutter game" do
        bowling = Bowling.new
        20.times { bowling.hit(0) }
        bowling.score.should == 0
      end
    end
RSpec

       # bowling_spec.rb
       require 'bowling'

       describe Bowling, "#score" do
         it "returns 0 for all gutter game" do
           bowling = Bowling.new
           20.times { bowling.hit(0) }
           bowling.score.should == 0
         end
       end




 Пишем СПЕЦИФИКАЦИЮ, а не UnitTEST
СЦЕНАРНЫЙ

BDD

            photo by dsearls
СЛ ОВАРЬ




           photophoto by dsearls
                 by Horia Varlan
о в
                         р
                    с те
             я те
           дл


СЛ ОВАРЬ




                             photophoto by dsearls
                                   by Horia Varlan
о в
                            р
                       с те
                я те
           дл


СЛ ОВАРЬ   дл
             яа
               на
                 ли
                         ти
                              ко
                                     в
                                photophoto by dsearls
                                      by Horia Varlan
о в
                                                           р
                                                      с те
                                               я те
                                          дл


                           в   СЛ ОВАРЬ   дл
                         о                  яа
                п   ер                        на
             ло
       в   е                                    ли
    де                                                  ти
для                                                          ко
                                                                    в
                                                               photophoto by dsearls
                                                                     by Horia Varlan
для                                                             в
       зак                                                 р   о
             азч                                      с те
                 и   ко                        я те
                          в               дл


                           в   СЛ ОВАРЬ   дл
                         о                  яа
                п   ер                        на
             ло
       в   е                                    ли
    де                                                  ти
для                                                          ко
                                                                    в
                                                               photophoto by dsearls
                                                                     by Horia Varlan
для                                                             в
       зак                                                 р   о
             азч                                      с те


                               1
                 и   ко                        я те
                          в               дл


                           в   СЛ ОВАРЬ   дл
                         о                  яа
                п   ер                        на
             ло
       в   е                                    ли
    де                                                  ти
для                                                          ко
                                                                    в
                                                               photophoto by dsearls
                                                                     by Horia Varlan
ИСКОРЕНИТ множество проблем
    ДИЗАЙНА и КОММУНИКАЦИЙ




              1
                                те ры
                         т ес
заказчики               девелоперы
             СЛ ОВАРЬ   ана
                           лит
                               ики



                                        photophoto by dsearls
                                              by Horia Varlan
НИК АЦИИ
К ОММУ




                 photo by joshfassbind.com
Story:




  In order to [A]
  As a [B]
  I need [C]
Story:




  Чтобы [A]
  В качестве [B]
  Мне нужно [C]
Story:




  Чтобы [A]
  В качестве [B]
  Мне нужно [C]
  A ⎯ добавочное знач. (профит) функционала
  B ⎯ профитирующая персона (роль)
  C ⎯ функционал
Story:




  Чтобы [A]
  В качестве [B]
                         ⎯ Сила данной конструкции в том, что
                          она требует определения профита от
                           функционала еще до его реализации

  Мне нужно [C]                              © Dan North




  A ⎯ добавочное знач. (профит) функционала
  B ⎯ профитирующая персона (роль)
  C ⎯ функционал
Story:




     Поведение story ⎯
     это ее приемочный
     критерий!
     ⎯ если система удовлетворяет все
     приемочные критерии, то она работает
     верно; если не выполняет - неверно.
Story:
In order to ...
As a ...
I need ...
Story:
In order to ...
As a ...
I need ...


      Given some initial context (the givens),
      When an event occurs,
      Then ensure some outcomes.
Story:
In order to ...
As a ...
I need ...


      Given some initial context (the givens),
      When an event occurs,
      Then ensure some outcomes.


      Given some initial context (the givens),
      When an event occurs,
      Then ensure some outcomes.
Story:
In order to ...
As a ...
I need ...

      Scenario 1:
      Given some initial context (the givens),
      When an event occurs,
      Then ensure some outcomes.

      Scenario 2:
      Given some initial context (the givens),
      When an event occurs,
      Then ensure some outcomes.
История

                                         Сначала дизайн Spec BDD




 UnitTest                 TDD             BDD          Scenario BDD




                                                           Сначала анализ
                          Тесты вперед
   Автоматизация тестов




                                           Dan North
История

                                         Сначала дизайн Spec BDD


                                                           +
 UnitTest                 TDD             BDD          Scenario BDD




                                                           Сначала анализ
                          Тесты вперед
   Автоматизация тестов




                                           Dan North
GHERKINDSL



             photo by isobel.gordon
Story:
In order to ...
As a ...
I need ...

      Scenario 1:
      Given some initial context (the givens),
      When an event occurs,
      Then ensure some outcomes.

      Scenario 2:
      Given some initial context (the givens),
      When an event occurs,
      Then ensure some outcomes.
Feature: Feature description
In order to ...
As a ...
I need ...

      Scenario: 1st scenario title
      Given some initial context (the givens),
      When an event occurs,
      Then ensure some outcomes.

      Scenario: 2nd scenario title
      Given some initial context (the givens),
      When an event occurs,
      Then ensure some outcomes.
feature tree
Feature: Feature description                             1. feature
In order to ...
As a ...
I need ...

              Scenario: 1st scenario title
2. scenario




              Given some initial context (the givens)     3. step
              When an event occurs                              ...
              Then ensure some outcomes                         ...

              Scenario: 2nd scenario title
2. scenario




              Given some initial context (the givens)     3. step
              When an event occurs                              ...
              Then ensure some outcomes                         ...
Feature: Feature description
In order to ...
As a ...
I need ...

      Scenario: 1st scenario title
      Given some initial context (the givens)
      When an event occurs
      Then ensure some outcomes

      Scenario: 2nd scenario title
      Given some initial context (the givens)
      When an event occurs
      Then ensure some outcomes
# language: fr
Fonctionnalité: Feature description
In order to ...
As a ...
I need ...

      Scénario: 1st scenario title
      Etant donné some initial context (the givens)
      Lorsque an event occurs
      Alors ensure some outcomes

      Scénario: 2nd scenario title
      Etant donné some initial context (the givens)
      Lorsque an event occurs
      Alors ensure some outcomes
# language: ja
                  : Feature description
In order to ...
As a ...
I need ...

                    : 1st scenario title
              some initial context (the givens)
              an event occurs
            ensure some outcomes

                    : 2nd scenario title
              some initial context (the givens)
              an event occurs
            ensure some outcomes
# language: ru
Функционал: Feature description
In order to ...
As a ...
I need ...

      Сценарий: 1st scenario title
      Допустим some initial context (the givens)
      Когда an event occurs
      То ensure some outcomes

      Сценарий: 2nd scenario title
      Допустим some initial context (the givens)
      Когда an event occurs
      То ensure some outcomes
# language: en-pirate
Ahoy matey!: Feature description
In order to ...
As a ...
I need ...

      Heave to: 1st scenario title
      Let go and haul some initial context (the givens)
      Blimey! an event occurs
      Aye ensure some outcomes

      Heave to: 2nd scenario title
      Let go and haul some initial context (the givens)
      Blimey! an event occurs
      Aye ensure some outcomes
# language: en-pirate
Ahoy matey!:



     Heave to:
     Let go and haul some initial context (the givens)
     Blimey! an event occurs
     Aye ensure some outcomes

     Heave to:
     Let go and haul some initial context (the givens)
     Blimey! an event occurs
     Aye ensure some outcomes
Приемочные критерии
должны быть исполняемы!
Установка

 1. Добавляем pear-channel:
  $ pear channel-discover pear.behat.org

 2. Ставим:
  $ pear install behat/behat

 3. Инициализируем:
  $ cd path/to/project && behat --init
Установка

 1. Добавляем pear-channel:
  $ pear channel-discover pear.behat.org

 2. Ставим:
  $ pear install behat/behat

 3. Инициализируем:
  $ cd path/to/project && behat --init
    +d features - place your *.feature files here
    +d features/steps - place step definition files here
    +f features/steps/steps.php - place some step definitions in this file
    +d features/support - place support scripts and static files here
    +f features/support/bootstrap.php - place bootstrap scripts in this file
    +f features/support/env.php - place environment initialization scripts in this file
# language: ru
Функционал: Операции над счетом
# language: ru
Функционал: Операции над счетом
Чтобы иметь возможность управлять счетом
В качестве клиента
Я должен иметь возможность выполнять операции
# language: ru
Функционал: Операции над счетом
Чтобы иметь возможность управлять счетом
В качестве клиента
Я должен иметь возможность выполнять операции


  Сценарий: Депозирование средств
# language: ru
Функционал: Операции над счетом
Чтобы иметь возможность управлять счетом
В качестве клиента
Я должен иметь возможность выполнять операции


  Сценарий: Депозирование средств
     Допустим у меня есть банковский счет
     Если я положу на счет 35$
     То на моем счету должно быть 35$
1. feature
  # language: ru
  Функционал: Операции над счетом
    Чтобы иметь возможность управлять счетом
    В качестве клиента
    Я должен иметь возможность выполнять операции


              Сценарий: Депозирование средств
2. scenario




                Допустим у меня есть банковский счет    3. step
                Если я положу на счет 35$                     ...
                То на моем счету должно быть 35$              ...
ОПРЕДЕЛЕНИЯШАГОВ
Допустим у меня есть банковский счет
ОПРЕДЕЛЕНИЯШАГОВ
Допустим у меня есть банковский счет
 <?php

 Допустим('/^у меня есть банковский счет$/');
ОПРЕДЕЛЕНИЯШАГОВ
Допустим у меня есть банковский счет
 <?php

 Допустим('/^у меня есть банковский счет$/',
    function() {
      throw new BehatBehatExceptionPending();
    }
 );
ОПРЕДЕЛЕНИЯШАГОВ
Допустим у меня есть банковский счет
 <?php

 $steps->Допустим('/^у меня есть банковский счет$/',
    function() {
      throw new BehatBehatExceptionPending();
    }
 );
ОПРЕДЕЛЕНИЯШАГОВ
Допустим у меня есть банковский счет
 <?php

 $steps->Допустим('/^у меня есть банковский счет$/',
    function() {
      throw new BehatBehatExceptionPending(); ???
    }
 );
ТИПЫРЕЗУЛЬТАТОВШАГОВ
ТИПЫРЕЗУЛЬТАТОВШАГОВ


1. Pending шаг ⎯ который throw new BehatBehatExceptionPending();
ТИПЫРЕЗУЛЬТАТОВШАГОВ


1. Pending шаг ⎯ который throw new BehatBehatExceptionPending();

2. Undefined шаг ⎯ у которого нет (не найдено) определений
ТИПЫРЕЗУЛЬТАТОВШАГОВ


1. Pending шаг ⎯ который throw new BehatBehatExceptionPending();

2. Undefined шаг ⎯ у которого нет (не найдено) определений

3. Ambiguous шаг ⎯ который подпадает под несколько определений
ТИПЫРЕЗУЛЬТАТОВШАГОВ


1. Pending шаг ⎯ который throw new BehatBehatExceptionPending();

2. Undefined шаг ⎯ у которого нет (не найдено) определений

3. Ambiguous шаг ⎯ который подпадает под несколько определений

4. Failed шаг ⎯ который throw Exception();
ТИПЫРЕЗУЛЬТАТОВШАГОВ


1. Pending шаг ⎯ который throw new BehatBehatExceptionPending();

2. Undefined шаг ⎯ у которого нет (не найдено) определений

3. Ambiguous шаг ⎯ который подпадает под несколько определений

4. Failed шаг ⎯ который throw Exception();

5. Skipped шаг ⎯ который идет следом за pending/undefined/failed в сценарии
ТИПЫРЕЗУЛЬТАТОВШАГОВ


1. Pending шаг ⎯ который throw new BehatBehatExceptionPending();

2. Undefined шаг ⎯ у которого нет (не найдено) определений

3. Ambiguous шаг ⎯ который подпадает под несколько определений

4. Failed шаг ⎯ который throw Exception();

5. Skipped шаг ⎯ который идет следом за pending/undefined/failed в сценарии

6. Passed шаг ⎯ который не кидает эксепшенов
ОПРЕДЕЛЕНИЯШАГОВ
Допустим у меня есть банковский счет
 <?php

 $steps->Допустим('/^у меня есть банковский счет$/',
    function() {
      throw new BehatBehatExceptionPending();
    }
 );
ОПРЕДЕЛЕНИЯШАГОВ
Допустим у меня есть банковский счет
 <?php

 $steps->Допустим('/^у меня есть банковский счет$/',
    function() {
      throw new BehatBehatExceptionPending();
    }
 );


Если я положу на счет 35$
ОПРЕДЕЛЕНИЯШАГОВ
Допустим у меня есть банковский счет
 <?php

 $steps->Допустим('/^у меня есть банковский счет$/',
    function() {
      throw new BehatBehatExceptionPending();
    }
 );


Если я положу на счет 35$
 <?php

 $steps->Если('/^я положу на счет (d+)$$/',
    function($dollars) {
      // $dollars === 35
    }
 );
ОПРЕДЕЛЕНИЯШАГОВ
Допустим у меня есть банковский счет
 <?php

 $steps->Допустим('/^у меня есть банковский счет$/',
    function() {
      throw new BehatBehatExceptionPending();
    }
 );


Если я положу на счет 35$
 <?php

 $steps->Если('/^я положу на счет (d+)$$/',
    function($dollars) {
      // $dollars === 35
    }
 );
ОПРЕДЕЛЕНИЯШАГОВ
Допустим у меня есть банковский счет
 <?php

 $steps->Допустим('/^у меня есть банковский счет$/',
    function($world) {
      throw new BehatBehatExceptionPending();
    }
 );


Если я положу на счет 35$
 <?php

 $steps->Если('/^я положу на счет (d+)$$/',
    function($world, $dollars) {
      // $dollars === 35
    }
 );
ОПРЕДЕЛЕНИЯШАГОВ
Допустим у меня есть банковский счет
 <?php

 $steps->Допустим('/^у меня есть банковский счет$/',
    function($world) {
      $world->account = new BankAccount();
    }
 );


Если я положу на счет 35$
 <?php

 $steps->Если('/^я положу на счет (d+)$$/',
    function($world, $dollars) {
      $world->account->deposit($dollars);
    }
 );
ПРОВЕРЯЕМРЕЗУЛЬТАТЫ
То на моем счету должно быть 35$
ПРОВЕРЯЕМРЕЗУЛЬТАТЫ
То на моем счету должно быть 35$
 <?php

 $steps->То('/^на моем счету должно быть (d+)$$/',
    function($world, $balance) {
      if ($balance !== $world->account->getBalance()) {
        throw new Exception('Неверный баланс!');
      }
    }
 );
ПРОВЕРЯЕМРЕЗУЛЬТАТЫ
То на моем счету должно быть 35$
 <?php

 $steps->То('/^на моем счету должно быть (d+)$$/',
    function($world, $balance) {
      if ($balance !== $world->account->getBalance()) {
        throw new Exception('Неверный баланс!');
      }
    }
 );


То на моем счету должно быть 35$ (                           using
                                                           PHPUnit   )
 <?php

 $steps->То('/^на моем счету должно быть (d+)$$/',
    function($world, $balance) {
      assertEquals($balance, $world->account->getBalance());
    }
 );
ОПРЕДЕЛЕНИЯШАГОВ
 <?php

 $steps->Допустим('/^у меня есть банковский счет$/',
    function($world) {
      $world->account = new BankAccount();
    }
 );

 $steps->Если('/^я положу на счет (d+)$$/',
    function($world, $dollars) {
      $world->account->deposit($dollars);
    }
 );

 $steps->То('/^на моем счету должно быть (d+)$$/',
    function($world, $balance) {
      assertEquals($balance, $world->account->getBalance());
    }
 );
ОПРЕДЕЛЕНИЯШАГОВ
 <?php

 $steps->

     Допустим('/^у меня есть банковский счет$/',
       function($world) {
         $world->account = new BankAccount();
       }
     )->

     Если('/^я положу на счет (d+)$$/',
       function($world, $dollars) {
         $world->account->deposit($dollars);
       }
     )->

     То('/^на моем счету должно быть (d+)$$/',
       function($world, $balance) {
         assertEquals($balance, $world->account->getBalance());
       }
     )
 ;
ЧТО ДАЛЬШЕ?


 1. Раскрашиваем:
  $ behat features/
ЧТО ДАЛЬШЕ?


 1. Раскрашиваем:
  $ behat features/


 2. Имплементируем
ЧТО ДАЛЬШЕ?


 1. Раскрашиваем:
  $ behat features/


 2. Имплементируем
 3. Раскрашиваем
ЧТО ДАЛЬШЕ?


 1. Раскрашиваем:
  $ behat features/


 2. Имплементируем
 3. Раскрашиваем
 4. Описываем новый функционал
ЧТО ДАЛЬШЕ?


 1. Раскрашиваем:
  $ behat features/


 2. Имплементируем
 3. Раскрашиваем
 4. Описываем новый функционал
Описание web-
      приложений
M!"#
Установка



 1. Добавляем pear-channel:
  $ pear channel-discover pear.behat.org

 2. Ставим:
  $ pear install behat/mink-beta
<?php

use BehatMinkMink,
    BehatMinkDriverGoutteDriver,
    BehatMinkDriverSahiDriver;


// инициализируем Mink и регистрируем драйверы
$mink = new Mink();
$mink->registerDriver('goutte',     new GoutteDriver($startUrl), true);
$mink->registerDriver('javascript', new SahiDriver($startUrl, 'firefox'));
$mink->registerDriver('custom',     new MyCustomDriver($startUrl));


// выполняем действия в стандартном драйвере
$mink->switchToDefaultDriver();
$mink->getSession()->getPage()->findLink('Downloads')->click();
echo $mink->getSession()->getPage()->getContent();


// выполняем действия в javascript (Sahi) драйвере
$mink->switchToDriver('javascript');
$mink->getSession()->getPage()->findLink('Downloads')->click();
echo $mink->getSession()->getPage()->getContent();


// выполняем действия в кастомном (MyCustomDriver) драйвере
$mink->switchToDriver('custom');
$mink->getSession()->getPage()->findLink('Downloads')->click();
echo $mink->getSession()->getPage()->getContent();
zF
Новый проект

 1. Создаем каркас проекта:
  $ cd path/to/project && zf ...
Новый проект

 1. Создаем каркас проекта:
  $ cd path/to/project && zf ...




              Getting Started with
               Zend Framework
                  By Rob Allen, www.akrabat.com
                     Document Revision 1.7.6
                      Copyright © 2006, 2010
Новый проект

 1. Создаем каркас проекта:
  $ cd path/to/project && zf ...

 2. Инициализируем B$%&':
  $ behat --init
Новый проект

 3. Знакомим B$%&' с M!"#:
  $ vim behat.yml
    # behat.yml
    default:
      environment:
        parameters:
            start_url:   http://tutorial.zf.dev/
    imports:
      - mink/behat.yml


  $ vim features/support/bootstrap.php

    <?php
    // features/support/bootstrap.php
    require_once 'PHPUnit/Autoload.php';
    require_once 'PHPUnit/Framework/Assert/Functions.php';
    require_once 'mink/autoload.php';


  $ behat --steps --lang ru
# language: ru
Функционал: Альбомы
 Чтобы иметь представление об исполнителях
 Как каталогизатор
 Я должен уметь управлять коллекцией альбомов


 Сценарий: Добавление альбома
    Допустим я на странице /index/add
    Если я ввожу "Pendulum" в поле "Artist"
    И я ввожу "In Silico" в поле "Title"
    И нажимаю "Add"
    То я должен видеть "In Cilico"
    И я должен видеть "Edit"
# language: ru
Функционал: Альбомы
 Чтобы иметь представление об исполнителях
 Как каталогизатор
 Я должен уметь управлять коллекцией альбомов


 Сценарий: Добавление альбома
    Допустим я на странице /index/add
    Если я ввожу "Pendulum" в поле "Artist"
    И я ввожу "In Silico" в поле "Title"
    И нажимаю "Add"
    То я должен видеть "In Cilico"
    И я должен видеть "Edit"
# language: ru
Функционал: Альбомы
 Чтобы иметь представление об исполнителях
 Как каталогизатор
 Я должен уметь управлять коллекцией альбомов

 Сценарий: Добавление альбома
    Допустим в базе нет альбомов
    И я на странице /index/add
    Если я ввожу "Pendulum" в поле "Artist"
    И я ввожу "In Silico" в поле "Title"
    И нажимаю "Add"
    То я должен видеть "In Silico"
    И я должен видеть "Edit"
<?php
# features/steps/steps.php
$steps->Допустим('/^в базе нет альбомов$/',
   function($world) {
     $albums = new Application_Model_DbTable_Albums();
     $albums->delete(1);
   }
);

<?php
# features/support/bootstrap.php

// Конфигурация и инициализация тестовой среды ZF
# language: ru
Функционал: Альбомы
 Чтобы иметь представление об исполнителях
 Как каталогизатор
 Я должен уметь управлять коллекцией альбомов


 Сценарий: Добавление альбома
    Допустим в базе нет альбомов
    И я на странице /index/add
    Если я ввожу "Pendulum" в поле "Artist"
    И я ввожу "In Silico" в поле "Title"
    И нажимаю "Add"
    То я должен видеть "In Silico"
    И я должен видеть "Edit"
# language: ru
Функционал: Альбомы
 Чтобы иметь представление об исполнителях
 Как каталогизатор
 Я должен уметь управлять коллекцией альбомов

 @javascript
 Сценарий: Добавление альбома
    Допустим в базе нет альбомов
    И я на странице /index/add
    Если я ввожу "Pendulum" в поле "Artist"
    И я ввожу "In Silico" в поле "Title"
    И нажимаю "Add"
    То я должен видеть "In Silico"
    И я должен видеть "Edit"
http://B$%&'.org
http://github.com/behat
http://groups.google.com/behat
  http://knplabs.com/trainings
Вопросы?


http://github.com/behat
http://groups.google.com/behat
  http://knplabs.com/trainings

Más contenido relacionado

Destacado

שיעור רביעי התעדכנות התמצאות ודואר אלקטרוני
שיעור רביעי   התעדכנות התמצאות ודואר אלקטרונישיעור רביעי   התעדכנות התמצאות ודואר אלקטרוני
שיעור רביעי התעדכנות התמצאות ודואר אלקטרוני
haimkarel
 
Dit Is Mijn Lijf
Dit Is Mijn LijfDit Is Mijn Lijf
Dit Is Mijn Lijf
guest2f17d3
 
Goldberg Visual Scanpath Representation
Goldberg Visual Scanpath RepresentationGoldberg Visual Scanpath Representation
Goldberg Visual Scanpath Representation
Kalle
 
M&A Examining Why So Many Fail to Produce the Shareholder Returns Expected
M&A Examining Why So Many Fail to Produce the Shareholder Returns ExpectedM&A Examining Why So Many Fail to Produce the Shareholder Returns Expected
M&A Examining Why So Many Fail to Produce the Shareholder Returns Expected
peregoff
 
Acordo hesperia illa da toxa
Acordo hesperia illa da toxaAcordo hesperia illa da toxa
Acordo hesperia illa da toxa
oscargaliza
 
Album Covers Powerpoint
Album Covers   PowerpointAlbum Covers   Powerpoint
Album Covers Powerpoint
guest9e86f78
 

Destacado (17)

Homophones Lesson
Homophones LessonHomophones Lesson
Homophones Lesson
 
Database Systems - Application Development
Database Systems - Application DevelopmentDatabase Systems - Application Development
Database Systems - Application Development
 
Aws
AwsAws
Aws
 
שיעור רביעי התעדכנות התמצאות ודואר אלקטרוני
שיעור רביעי   התעדכנות התמצאות ודואר אלקטרונישיעור רביעי   התעדכנות התמצאות ודואר אלקטרוני
שיעור רביעי התעדכנות התמצאות ודואר אלקטרוני
 
1merchan
1merchan1merchan
1merchan
 
Ou Milano
Ou MilanoOu Milano
Ou Milano
 
Power point
Power pointPower point
Power point
 
Klingner Fixation Aligned Pupillary Response Averaging
Klingner Fixation Aligned Pupillary Response AveragingKlingner Fixation Aligned Pupillary Response Averaging
Klingner Fixation Aligned Pupillary Response Averaging
 
Dit Is Mijn Lijf
Dit Is Mijn LijfDit Is Mijn Lijf
Dit Is Mijn Lijf
 
Goldberg Visual Scanpath Representation
Goldberg Visual Scanpath RepresentationGoldberg Visual Scanpath Representation
Goldberg Visual Scanpath Representation
 
Muhammad Yustan Portofolio
Muhammad Yustan PortofolioMuhammad Yustan Portofolio
Muhammad Yustan Portofolio
 
2010 Classic Celebrity Golf Tournament
2010 Classic Celebrity Golf Tournament2010 Classic Celebrity Golf Tournament
2010 Classic Celebrity Golf Tournament
 
Cis It 2010 Nrg Agrivis Togni Daniele 100205 R3
Cis It 2010   Nrg Agrivis   Togni Daniele   100205 R3Cis It 2010   Nrg Agrivis   Togni Daniele   100205 R3
Cis It 2010 Nrg Agrivis Togni Daniele 100205 R3
 
M&A Examining Why So Many Fail to Produce the Shareholder Returns Expected
M&A Examining Why So Many Fail to Produce the Shareholder Returns ExpectedM&A Examining Why So Many Fail to Produce the Shareholder Returns Expected
M&A Examining Why So Many Fail to Produce the Shareholder Returns Expected
 
Daugherty Measuring Vergence Over Stereoscopic Video With A Remote Eye Tracker
Daugherty Measuring Vergence Over Stereoscopic Video With A Remote Eye TrackerDaugherty Measuring Vergence Over Stereoscopic Video With A Remote Eye Tracker
Daugherty Measuring Vergence Over Stereoscopic Video With A Remote Eye Tracker
 
Acordo hesperia illa da toxa
Acordo hesperia illa da toxaAcordo hesperia illa da toxa
Acordo hesperia illa da toxa
 
Album Covers Powerpoint
Album Covers   PowerpointAlbum Covers   Powerpoint
Album Covers Powerpoint
 

Más de ZFConf Conference

ZFConf 2011: Создание REST-API для сторонних разработчиков и мобильных устрой...
ZFConf 2011: Создание REST-API для сторонних разработчиков и мобильных устрой...ZFConf 2011: Создание REST-API для сторонних разработчиков и мобильных устрой...
ZFConf 2011: Создание REST-API для сторонних разработчиков и мобильных устрой...
ZFConf Conference
 
ZFConf 2011: Что такое Sphinx, зачем он вообще нужен и как его использовать с...
ZFConf 2011: Что такое Sphinx, зачем он вообще нужен и как его использовать с...ZFConf 2011: Что такое Sphinx, зачем он вообще нужен и как его использовать с...
ZFConf 2011: Что такое Sphinx, зачем он вообще нужен и как его использовать с...
ZFConf Conference
 
ZFConf 2011: Как может помочь среда разработки при написании приложения на Ze...
ZFConf 2011: Как может помочь среда разработки при написании приложения на Ze...ZFConf 2011: Как может помочь среда разработки при написании приложения на Ze...
ZFConf 2011: Как может помочь среда разработки при написании приложения на Ze...
ZFConf Conference
 
ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...
ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...
ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...
ZFConf Conference
 
ZFConf 2011: Гибкая архитектура Zend Framework приложений с использованием De...
ZFConf 2011: Гибкая архитектура Zend Framework приложений с использованием De...ZFConf 2011: Гибкая архитектура Zend Framework приложений с использованием De...
ZFConf 2011: Гибкая архитектура Zend Framework приложений с использованием De...
ZFConf Conference
 
ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...
ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...
ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...
ZFConf Conference
 
ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)
ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)
ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)
ZFConf Conference
 
ZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and DoctrineZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and Doctrine
ZFConf Conference
 
ZFConf 2010: History of e-Shtab.ru
ZFConf 2010: History of e-Shtab.ruZFConf 2010: History of e-Shtab.ru
ZFConf 2010: History of e-Shtab.ru
ZFConf Conference
 
ZFConf 2010: Fotostrana.ru: Prototyping Project with Zend Framework
ZFConf 2010: Fotostrana.ru: Prototyping Project with Zend FrameworkZFConf 2010: Fotostrana.ru: Prototyping Project with Zend Framework
ZFConf 2010: Fotostrana.ru: Prototyping Project with Zend Framework
ZFConf Conference
 
ZFConf 2010: Performance of Zend Framework Applications
ZFConf 2010: Performance of Zend Framework ApplicationsZFConf 2010: Performance of Zend Framework Applications
ZFConf 2010: Performance of Zend Framework Applications
ZFConf Conference
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf Conference
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
ZFConf Conference
 

Más de ZFConf Conference (20)

ZFConf 2012: Кеш без промахов средствами Zend Framework 2 (Евгений Шпилевский)
ZFConf 2012: Кеш без промахов средствами Zend Framework 2 (Евгений Шпилевский)ZFConf 2012: Кеш без промахов средствами Zend Framework 2 (Евгений Шпилевский)
ZFConf 2012: Кеш без промахов средствами Zend Framework 2 (Евгений Шпилевский)
 
ZFConf 2012: Dependency Management в PHP и Zend Framework 2 (Кирилл Чебунин)
ZFConf 2012: Dependency Management в PHP и Zend Framework 2 (Кирилл Чебунин)ZFConf 2012: Dependency Management в PHP и Zend Framework 2 (Кирилл Чебунин)
ZFConf 2012: Dependency Management в PHP и Zend Framework 2 (Кирилл Чебунин)
 
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
 
ZFConf 2012: Проектирование архитектуры, внедрение и организация процесса раз...
ZFConf 2012: Проектирование архитектуры, внедрение и организация процесса раз...ZFConf 2012: Проектирование архитектуры, внедрение и организация процесса раз...
ZFConf 2012: Проектирование архитектуры, внедрение и организация процесса раз...
 
ZFConf 2012: Реализация доступа к СУБД IBM DB2 посредством встраиваемого SQL ...
ZFConf 2012: Реализация доступа к СУБД IBM DB2 посредством встраиваемого SQL ...ZFConf 2012: Реализация доступа к СУБД IBM DB2 посредством встраиваемого SQL ...
ZFConf 2012: Реализация доступа к СУБД IBM DB2 посредством встраиваемого SQL ...
 
ZFConf 2012: Code Generation и Scaffolding в Zend Framework 2 (Виктор Фараздаги)
ZFConf 2012: Code Generation и Scaffolding в Zend Framework 2 (Виктор Фараздаги)ZFConf 2012: Code Generation и Scaffolding в Zend Framework 2 (Виктор Фараздаги)
ZFConf 2012: Code Generation и Scaffolding в Zend Framework 2 (Виктор Фараздаги)
 
ZFConf 2012: Zend Framework 2, a quick start (Enrico Zimuel)
ZFConf 2012: Zend Framework 2, a quick start (Enrico Zimuel)ZFConf 2012: Zend Framework 2, a quick start (Enrico Zimuel)
ZFConf 2012: Zend Framework 2, a quick start (Enrico Zimuel)
 
ZFConf 2011: Создание REST-API для сторонних разработчиков и мобильных устрой...
ZFConf 2011: Создание REST-API для сторонних разработчиков и мобильных устрой...ZFConf 2011: Создание REST-API для сторонних разработчиков и мобильных устрой...
ZFConf 2011: Создание REST-API для сторонних разработчиков и мобильных устрой...
 
ZFConf 2011: Что такое Sphinx, зачем он вообще нужен и как его использовать с...
ZFConf 2011: Что такое Sphinx, зачем он вообще нужен и как его использовать с...ZFConf 2011: Что такое Sphinx, зачем он вообще нужен и как его использовать с...
ZFConf 2011: Что такое Sphinx, зачем он вообще нужен и как его использовать с...
 
ZFConf 2011: Как может помочь среда разработки при написании приложения на Ze...
ZFConf 2011: Как может помочь среда разработки при написании приложения на Ze...ZFConf 2011: Как может помочь среда разработки при написании приложения на Ze...
ZFConf 2011: Как может помочь среда разработки при написании приложения на Ze...
 
ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...
ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...
ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...
 
ZFConf 2011: Гибкая архитектура Zend Framework приложений с использованием De...
ZFConf 2011: Гибкая архитектура Zend Framework приложений с использованием De...ZFConf 2011: Гибкая архитектура Zend Framework приложений с использованием De...
ZFConf 2011: Гибкая архитектура Zend Framework приложений с использованием De...
 
ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...
ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...
ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...
 
ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)
ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)
ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)
 
ZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and DoctrineZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and Doctrine
 
ZFConf 2010: History of e-Shtab.ru
ZFConf 2010: History of e-Shtab.ruZFConf 2010: History of e-Shtab.ru
ZFConf 2010: History of e-Shtab.ru
 
ZFConf 2010: Fotostrana.ru: Prototyping Project with Zend Framework
ZFConf 2010: Fotostrana.ru: Prototyping Project with Zend FrameworkZFConf 2010: Fotostrana.ru: Prototyping Project with Zend Framework
ZFConf 2010: Fotostrana.ru: Prototyping Project with Zend Framework
 
ZFConf 2010: Performance of Zend Framework Applications
ZFConf 2010: Performance of Zend Framework ApplicationsZFConf 2010: Performance of Zend Framework Applications
ZFConf 2010: Performance of Zend Framework Applications
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
 

ZFConf 2011: Behavior Driven Development в PHP и Zend Framework (Константин Кудряшов)

  • 1. BDD в php и ZF
  • 2. Я кто такой @everzet senior from-birth web developer в
  • 3. Я кто такой International speaker Разработчик Behat, Mink http://github.com/everzet Разработчик capifony http://card.everzet.com Разработчик jade.php everzet@knplabs.com Контрибьютор Symfony2 framework Разработчик плагинов для symfony и Symfony2 @everzet senior from-birth web developer в
  • 4. BDD, Symfony2 эксперты Активные контрибуторы open-source проектов Консультанты, аудиторы, тренеры http://knplabs.com
  • 6. История UnitTest Автоматизация тестов
  • 7. TDD Тесты вперед История UnitTest Автоматизация тестов
  • 8. BDD Dan North TDD Тесты вперед История UnitTest Автоматизация тестов
  • 10. - Эволюция-хренолюция... Что не так с TDD?
  • 12. Мы на самом деле говорим о тестах??? Но каким образом тестировать то, чего еще нет? Test-Driven Development
  • 13. На самом деле, мы говорим о дизайне Test-Driven Development
  • 14. Behavior Test-Driven Development © 2003, Dan North
  • 15. BDD был создан как набор конвенций поверх TDD
  • 16. BDD был создан как набор конвенций поверх TDD Тест-кейсы должы составлять предложения testFindsCustomerById() testFailsForDuplicateCustomers()
  • 17. BDD был создан как набор конвенций поверх TDD Тест-кейсы должы составлять предложения testFindsCustomerById() testFailsForDuplicateCustomers() Тест-кейсы должны начинаться со слова “should” shouldFindCustomerById() shouldFailForDuplicateCustomers()
  • 18. BDD был создан как набор конвенций поверх TDD Тест-кейсы должы составлять предложения testFindsCustomerById() testFailsForDuplicateCustomers() Тест-кейсы должны начинаться со слова “should” shouldFindCustomerById() shouldFailForDuplicateCustomers() Класс тест-кейсов должен представлять из себя существительное для кейсов class CustomerTableTest extends PHPUnitTestCase { /** * @Test */ shouldFindCustomerById() ... }
  • 19. АССЕРШЕНЫ тоже TEST-ориентированы ТЕСТируем assertEquals($expected, $actual) assertGreaterThan($expected, $actual) assertInstanceOf($class, $actual)
  • 20. АССЕРШЕНЫ тоже TEST-ориентированы ТЕСТируем Описываем assertEquals($expected, $actual) $actual should be Equals to $expected assertGreaterThan($expected, $actual) $actual should be GreaterThan $expected assertInstanceOf($class, $actual) $actual should be InstanceOf $class
  • 21. История Сначала дизайн Spec BDD UnitTest TDD BDD Тесты вперед Автоматизация тестов Dan North
  • 22. Specификационные BDD Фрэймворки
  • 23. *Spec RSpec by Dave Astels
  • 24. *Spec RSpec by Dave Astels JSpec by TJ Holowaychuk
  • 25. *Spec RSpec by Dave Astels JSpec by TJ Holowaychuk Fabulous by Alex Rudakov
  • 26. RSpec # bowling_spec.rb require 'bowling' describe Bowling, "#score" do it "returns 0 for all gutter game" do bowling = Bowling.new 20.times { bowling.hit(0) } bowling.score.should == 0 end end
  • 27. RSpec # bowling_spec.rb require 'bowling' describe Bowling, "#score" do it "returns 0 for all gutter game" do bowling = Bowling.new 20.times { bowling.hit(0) } bowling.score.should == 0 end end Пишем СПЕЦИФИКАЦИЮ, а не UnitTEST
  • 28. СЦЕНАРНЫЙ BDD photo by dsearls
  • 29. СЛ ОВАРЬ photophoto by dsearls by Horia Varlan
  • 30. о в р с те я те дл СЛ ОВАРЬ photophoto by dsearls by Horia Varlan
  • 31. о в р с те я те дл СЛ ОВАРЬ дл яа на ли ти ко в photophoto by dsearls by Horia Varlan
  • 32. о в р с те я те дл в СЛ ОВАРЬ дл о яа п ер на ло в е ли де ти для ко в photophoto by dsearls by Horia Varlan
  • 33. для в зак р о азч с те и ко я те в дл в СЛ ОВАРЬ дл о яа п ер на ло в е ли де ти для ко в photophoto by dsearls by Horia Varlan
  • 34. для в зак р о азч с те 1 и ко я те в дл в СЛ ОВАРЬ дл о яа п ер на ло в е ли де ти для ко в photophoto by dsearls by Horia Varlan
  • 35. ИСКОРЕНИТ множество проблем ДИЗАЙНА и КОММУНИКАЦИЙ 1 те ры т ес заказчики девелоперы СЛ ОВАРЬ ана лит ики photophoto by dsearls by Horia Varlan
  • 36. НИК АЦИИ К ОММУ photo by joshfassbind.com
  • 37. Story: In order to [A] As a [B] I need [C]
  • 38. Story: Чтобы [A] В качестве [B] Мне нужно [C]
  • 39. Story: Чтобы [A] В качестве [B] Мне нужно [C] A ⎯ добавочное знач. (профит) функционала B ⎯ профитирующая персона (роль) C ⎯ функционал
  • 40. Story: Чтобы [A] В качестве [B] ⎯ Сила данной конструкции в том, что она требует определения профита от функционала еще до его реализации Мне нужно [C] © Dan North A ⎯ добавочное знач. (профит) функционала B ⎯ профитирующая персона (роль) C ⎯ функционал
  • 41. Story: Поведение story ⎯ это ее приемочный критерий! ⎯ если система удовлетворяет все приемочные критерии, то она работает верно; если не выполняет - неверно.
  • 42. Story: In order to ... As a ... I need ...
  • 43. Story: In order to ... As a ... I need ... Given some initial context (the givens), When an event occurs, Then ensure some outcomes.
  • 44. Story: In order to ... As a ... I need ... Given some initial context (the givens), When an event occurs, Then ensure some outcomes. Given some initial context (the givens), When an event occurs, Then ensure some outcomes.
  • 45. Story: In order to ... As a ... I need ... Scenario 1: Given some initial context (the givens), When an event occurs, Then ensure some outcomes. Scenario 2: Given some initial context (the givens), When an event occurs, Then ensure some outcomes.
  • 46. История Сначала дизайн Spec BDD UnitTest TDD BDD Scenario BDD Сначала анализ Тесты вперед Автоматизация тестов Dan North
  • 47. История Сначала дизайн Spec BDD + UnitTest TDD BDD Scenario BDD Сначала анализ Тесты вперед Автоматизация тестов Dan North
  • 48. GHERKINDSL photo by isobel.gordon
  • 49. Story: In order to ... As a ... I need ... Scenario 1: Given some initial context (the givens), When an event occurs, Then ensure some outcomes. Scenario 2: Given some initial context (the givens), When an event occurs, Then ensure some outcomes.
  • 50. Feature: Feature description In order to ... As a ... I need ... Scenario: 1st scenario title Given some initial context (the givens), When an event occurs, Then ensure some outcomes. Scenario: 2nd scenario title Given some initial context (the givens), When an event occurs, Then ensure some outcomes.
  • 51. feature tree Feature: Feature description 1. feature In order to ... As a ... I need ... Scenario: 1st scenario title 2. scenario Given some initial context (the givens) 3. step When an event occurs ... Then ensure some outcomes ... Scenario: 2nd scenario title 2. scenario Given some initial context (the givens) 3. step When an event occurs ... Then ensure some outcomes ...
  • 52. Feature: Feature description In order to ... As a ... I need ... Scenario: 1st scenario title Given some initial context (the givens) When an event occurs Then ensure some outcomes Scenario: 2nd scenario title Given some initial context (the givens) When an event occurs Then ensure some outcomes
  • 53. # language: fr Fonctionnalité: Feature description In order to ... As a ... I need ... Scénario: 1st scenario title Etant donné some initial context (the givens) Lorsque an event occurs Alors ensure some outcomes Scénario: 2nd scenario title Etant donné some initial context (the givens) Lorsque an event occurs Alors ensure some outcomes
  • 54. # language: ja : Feature description In order to ... As a ... I need ... : 1st scenario title some initial context (the givens) an event occurs ensure some outcomes : 2nd scenario title some initial context (the givens) an event occurs ensure some outcomes
  • 55. # language: ru Функционал: Feature description In order to ... As a ... I need ... Сценарий: 1st scenario title Допустим some initial context (the givens) Когда an event occurs То ensure some outcomes Сценарий: 2nd scenario title Допустим some initial context (the givens) Когда an event occurs То ensure some outcomes
  • 56. # language: en-pirate Ahoy matey!: Feature description In order to ... As a ... I need ... Heave to: 1st scenario title Let go and haul some initial context (the givens) Blimey! an event occurs Aye ensure some outcomes Heave to: 2nd scenario title Let go and haul some initial context (the givens) Blimey! an event occurs Aye ensure some outcomes
  • 57. # language: en-pirate Ahoy matey!: Heave to: Let go and haul some initial context (the givens) Blimey! an event occurs Aye ensure some outcomes Heave to: Let go and haul some initial context (the givens) Blimey! an event occurs Aye ensure some outcomes
  • 59.
  • 60. Установка 1. Добавляем pear-channel: $ pear channel-discover pear.behat.org 2. Ставим: $ pear install behat/behat 3. Инициализируем: $ cd path/to/project && behat --init
  • 61. Установка 1. Добавляем pear-channel: $ pear channel-discover pear.behat.org 2. Ставим: $ pear install behat/behat 3. Инициализируем: $ cd path/to/project && behat --init +d features - place your *.feature files here +d features/steps - place step definition files here +f features/steps/steps.php - place some step definitions in this file +d features/support - place support scripts and static files here +f features/support/bootstrap.php - place bootstrap scripts in this file +f features/support/env.php - place environment initialization scripts in this file
  • 62. # language: ru Функционал: Операции над счетом
  • 63. # language: ru Функционал: Операции над счетом Чтобы иметь возможность управлять счетом В качестве клиента Я должен иметь возможность выполнять операции
  • 64. # language: ru Функционал: Операции над счетом Чтобы иметь возможность управлять счетом В качестве клиента Я должен иметь возможность выполнять операции Сценарий: Депозирование средств
  • 65. # language: ru Функционал: Операции над счетом Чтобы иметь возможность управлять счетом В качестве клиента Я должен иметь возможность выполнять операции Сценарий: Депозирование средств Допустим у меня есть банковский счет Если я положу на счет 35$ То на моем счету должно быть 35$
  • 66. 1. feature # language: ru Функционал: Операции над счетом Чтобы иметь возможность управлять счетом В качестве клиента Я должен иметь возможность выполнять операции Сценарий: Депозирование средств 2. scenario Допустим у меня есть банковский счет 3. step Если я положу на счет 35$ ... То на моем счету должно быть 35$ ...
  • 67. ОПРЕДЕЛЕНИЯШАГОВ Допустим у меня есть банковский счет
  • 68. ОПРЕДЕЛЕНИЯШАГОВ Допустим у меня есть банковский счет <?php Допустим('/^у меня есть банковский счет$/');
  • 69. ОПРЕДЕЛЕНИЯШАГОВ Допустим у меня есть банковский счет <?php Допустим('/^у меня есть банковский счет$/', function() { throw new BehatBehatExceptionPending(); } );
  • 70. ОПРЕДЕЛЕНИЯШАГОВ Допустим у меня есть банковский счет <?php $steps->Допустим('/^у меня есть банковский счет$/', function() { throw new BehatBehatExceptionPending(); } );
  • 71. ОПРЕДЕЛЕНИЯШАГОВ Допустим у меня есть банковский счет <?php $steps->Допустим('/^у меня есть банковский счет$/', function() { throw new BehatBehatExceptionPending(); ??? } );
  • 73. ТИПЫРЕЗУЛЬТАТОВШАГОВ 1. Pending шаг ⎯ который throw new BehatBehatExceptionPending();
  • 74. ТИПЫРЕЗУЛЬТАТОВШАГОВ 1. Pending шаг ⎯ который throw new BehatBehatExceptionPending(); 2. Undefined шаг ⎯ у которого нет (не найдено) определений
  • 75. ТИПЫРЕЗУЛЬТАТОВШАГОВ 1. Pending шаг ⎯ который throw new BehatBehatExceptionPending(); 2. Undefined шаг ⎯ у которого нет (не найдено) определений 3. Ambiguous шаг ⎯ который подпадает под несколько определений
  • 76. ТИПЫРЕЗУЛЬТАТОВШАГОВ 1. Pending шаг ⎯ который throw new BehatBehatExceptionPending(); 2. Undefined шаг ⎯ у которого нет (не найдено) определений 3. Ambiguous шаг ⎯ который подпадает под несколько определений 4. Failed шаг ⎯ который throw Exception();
  • 77. ТИПЫРЕЗУЛЬТАТОВШАГОВ 1. Pending шаг ⎯ который throw new BehatBehatExceptionPending(); 2. Undefined шаг ⎯ у которого нет (не найдено) определений 3. Ambiguous шаг ⎯ который подпадает под несколько определений 4. Failed шаг ⎯ который throw Exception(); 5. Skipped шаг ⎯ который идет следом за pending/undefined/failed в сценарии
  • 78. ТИПЫРЕЗУЛЬТАТОВШАГОВ 1. Pending шаг ⎯ который throw new BehatBehatExceptionPending(); 2. Undefined шаг ⎯ у которого нет (не найдено) определений 3. Ambiguous шаг ⎯ который подпадает под несколько определений 4. Failed шаг ⎯ который throw Exception(); 5. Skipped шаг ⎯ который идет следом за pending/undefined/failed в сценарии 6. Passed шаг ⎯ который не кидает эксепшенов
  • 79. ОПРЕДЕЛЕНИЯШАГОВ Допустим у меня есть банковский счет <?php $steps->Допустим('/^у меня есть банковский счет$/', function() { throw new BehatBehatExceptionPending(); } );
  • 80. ОПРЕДЕЛЕНИЯШАГОВ Допустим у меня есть банковский счет <?php $steps->Допустим('/^у меня есть банковский счет$/', function() { throw new BehatBehatExceptionPending(); } ); Если я положу на счет 35$
  • 81. ОПРЕДЕЛЕНИЯШАГОВ Допустим у меня есть банковский счет <?php $steps->Допустим('/^у меня есть банковский счет$/', function() { throw new BehatBehatExceptionPending(); } ); Если я положу на счет 35$ <?php $steps->Если('/^я положу на счет (d+)$$/', function($dollars) { // $dollars === 35 } );
  • 82. ОПРЕДЕЛЕНИЯШАГОВ Допустим у меня есть банковский счет <?php $steps->Допустим('/^у меня есть банковский счет$/', function() { throw new BehatBehatExceptionPending(); } ); Если я положу на счет 35$ <?php $steps->Если('/^я положу на счет (d+)$$/', function($dollars) { // $dollars === 35 } );
  • 83. ОПРЕДЕЛЕНИЯШАГОВ Допустим у меня есть банковский счет <?php $steps->Допустим('/^у меня есть банковский счет$/', function($world) { throw new BehatBehatExceptionPending(); } ); Если я положу на счет 35$ <?php $steps->Если('/^я положу на счет (d+)$$/', function($world, $dollars) { // $dollars === 35 } );
  • 84. ОПРЕДЕЛЕНИЯШАГОВ Допустим у меня есть банковский счет <?php $steps->Допустим('/^у меня есть банковский счет$/', function($world) { $world->account = new BankAccount(); } ); Если я положу на счет 35$ <?php $steps->Если('/^я положу на счет (d+)$$/', function($world, $dollars) { $world->account->deposit($dollars); } );
  • 85. ПРОВЕРЯЕМРЕЗУЛЬТАТЫ То на моем счету должно быть 35$
  • 86. ПРОВЕРЯЕМРЕЗУЛЬТАТЫ То на моем счету должно быть 35$ <?php $steps->То('/^на моем счету должно быть (d+)$$/', function($world, $balance) { if ($balance !== $world->account->getBalance()) { throw new Exception('Неверный баланс!'); } } );
  • 87. ПРОВЕРЯЕМРЕЗУЛЬТАТЫ То на моем счету должно быть 35$ <?php $steps->То('/^на моем счету должно быть (d+)$$/', function($world, $balance) { if ($balance !== $world->account->getBalance()) { throw new Exception('Неверный баланс!'); } } ); То на моем счету должно быть 35$ ( using PHPUnit ) <?php $steps->То('/^на моем счету должно быть (d+)$$/', function($world, $balance) { assertEquals($balance, $world->account->getBalance()); } );
  • 88. ОПРЕДЕЛЕНИЯШАГОВ <?php $steps->Допустим('/^у меня есть банковский счет$/', function($world) { $world->account = new BankAccount(); } ); $steps->Если('/^я положу на счет (d+)$$/', function($world, $dollars) { $world->account->deposit($dollars); } ); $steps->То('/^на моем счету должно быть (d+)$$/', function($world, $balance) { assertEquals($balance, $world->account->getBalance()); } );
  • 89. ОПРЕДЕЛЕНИЯШАГОВ <?php $steps-> Допустим('/^у меня есть банковский счет$/', function($world) { $world->account = new BankAccount(); } )-> Если('/^я положу на счет (d+)$$/', function($world, $dollars) { $world->account->deposit($dollars); } )-> То('/^на моем счету должно быть (d+)$$/', function($world, $balance) { assertEquals($balance, $world->account->getBalance()); } ) ;
  • 90. ЧТО ДАЛЬШЕ? 1. Раскрашиваем: $ behat features/
  • 91. ЧТО ДАЛЬШЕ? 1. Раскрашиваем: $ behat features/ 2. Имплементируем
  • 92. ЧТО ДАЛЬШЕ? 1. Раскрашиваем: $ behat features/ 2. Имплементируем 3. Раскрашиваем
  • 93. ЧТО ДАЛЬШЕ? 1. Раскрашиваем: $ behat features/ 2. Имплементируем 3. Раскрашиваем 4. Описываем новый функционал
  • 94. ЧТО ДАЛЬШЕ? 1. Раскрашиваем: $ behat features/ 2. Имплементируем 3. Раскрашиваем 4. Описываем новый функционал
  • 95. Описание web- приложений
  • 96. M!"#
  • 97. Установка 1. Добавляем pear-channel: $ pear channel-discover pear.behat.org 2. Ставим: $ pear install behat/mink-beta
  • 98. <?php use BehatMinkMink, BehatMinkDriverGoutteDriver, BehatMinkDriverSahiDriver; // инициализируем Mink и регистрируем драйверы $mink = new Mink(); $mink->registerDriver('goutte', new GoutteDriver($startUrl), true); $mink->registerDriver('javascript', new SahiDriver($startUrl, 'firefox')); $mink->registerDriver('custom', new MyCustomDriver($startUrl)); // выполняем действия в стандартном драйвере $mink->switchToDefaultDriver(); $mink->getSession()->getPage()->findLink('Downloads')->click(); echo $mink->getSession()->getPage()->getContent(); // выполняем действия в javascript (Sahi) драйвере $mink->switchToDriver('javascript'); $mink->getSession()->getPage()->findLink('Downloads')->click(); echo $mink->getSession()->getPage()->getContent(); // выполняем действия в кастомном (MyCustomDriver) драйвере $mink->switchToDriver('custom'); $mink->getSession()->getPage()->findLink('Downloads')->click(); echo $mink->getSession()->getPage()->getContent();
  • 99. zF
  • 100. Новый проект 1. Создаем каркас проекта: $ cd path/to/project && zf ...
  • 101. Новый проект 1. Создаем каркас проекта: $ cd path/to/project && zf ... Getting Started with Zend Framework By Rob Allen, www.akrabat.com Document Revision 1.7.6 Copyright © 2006, 2010
  • 102.
  • 103.
  • 104. Новый проект 1. Создаем каркас проекта: $ cd path/to/project && zf ... 2. Инициализируем B$%&': $ behat --init
  • 105. Новый проект 3. Знакомим B$%&' с M!"#: $ vim behat.yml # behat.yml default: environment: parameters: start_url: http://tutorial.zf.dev/ imports: - mink/behat.yml $ vim features/support/bootstrap.php <?php // features/support/bootstrap.php require_once 'PHPUnit/Autoload.php'; require_once 'PHPUnit/Framework/Assert/Functions.php'; require_once 'mink/autoload.php'; $ behat --steps --lang ru
  • 106. # language: ru Функционал: Альбомы Чтобы иметь представление об исполнителях Как каталогизатор Я должен уметь управлять коллекцией альбомов Сценарий: Добавление альбома Допустим я на странице /index/add Если я ввожу "Pendulum" в поле "Artist" И я ввожу "In Silico" в поле "Title" И нажимаю "Add" То я должен видеть "In Cilico" И я должен видеть "Edit"
  • 107.
  • 108. # language: ru Функционал: Альбомы Чтобы иметь представление об исполнителях Как каталогизатор Я должен уметь управлять коллекцией альбомов Сценарий: Добавление альбома Допустим я на странице /index/add Если я ввожу "Pendulum" в поле "Artist" И я ввожу "In Silico" в поле "Title" И нажимаю "Add" То я должен видеть "In Cilico" И я должен видеть "Edit"
  • 109.
  • 110.
  • 111. # language: ru Функционал: Альбомы Чтобы иметь представление об исполнителях Как каталогизатор Я должен уметь управлять коллекцией альбомов Сценарий: Добавление альбома Допустим в базе нет альбомов И я на странице /index/add Если я ввожу "Pendulum" в поле "Artist" И я ввожу "In Silico" в поле "Title" И нажимаю "Add" То я должен видеть "In Silico" И я должен видеть "Edit"
  • 112.
  • 113. <?php # features/steps/steps.php $steps->Допустим('/^в базе нет альбомов$/', function($world) { $albums = new Application_Model_DbTable_Albums(); $albums->delete(1); } ); <?php # features/support/bootstrap.php // Конфигурация и инициализация тестовой среды ZF
  • 114. # language: ru Функционал: Альбомы Чтобы иметь представление об исполнителях Как каталогизатор Я должен уметь управлять коллекцией альбомов Сценарий: Добавление альбома Допустим в базе нет альбомов И я на странице /index/add Если я ввожу "Pendulum" в поле "Artist" И я ввожу "In Silico" в поле "Title" И нажимаю "Add" То я должен видеть "In Silico" И я должен видеть "Edit"
  • 115. # language: ru Функционал: Альбомы Чтобы иметь представление об исполнителях Как каталогизатор Я должен уметь управлять коллекцией альбомов @javascript Сценарий: Добавление альбома Допустим в базе нет альбомов И я на странице /index/add Если я ввожу "Pendulum" в поле "Artist" И я ввожу "In Silico" в поле "Title" И нажимаю "Add" То я должен видеть "In Silico" И я должен видеть "Edit"