SlideShare a Scribd company logo
1 of 120
Download to read offline
BDD   в php
Я
кто
       такой




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



      International speaker
      Разработчик Behat, Mink                   http://github.com/everzet
      Разработчик jade.php                       http://card.everzet.com
      Разработчик capifony                       everzet@knplabs.com
      Core-contributor 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-ориентированы
АССЕРШЕНЫ
     тоже 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 Фрэймворки
*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
История

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




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




                                           Dan North
СЦЕНАРНЫЙ

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
Наратив:




 In order to [A]
 As a [B]
 I need [C]
Наратив:




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




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




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

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




 A ⎯ добавочное знач. (профит) функционала
 B ⎯ профитирующая персона (роль)
 C ⎯ функционал
Поведение 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
Функционал: Утилита ls
Чтобы узнать содержимое директории
Как пользователь UNIX
Я должен иметь утилиту листинга директорий
# language: ru
Функционал: Утилита ls
Чтобы узнать содержимое директории
Как пользователь UNIX
Я должен иметь утилиту листинга директорий


  Сценарий: 2 файла в директории
# language: ru
Функционал: Утилита ls
Чтобы узнать содержимое директории
Как пользователь UNIX
Я должен иметь утилиту листинга директорий


  Сценарий: 2 файла в директории
     Допустим я нахожусь в директории “test1”
     Если я исполню “ls”
     То я должен увидеть:
       """
       file_one.txt
       file_foo.txt
       """
# language: ru                                       1. feature
  Функционал: Утилита ls
    Чтобы узнать содержимое директории
    Как пользователь UNIX
    Я должен иметь утилиту листинга директорий


              Сценарий: 2 файла в директории
                Допустим я нахожусь в директории “test1”
2. scenario




                Если я исполню “ls”
                То я должен увидеть:
                  """
                  file_one.txt
                  file_foo.txt
                  """
# language: ru
Функционал: Утилита ls
Чтобы узнать содержимое директории
Как пользователь UNIX
Я должен иметь утилиту листинга директорий


  Сценарий: 2 файла в директории
     Допустим я нахожусь в директории “test1”
     Если я исполню “ls”
     То я должен увидеть:
       """
       file_one.txt
       file_foo.txt
       """
ОПРЕДЕЛЕНИЯШАГОВ
Допустим я нахожусь в директории “test1”
ОПРЕДЕЛЕНИЯШАГОВ
Допустим я нахожусь в директории “test1”
 <?php

 Допустим('/^я нахожусь в директории “(.*)”$/');
ОПРЕДЕЛЕНИЯШАГОВ
Допустим я нахожусь в директории “test1”
 <?php

 Допустим('/^я нахожусь в директории “(.*)”$/',
    function() {
      throw new BehatBehatExceptionPending();
    }
 );
ОПРЕДЕЛЕНИЯШАГОВ
Допустим я нахожусь в директории “test1”
 <?php

 $steps->Допустим('/^я нахожусь в директории “(.*)”$/',
    function() {
      throw new BehatBehatExceptionPending();
    }
 );
ОПРЕДЕЛЕНИЯШАГОВ
Допустим я нахожусь в директории “test1”
 <?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 шаг ⎯ который не кидает эксепшенов
ОПРЕДЕЛЕНИЯШАГОВ
Допустим я нахожусь в директории “test1”
 <?php

 $steps->Допустим('/^я нахожусь в директории “(.*)”$/',
    function() {
      throw new BehatBehatExceptionPending();
    }
 );
ОПРЕДЕЛЕНИЯШАГОВ
Допустим я нахожусь в директории “test1”
 <?php

 $steps->Допустим('/^я нахожусь в директории “(.*)”$/',
    function() {
      throw new BehatBehatExceptionPending();
    }
 );


Если я исполню “ls”
ОПРЕДЕЛЕНИЯШАГОВ
Допустим я нахожусь в директории “test1”
 <?php

 $steps->Допустим('/^я нахожусь в директории “(.*)”$/',
    function() {
      throw new BehatBehatExceptionPending();
    }
 );


Если я исполню “ls”
 <?php

 $steps->Если('/^я исполню “(.*)”$/',
    function($dollars) {
      throw new BehatBehatExceptionPending();
    }
 );
ОПРЕДЕЛЕНИЯШАГОВ
Допустим я нахожусь в директории “test1”
 <?php

 $steps->Допустим('/^я нахожусь в директории “(.*)”$/',
    function($dir) {
      // $dir === “test1”
    }
 );


