SlideShare a Scribd company logo
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
Приемочные критерии
должны быть исполняемы!
ZFConf 2011: Behavior Driven Development в PHP и Zend Framework (Константин Кудряшов)
Установка

 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
ZFConf 2011: Behavior Driven Development в PHP и Zend Framework (Константин Кудряшов)
ZFConf 2011: Behavior Driven Development в PHP и Zend Framework (Константин Кудряшов)
Новый проект

 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"
ZFConf 2011: Behavior Driven Development в PHP и Zend Framework (Константин Кудряшов)
# language: ru
Функционал: Альбомы
 Чтобы иметь представление об исполнителях
 Как каталогизатор
 Я должен уметь управлять коллекцией альбомов


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

 Сценарий: Добавление альбома
    Допустим в базе нет альбомов
    И я на странице /index/add
    Если я ввожу "Pendulum" в поле "Artist"
    И я ввожу "In Silico" в поле "Title"
    И нажимаю "Add"
    То я должен видеть "In Silico"
    И я должен видеть "Edit"
ZFConf 2011: Behavior Driven Development в PHP и Zend Framework (Константин Кудряшов)
<?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

More Related Content

PDF
BDD в PHP с Behat и Mink
PPT
TEMA 4B Vocabulario
PPT
Engagement Party
PDF
Lua on Steroids
PDF
Creating a Leak-Free Water Containment Tank
PPT
Html
PDF
Nagamatsu Gaze Estimation Method Based On An Aspherical Model Of The Cornea S...
BDD в PHP с Behat и Mink
TEMA 4B Vocabulario
Engagement Party
Lua on Steroids
Creating a Leak-Free Water Containment Tank
Html
Nagamatsu Gaze Estimation Method Based On An Aspherical Model Of The Cornea S...

Viewers also liked (17)

PPTX
Homophones Lesson
PDF
Database Systems - Application Development
PPTX
PDF
שיעור רביעי התעדכנות התמצאות ודואר אלקטרוני
PDF
1merchan
PDF
Ou Milano
PDF
Klingner Fixation Aligned Pupillary Response Averaging
PPT
Dit Is Mijn Lijf
PDF
Goldberg Visual Scanpath Representation
PDF
Muhammad Yustan Portofolio
PDF
2010 Classic Celebrity Golf Tournament
PPT
Cis It 2010 Nrg Agrivis Togni Daniele 100205 R3
PPT
M&A Examining Why So Many Fail to Produce the Shareholder Returns Expected
PDF
Daugherty Measuring Vergence Over Stereoscopic Video With A Remote Eye Tracker
DOC
Acordo hesperia illa da toxa
PPT
Album Covers Powerpoint
Homophones Lesson
Database Systems - Application Development
שיעור רביעי התעדכנות התמצאות ודואר אלקטרוני
1merchan
Ou Milano
Klingner Fixation Aligned Pupillary Response Averaging
Dit Is Mijn Lijf
Goldberg Visual Scanpath Representation
Muhammad Yustan Portofolio
2010 Classic Celebrity Golf Tournament
Cis It 2010 Nrg Agrivis Togni Daniele 100205 R3
M&A Examining Why So Many Fail to Produce the Shareholder Returns Expected
Daugherty Measuring Vergence Over Stereoscopic Video With A Remote Eye Tracker
Acordo hesperia illa da toxa
Album Covers Powerpoint
Ad

More from ZFConf Conference (20)

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

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