Если я исполню “ls”
 <?php

 $steps->Если('/^я исполню “(.*)”$/',
    function($command) {
      // $command === “ls”
    }
 );
ОПРЕДЕЛЕНИЯШАГОВ
Допустим я нахожусь в директории “test1”
 <?php

 $steps->Допустим('/^я нахожусь в директории “(.*)”$/',
    function($dir) {
      chdir('fixtures/' . $dir);
    }
 );


Если я исполню “ls”
 <?php

 $steps->Если('/^я исполню “(.*)”$/',
    function($command) {
      exec($command, $output);
      $output = trim(implode(“n”, $output));
    }
 );
ОПРЕДЕЛЕНИЯШАГОВ
Допустим я нахожусь в директории “test1”
 <?php

 $steps->Допустим('/^я нахожусь в директории “(.*)”$/',
    function($world, $dir) {
      chdir('fixtures/' . $dir);
    }
 );


Если я исполню “ls”
 <?php

 $steps->Если('/^я исполню “(.*)”$/',
    function($world, $command) {
      exec($command, $output);
      $world->output = trim(implode(“n”, $output));
    }
 );
ПРОВЕРЯЕМРЕЗУЛЬТАТЫ
То я должен увидеть:
ПРОВЕРЯЕМРЕЗУЛЬТАТЫ
То я должен увидеть:
 <?php

 $steps->То('/^я должен увидеть:$/',
    function($world, $string) {
      if ($world->output !== (string) $string) {
        throw new Exception('Неверный вывод');
      }
    }
 );
ПРОВЕРЯЕМРЕЗУЛЬТАТЫ
То я должен увидеть:
 <?php

 $steps->То('/^я должен увидеть:$/',
    function($world, $string) {
      if ($world->output !== (string) $string) {
        throw new Exception('Неверный вывод');
      }
    }
 );


То я должен увидеть: (               using
                                   PHPUnit   )
 <?php

 $steps->То('/^я должен увидеть:$/',
    function($world, $string) {
      assertEquals((string) $string, $world->output);
    }
 );
ОПРЕДЕЛЕНИЯШАГОВ
 <?php

 $steps->Допустим('/^я нахожусь в директории “(.*)”$/',
    function($world, $dir) {
      chdir('fixtures/' . $dir);
    }
 );

 $steps->Если('/^я исполню “(.*)”$/',
    function($world, $command) {
      exec($command, $output);
      $world->output = trim(implode(“n”, $output));
    }
 );

 $steps->То('/^я должен увидеть:$/',
    function($world, $string) {
      assertEquals((string) $string, $world->output);
    }
 );
ОПРЕДЕЛЕНИЯШАГОВ
 <?php

 $steps->

     Допустим('/^я нахожусь в директории “(.*)”$/',
       function($world, $dir) {
         chdir('fixtures/' . $dir);
       }
     )->

     Если('/^я исполню “(.*)”$/',
       function($world, $command) {
         exec($command, $output);
         $world->output = trim(implode(“n”, $output));
       }
     )->

     То('/^я должен увидеть:$/',
       function($world, $string) {
         assertEquals((string) $string, $world->output);
       }
     )
 ;
Workflow

 1. Описываем поведение
Workflow

 1. Описываем поведение
 2. Проверяем поведение ( $                 )
                              behat features/
Workflow

 1. Описываем поведение
 2. Проверяем поведение ( $                 )
                              behat features/

 3. Реализуем поведение
Workflow

 1. Описываем поведение
 2. Проверяем поведение ( $                 )
                              behat features/

 3. Реализуем поведение
 4. Проверяем поведение
Workflow

 1. Описываем поведение
 2. Проверяем поведение ( $                 )
                              behat features/

 3. Реализуем поведение
 4. Проверяем поведение
Workflow

 1. Описываем поведение
 2. Проверяем поведение ( $                 )
                              behat features/

 3. Реализуем поведение:
   3.1. Пишем спеки
   3.2. Прогоняем спеки
   3.3. Пишем код
   3.4. Прогоняем спеки

 4. Проверяем поведение
Workflow

 1. Описываем поведение
 2. Проверяем поведение ( $                 )
                              behat features/

 3. Реализуем поведение:
   3.1. Пишем спеки
   3.2. Прогоняем спеки
   3.3. Пишем код
   3.4. Прогоняем спеки

 4. Проверяем поведение
Описание web-
      приложений
M!"#
Установка



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

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

use BehatMinkMink,
    BehatMinkSession,
    BehatMinkDriverGoutteDriver,
    BehatMinkDriverSahiDriver;


// инициализируем Mink и сессии
$mink = new Mink();
$mink->registerSession('goutte',
    new Session(new GoutteDriver($startUrl))
);
$mink->registerSession('javascript',,
    new Session(new SahiDriver($startUrl, 'firefox'))
);

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

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

 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

More Related Content

Viewers also liked

Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICKonstantin Kudryashov
 
Bridging The Communication Gap, Fast
Bridging The Communication Gap, Fast Bridging The Communication Gap, Fast
Bridging The Communication Gap, Fast Konstantin Kudryashov
 
Moving away from legacy code (AgileCymru)
Moving away from legacy code  (AgileCymru)Moving away from legacy code  (AgileCymru)
Moving away from legacy code (AgileCymru)Konstantin Kudryashov
 
Moving away from legacy code with BDD
Moving away from legacy code with BDDMoving away from legacy code with BDD
Moving away from legacy code with BDDKonstantin Kudryashov
 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mockingKonstantin Kudryashov
 
RESTful API development with Symfony2
RESTful API development with Symfony2RESTful API development with Symfony2
RESTful API development with Symfony2Taras Omelianenko
 

Viewers also liked (8)

Modern Agile Project Toolbox
Modern Agile Project ToolboxModern Agile Project Toolbox
Modern Agile Project Toolbox
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
 
Bridging The Communication Gap, Fast
Bridging The Communication Gap, Fast Bridging The Communication Gap, Fast
Bridging The Communication Gap, Fast
 
Moving away from legacy code (AgileCymru)
Moving away from legacy code  (AgileCymru)Moving away from legacy code  (AgileCymru)
Moving away from legacy code (AgileCymru)
 
Taking back BDD
Taking back BDDTaking back BDD
Taking back BDD
 
Moving away from legacy code with BDD
Moving away from legacy code with BDDMoving away from legacy code with BDD
Moving away from legacy code with BDD
 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mocking
 
RESTful API development with Symfony2
RESTful API development with Symfony2RESTful API development with Symfony2
RESTful API development with Symfony2
 

Recently uploaded (9)

СИСТЕМА ОЦЕНКИ УЯЗВИМОСТЕЙ CVSS 4.0 / CVSS v4.0 [RU].pdf
СИСТЕМА ОЦЕНКИ УЯЗВИМОСТЕЙ CVSS 4.0 / CVSS v4.0 [RU].pdfСИСТЕМА ОЦЕНКИ УЯЗВИМОСТЕЙ CVSS 4.0 / CVSS v4.0 [RU].pdf
СИСТЕМА ОЦЕНКИ УЯЗВИМОСТЕЙ CVSS 4.0 / CVSS v4.0 [RU].pdf
 
ИСТОЧНИКИ ИННОВАЦИОННОСТИ КИТАЯ (ПО ВЕРСИИ DGAP) | The Sources of China’s Inn...
ИСТОЧНИКИ ИННОВАЦИОННОСТИ КИТАЯ (ПО ВЕРСИИ DGAP) | The Sources of China’s Inn...ИСТОЧНИКИ ИННОВАЦИОННОСТИ КИТАЯ (ПО ВЕРСИИ DGAP) | The Sources of China’s Inn...
ИСТОЧНИКИ ИННОВАЦИОННОСТИ КИТАЯ (ПО ВЕРСИИ DGAP) | The Sources of China’s Inn...
 
CVE. The Fortra's GoAnywhere MFT [RU].pdf
CVE. The Fortra's GoAnywhere MFT [RU].pdfCVE. The Fortra's GoAnywhere MFT [RU].pdf
CVE. The Fortra's GoAnywhere MFT [RU].pdf
 
Malware. DCRAT (DARK CRYSTAL RAT) [RU].pdf
Malware. DCRAT (DARK CRYSTAL RAT) [RU].pdfMalware. DCRAT (DARK CRYSTAL RAT) [RU].pdf
Malware. DCRAT (DARK CRYSTAL RAT) [RU].pdf
 
Cyberprint. Dark Pink Apt Group [RU].pdf
Cyberprint. Dark Pink Apt Group [RU].pdfCyberprint. Dark Pink Apt Group [RU].pdf
Cyberprint. Dark Pink Apt Group [RU].pdf
 
Ransomware_Q3 2023. The report [RU].pdf
Ransomware_Q3 2023.  The report [RU].pdfRansomware_Q3 2023.  The report [RU].pdf
Ransomware_Q3 2023. The report [RU].pdf
 
MS Navigating Incident Response [RU].pdf
MS Navigating Incident Response [RU].pdfMS Navigating Incident Response [RU].pdf
MS Navigating Incident Response [RU].pdf
 
2023 Q4. The Ransomware report. [RU].pdf
2023 Q4. The Ransomware report. [RU].pdf2023 Q4. The Ransomware report. [RU].pdf
2023 Q4. The Ransomware report. [RU].pdf
 
Cyber Defense Doctrine Managing the Risk Full Applied Guide to Organizational...
Cyber Defense Doctrine Managing the Risk Full Applied Guide to Organizational...Cyber Defense Doctrine Managing the Risk Full Applied Guide to Organizational...
Cyber Defense Doctrine Managing the Risk Full Applied Guide to Organizational...
 

BDD в PHP с Behat и Mink

  • 1. BDD в php
  • 2. Я кто такой @ everzet senior from-birth web developer в
  • 3. Я кто такой International speaker Разработчик Behat, Mink http://github.com/everzet Разработчик jade.php http://card.everzet.com Разработчик capifony everzet@knplabs.com Core-contributor 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() ... }
  • 20. АССЕРШЕНЫ тоже TEST-ориентированы ТЕСТируем assertEquals($expected, $actual) assertGreaterThan($expected, $actual) assertInstanceOf($class, $actual)
  • 21. АССЕРШЕНЫ тоже 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
  • 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. История Сначала дизайн Spec BDD UnitTest TDD BDD Тесты вперед Автоматизация тестов Dan North
  • 29. СЦЕНАРНЫЙ BDD photo by dsearls
  • 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. для в зак р о азч с те и ко я те в дл в СЛ ОВАРЬ дл о яа п ер на ло в е ли де ти для ко в photophoto by dsearls by Horia Varlan
  • 35. для в зак р о азч с те 1 и ко я те в дл в СЛ ОВАРЬ дл о яа п ер на ло в е ли де ти для ко в photophoto by dsearls by Horia Varlan
  • 36. ИСКОРЕНИТ множество проблем ДИЗАЙНА и КОММУНИКАЦИЙ 1 те ры т ес заказчики девелоперы СЛ ОВАРЬ ана лит ики photophoto by dsearls by Horia Varlan
  • 37. НИК АЦИИ К ОММУ photo by joshfassbind.com
  • 38. Наратив: In order to [A] As a [B] I need [C]
  • 39. Наратив: Чтобы [A] В качестве [B] Мне нужно [C]
  • 40. Наратив: Чтобы [A] В качестве [B] Мне нужно [C] A ⎯ добавочное знач. (профит) функционала B ⎯ профитирующая персона (роль) C ⎯ функционал
  • 41. Наратив: Чтобы [A] В качестве [B] ⎯ Сила данной конструкции в том, что она требует определения профита от функционала еще до его реализации Мне нужно [C] © Dan North A ⎯ добавочное знач. (профит) функционала B ⎯ профитирующая персона (роль) C ⎯ функционал
  • 42. Поведение story ⎯ это ее приемочный критерий! ⎯ если система удовлетворяет все приемочные критерии, то она работает верно; если не выполняет - неверно.
  • 43. Story: In order to ... As a ... I need ...
  • 44. Story: In order to ... As a ... I need ... Given some initial context (the givens), When an event occurs, Then ensure some outcomes.
  • 45. 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.
  • 46. 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.
  • 47. История Сначала дизайн Spec BDD UnitTest TDD BDD Scenario BDD Сначала анализ Тесты вперед Автоматизация тестов Dan North
  • 48. История Сначала дизайн Spec BDD + UnitTest TDD BDD Scenario BDD Сначала анализ Тесты вперед Автоматизация тестов Dan North
  • 49. GHERKINDSL photo by isobel.gordon
  • 50. 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.
  • 51. 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.
  • 52. 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 ...
  • 53. 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
  • 54. # 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
  • 55. # 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
  • 56. # 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
  • 57. # 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
  • 58. # 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.
  • 61. Установка 1. Добавляем pear-channel: $ pear channel-discover pear.behat.org 2. Ставим: $ pear install behat/behat 3. Инициализируем: $ cd path/to/project && behat --init
  • 62. Установка 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
  • 63. # language: ru Функционал: Утилита ls Чтобы узнать содержимое директории Как пользователь UNIX Я должен иметь утилиту листинга директорий
  • 64. # language: ru Функционал: Утилита ls Чтобы узнать содержимое директории Как пользователь UNIX Я должен иметь утилиту листинга директорий Сценарий: 2 файла в директории
  • 65. # language: ru Функционал: Утилита ls Чтобы узнать содержимое директории Как пользователь UNIX Я должен иметь утилиту листинга директорий Сценарий: 2 файла в директории Допустим я нахожусь в директории “test1” Если я исполню “ls” То я должен увидеть: """ file_one.txt file_foo.txt """
  • 66. # language: ru 1. feature Функционал: Утилита ls Чтобы узнать содержимое директории Как пользователь UNIX Я должен иметь утилиту листинга директорий Сценарий: 2 файла в директории Допустим я нахожусь в директории “test1” 2. scenario Если я исполню “ls” То я должен увидеть: """ file_one.txt file_foo.txt """
  • 67. # language: ru Функционал: Утилита ls Чтобы узнать содержимое директории Как пользователь UNIX Я должен иметь утилиту листинга директорий Сценарий: 2 файла в директории Допустим я нахожусь в директории “test1” Если я исполню “ls” То я должен увидеть: """ file_one.txt file_foo.txt """
  • 69. ОПРЕДЕЛЕНИЯШАГОВ Допустим я нахожусь в директории “test1” <?php Допустим('/^я нахожусь в директории “(.*)”$/');
  • 70. ОПРЕДЕЛЕНИЯШАГОВ Допустим я нахожусь в директории “test1” <?php Допустим('/^я нахожусь в директории “(.*)”$/', function() { throw new BehatBehatExceptionPending(); } );
  • 71. ОПРЕДЕЛЕНИЯШАГОВ Допустим я нахожусь в директории “test1” <?php $steps->Допустим('/^я нахожусь в директории “(.*)”$/', function() { throw new BehatBehatExceptionPending(); } );
  • 72. ОПРЕДЕЛЕНИЯШАГОВ Допустим я нахожусь в директории “test1” <?php $steps->Допустим('/^я нахожусь в директории “(.*)”$/', function() { throw new BehatBehatExceptionPending(); ??? } );
  • 74. ТИПЫРЕЗУЛЬТАТОВШАГОВ 1. Pending шаг ⎯ который throw new BehatBehatExceptionPending();
  • 75. ТИПЫРЕЗУЛЬТАТОВШАГОВ 1. Pending шаг ⎯ который throw new BehatBehatExceptionPending(); 2. Undefined шаг ⎯ у которого нет (не найдено) определений
  • 76. ТИПЫРЕЗУЛЬТАТОВШАГОВ 1. Pending шаг ⎯ который throw new BehatBehatExceptionPending(); 2. Undefined шаг ⎯ у которого нет (не найдено) определений 3. Ambiguous шаг ⎯ который подпадает под несколько определений
  • 77. ТИПЫРЕЗУЛЬТАТОВШАГОВ 1. Pending шаг ⎯ который throw new BehatBehatExceptionPending(); 2. Undefined шаг ⎯ у которого нет (не найдено) определений 3. Ambiguous шаг ⎯ который подпадает под несколько определений 4. Failed шаг ⎯ который throw Exception();
  • 78. ТИПЫРЕЗУЛЬТАТОВШАГОВ 1. Pending шаг ⎯ который throw new BehatBehatExceptionPending(); 2. Undefined шаг ⎯ у которого нет (не найдено) определений 3. Ambiguous шаг ⎯ который подпадает под несколько определений 4. Failed шаг ⎯ который throw Exception(); 5. Skipped шаг ⎯ который идет следом за pending/undefined/failed в сценарии
  • 79. ТИПЫРЕЗУЛЬТАТОВШАГОВ 1. Pending шаг ⎯ который throw new BehatBehatExceptionPending(); 2. Undefined шаг ⎯ у которого нет (не найдено) определений 3. Ambiguous шаг ⎯ который подпадает под несколько определений 4. Failed шаг ⎯ который throw Exception(); 5. Skipped шаг ⎯ который идет следом за pending/undefined/failed в сценарии 6. Passed шаг ⎯ который не кидает эксепшенов
  • 80. ОПРЕДЕЛЕНИЯШАГОВ Допустим я нахожусь в директории “test1” <?php $steps->Допустим('/^я нахожусь в директории “(.*)”$/', function() { throw new BehatBehatExceptionPending(); } );
  • 81. ОПРЕДЕЛЕНИЯШАГОВ Допустим я нахожусь в директории “test1” <?php $steps->Допустим('/^я нахожусь в директории “(.*)”$/', function() { throw new BehatBehatExceptionPending(); } ); Если я исполню “ls”
  • 82. ОПРЕДЕЛЕНИЯШАГОВ Допустим я нахожусь в директории “test1” <?php $steps->Допустим('/^я нахожусь в директории “(.*)”$/', function() { throw new BehatBehatExceptionPending(); } ); Если я исполню “ls” <?php $steps->Если('/^я исполню “(.*)”$/', function($dollars) { throw new BehatBehatExceptionPending(); } );
  • 83. ОПРЕДЕЛЕНИЯШАГОВ Допустим я нахожусь в директории “test1” <?php $steps->Допустим('/^я нахожусь в директории “(.*)”$/', function($dir) { // $dir === “test1” } ); Если я исполню “ls” <?php $steps->Если('/^я исполню “(.*)”$/', function($command) { // $command === “ls” } );
  • 84. ОПРЕДЕЛЕНИЯШАГОВ Допустим я нахожусь в директории “test1” <?php $steps->Допустим('/^я нахожусь в директории “(.*)”$/', function($dir) { chdir('fixtures/' . $dir); } ); Если я исполню “ls” <?php $steps->Если('/^я исполню “(.*)”$/', function($command) { exec($command, $output); $output = trim(implode(“n”, $output)); } );
  • 85. ОПРЕДЕЛЕНИЯШАГОВ Допустим я нахожусь в директории “test1” <?php $steps->Допустим('/^я нахожусь в директории “(.*)”$/', function($world, $dir) { chdir('fixtures/' . $dir); } ); Если я исполню “ls” <?php $steps->Если('/^я исполню “(.*)”$/', function($world, $command) { exec($command, $output); $world->output = trim(implode(“n”, $output)); } );
  • 87. ПРОВЕРЯЕМРЕЗУЛЬТАТЫ То я должен увидеть: <?php $steps->То('/^я должен увидеть:$/', function($world, $string) { if ($world->output !== (string) $string) { throw new Exception('Неверный вывод'); } } );
  • 88. ПРОВЕРЯЕМРЕЗУЛЬТАТЫ То я должен увидеть: <?php $steps->То('/^я должен увидеть:$/', function($world, $string) { if ($world->output !== (string) $string) { throw new Exception('Неверный вывод'); } } ); То я должен увидеть: ( using PHPUnit ) <?php $steps->То('/^я должен увидеть:$/', function($world, $string) { assertEquals((string) $string, $world->output); } );
  • 89. ОПРЕДЕЛЕНИЯШАГОВ <?php $steps->Допустим('/^я нахожусь в директории “(.*)”$/', function($world, $dir) { chdir('fixtures/' . $dir); } ); $steps->Если('/^я исполню “(.*)”$/', function($world, $command) { exec($command, $output); $world->output = trim(implode(“n”, $output)); } ); $steps->То('/^я должен увидеть:$/', function($world, $string) { assertEquals((string) $string, $world->output); } );
  • 90. ОПРЕДЕЛЕНИЯШАГОВ <?php $steps-> Допустим('/^я нахожусь в директории “(.*)”$/', function($world, $dir) { chdir('fixtures/' . $dir); } )-> Если('/^я исполню “(.*)”$/', function($world, $command) { exec($command, $output); $world->output = trim(implode(“n”, $output)); } )-> То('/^я должен увидеть:$/', function($world, $string) { assertEquals((string) $string, $world->output); } ) ;
  • 91. Workflow 1. Описываем поведение
  • 92. Workflow 1. Описываем поведение 2. Проверяем поведение ( $ ) behat features/
  • 93. Workflow 1. Описываем поведение 2. Проверяем поведение ( $ ) behat features/ 3. Реализуем поведение
  • 94. Workflow 1. Описываем поведение 2. Проверяем поведение ( $ ) behat features/ 3. Реализуем поведение 4. Проверяем поведение
  • 95. Workflow 1. Описываем поведение 2. Проверяем поведение ( $ ) behat features/ 3. Реализуем поведение 4. Проверяем поведение
  • 96. Workflow 1. Описываем поведение 2. Проверяем поведение ( $ ) behat features/ 3. Реализуем поведение: 3.1. Пишем спеки 3.2. Прогоняем спеки 3.3. Пишем код 3.4. Прогоняем спеки 4. Проверяем поведение
  • 97. Workflow 1. Описываем поведение 2. Проверяем поведение ( $ ) behat features/ 3. Реализуем поведение: 3.1. Пишем спеки 3.2. Прогоняем спеки 3.3. Пишем код 3.4. Прогоняем спеки 4. Проверяем поведение
  • 98. Описание web- приложений
  • 99. M!"#
  • 100. Установка 1. Добавляем pear-channel: $ pear channel-discover pear.behat.org 2. Ставим: $ pear install behat/mink-beta
  • 101. <?php use BehatMinkMink, BehatMinkSession, BehatMinkDriverGoutteDriver, BehatMinkDriverSahiDriver; // инициализируем Mink и сессии $mink = new Mink(); $mink->registerSession('goutte', new Session(new GoutteDriver($startUrl)) ); $mink->registerSession('javascript',, new Session(new SahiDriver($startUrl, 'firefox')) ); // выполняем действия в стандартном драйвере $mink->getSession('goutte')->getPage()->clickLink('Downloads'); echo $mink->getSession('goutte')->getPage()->getContent(); // выполняем действия в javascript (Sahi) сессии $mink->getSession('javascript')->getPage()->clickLink('Downloads'); echo $mink->getSession('javascript')->getPage()->getContent();
  • 102. Новый проект 1. Создаем каркас проекта: $ cd path/to/project && zf ...
  • 103. Новый проект 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.
  • 105.
  • 106. Новый проект 1. Создаем каркас проекта: $ cd path/to/project && zf ... 2. Инициализируем B$%&': $ behat --init
  • 107. Новый проект 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
  • 108. # language: ru Функционал: Альбомы Чтобы иметь представление об исполнителях Как каталогизатор Я должен уметь управлять коллекцией альбомов Сценарий: Добавление альбома Допустим я на странице /index/add Если я ввожу "Pendulum" в поле "Artist" И я ввожу "In Silico" в поле "Title" И нажимаю "Add" То я должен видеть "In Cilico" И я должен видеть "Edit"
  • 109.
  • 110. # language: ru Функционал: Альбомы Чтобы иметь представление об исполнителях Как каталогизатор Я должен уметь управлять коллекцией альбомов Сценарий: Добавление альбома Допустим я на странице /index/add Если я ввожу "Pendulum" в поле "Artist" И я ввожу "In Silico" в поле "Title" И нажимаю "Add" То я должен видеть "In Cilico" И я должен видеть "Edit"
  • 111.
  • 112.
  • 113. # language: ru Функционал: Альбомы Чтобы иметь представление об исполнителях Как каталогизатор Я должен уметь управлять коллекцией альбомов Сценарий: Добавление альбома Допустим в базе нет альбомов И я на странице /index/add Если я ввожу "Pendulum" в поле "Artist" И я ввожу "In Silico" в поле "Title" И нажимаю "Add" То я должен видеть "In Silico" И я должен видеть "Edit"
  • 114.
  • 115. <?php # features/steps/steps.php $steps->Допустим('/^в базе нет альбомов$/', function($world) { $albums = new Application_Model_DbTable_Albums(); $albums->delete(1); } ); <?php # features/support/bootstrap.php // Конфигурация и инициализация тестовой среды ZF
  • 116. # language: ru Функционал: Альбомы Чтобы иметь представление об исполнителях Как каталогизатор Я должен уметь управлять коллекцией альбомов Сценарий: Добавление альбома Допустим в базе нет альбомов И я на странице /index/add Если я ввожу "Pendulum" в поле "Artist" И я ввожу "In Silico" в поле "Title" И нажимаю "Add" То я должен видеть "In Silico" И я должен видеть "Edit"
  • 117. # language: ru Функционал: Альбомы Чтобы иметь представление об исполнителях Как каталогизатор Я должен уметь управлять коллекцией альбомов @javascript Сценарий: Добавление альбома Допустим в базе нет альбомов И я на странице /index/add Если я ввожу "Pendulum" в поле "Artist" И я ввожу "In Silico" в поле "Title" И нажимаю "Add" То я должен видеть "In Silico" И я должен видеть "Edit"