SlideShare a Scribd company logo
BEHAVIOR
           DRIVEN
           DEVELOPMENT
           ДЛЯ PHP ПРОЕКТОВ


@everzet
КТО Я
                symfony-разработчик
                С 2007 года
                СОЗДАТЕЛЬ
                BEHAT
                ВЕДУЩИЙ РАЗРАБОТЧИК

               DEV.BY
ПРОГРАММИСТ
С РОЖДЕНИЯ http://everzet.com
РАЗРАБОТКА
INSIDE-OUT
Тесты соединений
                                        Тесты двигателя




                              Тесты колес




                                            UNIT
Тесты электрики




                                            ТЕСТЫ
TDD


             +                =      ?
                                  качественный
unit-тесты       разработка       продукт
TDD


             +                =
                                  качественный-
unit-тесты       разработка       продукт
UNIT-ТЕСТЫ
ОТДЕЛЬНЫХ МОДУЛЕЙ
НЕ ГАРАНТИРУЮТ КАЧЕСТВО
РАБОТЫ СИСТЕМЫ В ЦЕЛОМ
РАЗРАБОТКА
OUTSIDE-IN
ВХОДНЫЕ/ВЫХОДНЫЕ

ДАННЫЕ




                   выходные
 входные           данные
 данные
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
PHPSpec
<?php
require_once 'bowling.php'

class DescribeIndexController
    extends PHPSpec_Context_Zend
{
  public function itShouldDisplayHelloWorld()
  {
    $this->get(‘index’);
    $this->
      response()->
      should->
      match(‘/Hello World/’);
  }
}
Symfony Functional Test

<?php

$browser->get(‘/job/new’)->
  with(‘request’)->begin()->
    isParameter(‘module’, ‘job’)->
    isParameter(‘action’, ‘new’)->
  end()->

  click(‘Preview   your job’, array(‘job’ => array(
    ‘company’ =>   ‘Sensio Labs’,
    ‘url‘     =>   ‘http://sensio.com’,
    ‘logo‘    =>   ‘/uploads/jobs/sensio-labs.gif’,
  ));
BDD


                 unit-тесты

            +(      +         )=
                                   качественный
ПОВЕДЕНИЕ
                                   продукт
                 разработка
ТЕХНИКА
КОММУНИКАЦИЙ
ИДЕЯ
 # 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
ИДЕЯ
 # bowling_spec.rb




            NO!
 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
ИДЕЯ
 Хочу онлайн-боулинг
              с блэкджеком и...
 и он будет
              ПЛАТНЫМ
КОММУНИКАЦИИ

 Хочу кастомный
    Porsche
                    # 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




                                                              разработка




                  написание спек
   идея
BDD для PHP проектов
ФУНКЦИОНАЛ


Feature: Addition
  In order to avoid silly mistakes
  As a math idiot
  I want to be told the sum of two numbers

  Scenario: Add two numbers
    Given I have entered 10 into the calculator
    And I have entered 5 into the calculator
    When I press ‘plus’
    Then the result should be 15
ФУНКЦИОНАЛ


Feature: Addition
  In order to avoid silly mistakes
  As a math idiot
  I want to be told the sum of two numbers

  Scenario: Add two numbers
    Given I have entered 10 into the calculator
    And I have entered 5 into the calculator
    When I press ‘plus’
    Then the result should be 15
СЦЕНАРИИ


Feature: Addition
  In order to avoid silly mistakes
  As a math idiot
  I want to be told the sum of two numbers

  Scenario: Add two numbers
    Given I have entered 10 into the calculator
    And I have entered 5 into the calculator
    When I press ‘plus’
    Then the result should be 15
ШАГИ


Feature: Addition
  In order to avoid silly mistakes
  As a math idiot
  I want to be told the sum of two numbers

  Scenario: Add two numbers
    Given I have entered 10 into the calculator
    And I have entered 5 into the calculator
    When I press ‘plus’
    Then the result should be 15
БИБЛИОТЕКИ



ASSERTIONS   Test::Unit, RSpec

BROWSER      Webrat, Capybara, Selenium


RUNNER       Autotest, RStakeout, Watchr
ОПРЕДЕЛЕНИЯ

require 'calculator'

Given /I have entered (d+) into the calculator/ do
|n|
  @calc.push n.to_i
end

When /I press (w+)/ do |op|
  @result = @calc.send op
end

Then /the resoulr should be (.*)/ do |result|
  @result.should == result.to_f
end
ОПРЕДЕЛЕНИЯ

require 'calculator'

Given /I have entered (d+) into the calculator/ do
|n|
                ПИШУТСЯ на

               Ruby
  @calc.push n.to_i
end

When /I press (w+)/ do |op|
  @result = @calc.send op
end

Then /the resoulr should be (.*)/ do |result|
  @result.should == result.to_f
end
МИНУСЫ



 1. Не все PHP-разработчики знают/хотят знать Ruby
 2. Сложность при описании входных условий
 3. Невозможность использования PHP библиотек
 4. Скорость работы кросс-языкового решения
BDD для PHP проектов
1. Написан с нуля на PHP5.3
2. Написан с применением Symfony Components
3. Старается быть Cucumber’ом с входными/выходными данными
4. Полностью нативное решение на PHP
5. Столь же быстр, что и Cucumber (проверено)
6. Поддерживает полную и17ю
7. Полностью расширяем и настраиваем
8. Поддерживает различные типы лоадеров
ФУНКЦИОНАЛ


Feature: Serve coffee
  In order to earn money
  Customers should be able to
  buy coffee at all times

  Scenario: Buy last coffee
    Given there are 1 coffees left in the machine
    And I have deposited 1$
    When I press the coffee button
    Then I should be served a coffee
ОПРЕДЕЛЕНИЯ


<?php

$steps->Then(‘/^it should (fail|pass)$/’,
   function($world, $status) {
     if (‘fail’ === $success) {
       assertNotEquals(0, $world->return);
     } else {
       assertEquals(0, $world->return);
     }
   }
);
ОПРЕДЕЛЕНИЯ


<?php
ТИП ОПРЕДЕЛЕНИЯ
$steps->Then(‘/^it should (fail|pass)$/’,
   function($world, $status) {
     if (‘fail’ === $success) {
       assertNotEquals(0, $world->return);
     } else {
       assertEquals(0, $world->return);
     }
   }
);
ОПРЕДЕЛЕНИЯ


<?php
                  РЕГУЛЯРНОЕ ВЫРАЖЕНИЕ
$steps->Then(‘/^it should (fail|pass)$/’,
   function($world, $status) {
     if (‘fail’ === $success) {
       assertNotEquals(0, $world->return);
     } else {
       assertEquals(0, $world->return);
     }
   }
);
ОПРЕДЕЛЕНИЯ


<?php

$steps->Then(‘/^it should (fail|pass)$/’,
   function($world, $status) {
     if (‘fail’ === $success) {
       assertNotEquals(0, $world->return);
     } else {                                CALLBACK
       assertEquals(0, $world->return);
     }
   }
);
ИСПОЛНЕНИЕ
Feature: Behat Console Runner
  Scenario: Run feature from CLI
    Given I have default Behat configuration
    When I call ‘behat -f progress’
    Then it should pass


<?php

$steps->Then(‘/^it should (fail|pass)$/’,
   function($world, $status) {
     ...
   }
);
ИСПОЛНЕНИЕ
Feature: Behat Console Runner
  Scenario: Run feature from CLI
    Given I have default Behat configuration
    When I call ‘behat -f progress’
    Then it should pass


<?php

$steps->Then(‘/^it should (fail|pass)$/’,
   function($world, $status) {
     // $status == ‘pass’
   }
);
СТАТУСЫ
<?php

$steps->Then(‘/^it should pass$/’, function($world) {
  return true;
});

$steps->Then(‘/^it passes$/’, function($world) {
  return false;
});

$steps->Then(‘/^it should fail$/’, function($world) {
  throw new Exception();
});

$steps->Then(‘/^it should pend$/’, function($world) {
  throw new EverzetBehatExceptionPending();
});
СТАТУСЫ
<?php

$steps->Then(‘/^it should pass$/’, function($world) {
  ...
});

$steps->Then(‘/^it should pass$/’, function($world) {
  // Will throw exception on definitions read
});

$steps->Then(‘/^it’s good$/’, function($world) {
  ...
});

$steps->Then(‘/^it’s w+$/’, function($world) {
  // Will throw exception on ‘it should pass call’
});
ПРИМЕР
ИСПОЛЬЗОВАНИЯ
УСТАНОВКА




$> pear channel-discover pear.everzet.com
$> pear install everzet/behat-beta
HOW MUCH IS THE FISH?

<?php # ./user.php

class User
{
  public function __construct($username, $age = 1)
  {
  }

    public function getName() {}

    public function getAge() {}
}
FEATURE

# ./features/user.feature
# language: ru

Функционал: Базовый Пользователь
  Чтобы работать с пользователями
  Как разработчик сайта
  Я хочу иметь доступ к
  пользовательской модели

  Сценарий: Создание пользователя
    Допустим у нас нет пользователей
    Если мы добавим пользователя ‘everzet’
    То у нас должно быть 1 пользователей
    И имя у первого пользователя ‘everzet’
GET SNIPPETS
ОПРЕДЕЛЕНИЯ
<?php # ./features/steps/user_steps.php

require_once ‘PHPUnit/Autoload.php’;
require_once ‘PHPUnit/Framework/Assert/Functions.php’;
require_once __DIR__ . ‘/../../user.php’;

$steps->

Допустим(‘/^у нас нет пользователей$/’, function($world) {
     $world->users = array();
})->

Если(‘/^мы добавим пользователя ’([^’]+)’$/’, function($world, $username) {
     $world->users[] = new User($username);
})->

To(‘/^у нас должно быть (d+) пользователей$/’, function($world, $count) {
     assertEquals($count, count($world->users));
})->

То(‘/^имя у первого пользователя ’([^’]+)’$/’, function($world, $username) {
    assertEquals($username, $world->users[0]->getName());
});
WATCH IT FAILS
РЕАЛИЗАЦИЯ
<?php # ./user.php

class User
{
  protected $name, $age;

    public function __construct($username, $age = 1)
    {
      $this->name = $username;
      $this->age = $age;
    }

    public function getName() { return $this->name; }

    public function getAge() { return $this->age; }
}
WATCH IT PASSES
TODO




1. CommonWebSteps
2. Annotated class step definitions and hooks
3. JUnit formatter
4. PDF/HTML formatter
5. Selenium integration
ССЫЛКИ
         ОФФИЦИАЛЬНЫЙ САЙТ
         http://everzet.com/Behat




         ОФФИЦИАЛЬНЫЙ РЕПОЗИТОРИЙ
         http://github.com/everzet/Behat




         ОФФИЦИАЛЬНАЯ GOOGLE GROUP
         http://groups.google.com/group/behat
ВОПРОСЫ?
CREDITS




http://www.flickr.com/photos/jasmic/279741827
http://www.flickr.com/photos/mulmatsherm/2312688473
http://www.flickr.com/photos/joshfassbind/4584323789
http://www.flickr.com/photos/bearuk/564788081
http://www.flickr.com/photos/jasmincormier/3511034253
http://www.flickr.com/photos/chuqui/4552338602

More Related Content

PDF
Behat в PHP с использованием Behat и Mink
PPTX
Codeception Introduction
PDF
Чуть сложнее чем Singleton: аннотации, IOC, АОП
PPTX
Микрофреймворки PHP
PDF
Анджей Гужовский "Riot.JS, или как приготовить современные Web Components"
PDF
Почему Mojolicious?
PDF
Контроль качества верстки или как начать делать Makeup
PPTX
Unit тестирование
Behat в PHP с использованием Behat и Mink
Codeception Introduction
Чуть сложнее чем Singleton: аннотации, IOC, АОП
Микрофреймворки PHP
Анджей Гужовский "Riot.JS, или как приготовить современные Web Components"
Почему Mojolicious?
Контроль качества верстки или как начать делать Makeup
Unit тестирование

What's hot (19)

ODP
Saint Perl 2009: CGI::Ajax demo
PPTX
CodeFest 2012. Родионов А. — Тестирование Ruby (on Rails) приложений: стек, п...
PDF
Angular 2: Всех переиграл
PPTX
Behat-trick: как мы внедряли BDD на наших проектах
PPT
JS Fest 2018. Лилия Карпенко. Особенности создания IOS / Android Mobile Apps ...
PPTX
Леонид Динерштейн - Разработка программ через тестирование поведения средства...
PDF
Основы доменной модели
PDF
Автоматизация UI тестирования под Windows и Windows Phone
PDF
QA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшe
PDF
Сергей Татаринцев — bem-tools v1.0.0
PDF
Что нового в Perl? 5.10 — 5.16
PDF
М. Боднарчук Современное функциональное тестирование с Codeception
PDF
Pycon Russia 2013 - Разработка через тестирование в Python и Django
PPTX
Михаил Боднарчук Современное функциональное тестирование с Codeception
PPT
Cucumber on Kazan.rb
PPTX
What’s New in PHP7?
ODP
ZFConf 2010: Zend Framework and Doctrine
PDF
Emmet - инструмент для веб-разработчика
PPT
Easy authcache 2 кеширование для pro родионов игорь
Saint Perl 2009: CGI::Ajax demo
CodeFest 2012. Родионов А. — Тестирование Ruby (on Rails) приложений: стек, п...
Angular 2: Всех переиграл
Behat-trick: как мы внедряли BDD на наших проектах
JS Fest 2018. Лилия Карпенко. Особенности создания IOS / Android Mobile Apps ...
Леонид Динерштейн - Разработка программ через тестирование поведения средства...
Основы доменной модели
Автоматизация UI тестирования под Windows и Windows Phone
QA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшe
Сергей Татаринцев — bem-tools v1.0.0
Что нового в Perl? 5.10 — 5.16
М. Боднарчук Современное функциональное тестирование с Codeception
Pycon Russia 2013 - Разработка через тестирование в Python и Django
Михаил Боднарчук Современное функциональное тестирование с Codeception
Cucumber on Kazan.rb
What’s New in PHP7?
ZFConf 2010: Zend Framework and Doctrine
Emmet - инструмент для веб-разработчика
Easy authcache 2 кеширование для pro родионов игорь
Ad

Viewers also liked (16)

PDF
BDD в PHP с Behat и Mink
PPTX
Testing with laravel
PPTX
Laravel Unit Testing
PDF
Modern Project Toolbox
PDF
Being effective with legacy projects
PDF
Enabling agile devliery through enabling BDD in PHP projects
PDF
Moving away from legacy code with BDD
PDF
Min-Maxing Software Costs
PDF
Modern Agile Project Toolbox
PDF
Decoupling with Design Patterns and Symfony2 DIC
PPTX
Автоматизация для ленивых тестировщиков. Selenium + Python + Behave (BDD)
PDF
Bridging The Communication Gap, Fast
PDF
Moving away from legacy code (AgileCymru)
PDF
Taking back BDD
PDF
Moving away from legacy code with BDD
PDF
Design how your objects talk through mocking
BDD в PHP с Behat и Mink
Testing with laravel
Laravel Unit Testing
Modern Project Toolbox
Being effective with legacy projects
Enabling agile devliery through enabling BDD in PHP projects
Moving away from legacy code with BDD
Min-Maxing Software Costs
Modern Agile Project Toolbox
Decoupling with Design Patterns and Symfony2 DIC
Автоматизация для ленивых тестировщиков. Selenium + Python + Behave (BDD)
Bridging The Communication Gap, Fast
Moving away from legacy code (AgileCymru)
Taking back BDD
Moving away from legacy code with BDD
Design how your objects talk through mocking
Ad

Similar to BDD для PHP проектов (20)

PDF
Agile with cucumber or BDD with fun
PPT
CodeFest 2012. Корсаков С. — Cucumber. Некоторые советы по приготовлению
PPTX
automation is iOS development
PDF
Erlang tasty & useful stuff
PPT
TestGuy - эмулируем вашего тестировщика
PDF
Антипаттерны модульного тестирования (Донецкий кофе-и-код Сентябрь 2010)
PDF
Plugin for plugin, or extending android new build system
PDF
BDD girls Battle: Cucumber VS. JBehave
PDF
functional patterns - dotnetconf'11
PDF
Moscow Python Conf 2016. Почему 100% покрытие это плохо?
PDF
JavaScript не нужен, CoffeeScript - мимими
PDF
Тестируй это / Виктор Русакович (GP Solutions)
PPT
Руководство по приготовлению бутербродов из Selenium
PDF
Инструментируй это
PDF
Архитектура кода нового 2ГИС Web API или куда мы дели MVC
PDF
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
PDF
Пластилиновый код: как перестать кодить и начать жить
PDF
“QA job interview: life hacks and scripts for success”
Agile with cucumber or BDD with fun
CodeFest 2012. Корсаков С. — Cucumber. Некоторые советы по приготовлению
automation is iOS development
Erlang tasty & useful stuff
TestGuy - эмулируем вашего тестировщика
Антипаттерны модульного тестирования (Донецкий кофе-и-код Сентябрь 2010)
Plugin for plugin, or extending android new build system
BDD girls Battle: Cucumber VS. JBehave
functional patterns - dotnetconf'11
Moscow Python Conf 2016. Почему 100% покрытие это плохо?
JavaScript не нужен, CoffeeScript - мимими
Тестируй это / Виктор Русакович (GP Solutions)
Руководство по приготовлению бутербродов из Selenium
Инструментируй это
Архитектура кода нового 2ГИС Web API или куда мы дели MVC
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
Пластилиновый код: как перестать кодить и начать жить
“QA job interview: life hacks and scripts for success”

BDD для PHP проектов

  • 1. BEHAVIOR DRIVEN DEVELOPMENT ДЛЯ PHP ПРОЕКТОВ @everzet
  • 2. КТО Я symfony-разработчик С 2007 года СОЗДАТЕЛЬ BEHAT ВЕДУЩИЙ РАЗРАБОТЧИК DEV.BY ПРОГРАММИСТ С РОЖДЕНИЯ http://everzet.com
  • 4. Тесты соединений Тесты двигателя Тесты колес UNIT Тесты электрики ТЕСТЫ
  • 5. TDD + = ? качественный unit-тесты разработка продукт
  • 6. TDD + = качественный- unit-тесты разработка продукт
  • 7. UNIT-ТЕСТЫ ОТДЕЛЬНЫХ МОДУЛЕЙ НЕ ГАРАНТИРУЮТ КАЧЕСТВО РАБОТЫ СИСТЕМЫ В ЦЕЛОМ
  • 9. ВХОДНЫЕ/ВЫХОДНЫЕ ДАННЫЕ выходные входные данные данные
  • 10. 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
  • 11. PHPSpec <?php require_once 'bowling.php' class DescribeIndexController extends PHPSpec_Context_Zend { public function itShouldDisplayHelloWorld() { $this->get(‘index’); $this-> response()-> should-> match(‘/Hello World/’); } }
  • 12. Symfony Functional Test <?php $browser->get(‘/job/new’)-> with(‘request’)->begin()-> isParameter(‘module’, ‘job’)-> isParameter(‘action’, ‘new’)-> end()-> click(‘Preview your job’, array(‘job’ => array( ‘company’ => ‘Sensio Labs’, ‘url‘ => ‘http://sensio.com’, ‘logo‘ => ‘/uploads/jobs/sensio-labs.gif’, ));
  • 13. BDD unit-тесты +( + )= качественный ПОВЕДЕНИЕ продукт разработка
  • 15. ИДЕЯ # 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
  • 16. ИДЕЯ # bowling_spec.rb NO! 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
  • 17. ИДЕЯ Хочу онлайн-боулинг с блэкджеком и... и он будет ПЛАТНЫМ
  • 18. КОММУНИКАЦИИ Хочу кастомный Porsche # 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 разработка написание спек идея
  • 20. ФУНКЦИОНАЛ Feature: Addition In order to avoid silly mistakes As a math idiot I want to be told the sum of two numbers Scenario: Add two numbers Given I have entered 10 into the calculator And I have entered 5 into the calculator When I press ‘plus’ Then the result should be 15
  • 21. ФУНКЦИОНАЛ Feature: Addition In order to avoid silly mistakes As a math idiot I want to be told the sum of two numbers Scenario: Add two numbers Given I have entered 10 into the calculator And I have entered 5 into the calculator When I press ‘plus’ Then the result should be 15
  • 22. СЦЕНАРИИ Feature: Addition In order to avoid silly mistakes As a math idiot I want to be told the sum of two numbers Scenario: Add two numbers Given I have entered 10 into the calculator And I have entered 5 into the calculator When I press ‘plus’ Then the result should be 15
  • 23. ШАГИ Feature: Addition In order to avoid silly mistakes As a math idiot I want to be told the sum of two numbers Scenario: Add two numbers Given I have entered 10 into the calculator And I have entered 5 into the calculator When I press ‘plus’ Then the result should be 15
  • 24. БИБЛИОТЕКИ ASSERTIONS Test::Unit, RSpec BROWSER Webrat, Capybara, Selenium RUNNER Autotest, RStakeout, Watchr
  • 25. ОПРЕДЕЛЕНИЯ require 'calculator' Given /I have entered (d+) into the calculator/ do |n| @calc.push n.to_i end When /I press (w+)/ do |op| @result = @calc.send op end Then /the resoulr should be (.*)/ do |result| @result.should == result.to_f end
  • 26. ОПРЕДЕЛЕНИЯ require 'calculator' Given /I have entered (d+) into the calculator/ do |n| ПИШУТСЯ на Ruby @calc.push n.to_i end When /I press (w+)/ do |op| @result = @calc.send op end Then /the resoulr should be (.*)/ do |result| @result.should == result.to_f end
  • 27. МИНУСЫ 1. Не все PHP-разработчики знают/хотят знать Ruby 2. Сложность при описании входных условий 3. Невозможность использования PHP библиотек 4. Скорость работы кросс-языкового решения
  • 29. 1. Написан с нуля на PHP5.3 2. Написан с применением Symfony Components 3. Старается быть Cucumber’ом с входными/выходными данными 4. Полностью нативное решение на PHP 5. Столь же быстр, что и Cucumber (проверено) 6. Поддерживает полную и17ю 7. Полностью расширяем и настраиваем 8. Поддерживает различные типы лоадеров
  • 30. ФУНКЦИОНАЛ Feature: Serve coffee In order to earn money Customers should be able to buy coffee at all times Scenario: Buy last coffee Given there are 1 coffees left in the machine And I have deposited 1$ When I press the coffee button Then I should be served a coffee
  • 31. ОПРЕДЕЛЕНИЯ <?php $steps->Then(‘/^it should (fail|pass)$/’, function($world, $status) { if (‘fail’ === $success) { assertNotEquals(0, $world->return); } else { assertEquals(0, $world->return); } } );
  • 32. ОПРЕДЕЛЕНИЯ <?php ТИП ОПРЕДЕЛЕНИЯ $steps->Then(‘/^it should (fail|pass)$/’, function($world, $status) { if (‘fail’ === $success) { assertNotEquals(0, $world->return); } else { assertEquals(0, $world->return); } } );
  • 33. ОПРЕДЕЛЕНИЯ <?php РЕГУЛЯРНОЕ ВЫРАЖЕНИЕ $steps->Then(‘/^it should (fail|pass)$/’, function($world, $status) { if (‘fail’ === $success) { assertNotEquals(0, $world->return); } else { assertEquals(0, $world->return); } } );
  • 34. ОПРЕДЕЛЕНИЯ <?php $steps->Then(‘/^it should (fail|pass)$/’, function($world, $status) { if (‘fail’ === $success) { assertNotEquals(0, $world->return); } else { CALLBACK assertEquals(0, $world->return); } } );
  • 35. ИСПОЛНЕНИЕ Feature: Behat Console Runner Scenario: Run feature from CLI Given I have default Behat configuration When I call ‘behat -f progress’ Then it should pass <?php $steps->Then(‘/^it should (fail|pass)$/’, function($world, $status) { ... } );
  • 36. ИСПОЛНЕНИЕ Feature: Behat Console Runner Scenario: Run feature from CLI Given I have default Behat configuration When I call ‘behat -f progress’ Then it should pass <?php $steps->Then(‘/^it should (fail|pass)$/’, function($world, $status) { // $status == ‘pass’ } );
  • 37. СТАТУСЫ <?php $steps->Then(‘/^it should pass$/’, function($world) { return true; }); $steps->Then(‘/^it passes$/’, function($world) { return false; }); $steps->Then(‘/^it should fail$/’, function($world) { throw new Exception(); }); $steps->Then(‘/^it should pend$/’, function($world) { throw new EverzetBehatExceptionPending(); });
  • 38. СТАТУСЫ <?php $steps->Then(‘/^it should pass$/’, function($world) { ... }); $steps->Then(‘/^it should pass$/’, function($world) { // Will throw exception on definitions read }); $steps->Then(‘/^it’s good$/’, function($world) { ... }); $steps->Then(‘/^it’s w+$/’, function($world) { // Will throw exception on ‘it should pass call’ });
  • 40. УСТАНОВКА $> pear channel-discover pear.everzet.com $> pear install everzet/behat-beta
  • 41. HOW MUCH IS THE FISH? <?php # ./user.php class User { public function __construct($username, $age = 1) { } public function getName() {} public function getAge() {} }
  • 42. FEATURE # ./features/user.feature # language: ru Функционал: Базовый Пользователь Чтобы работать с пользователями Как разработчик сайта Я хочу иметь доступ к пользовательской модели Сценарий: Создание пользователя Допустим у нас нет пользователей Если мы добавим пользователя ‘everzet’ То у нас должно быть 1 пользователей И имя у первого пользователя ‘everzet’
  • 44. ОПРЕДЕЛЕНИЯ <?php # ./features/steps/user_steps.php require_once ‘PHPUnit/Autoload.php’; require_once ‘PHPUnit/Framework/Assert/Functions.php’; require_once __DIR__ . ‘/../../user.php’; $steps-> Допустим(‘/^у нас нет пользователей$/’, function($world) { $world->users = array(); })-> Если(‘/^мы добавим пользователя ’([^’]+)’$/’, function($world, $username) { $world->users[] = new User($username); })-> To(‘/^у нас должно быть (d+) пользователей$/’, function($world, $count) { assertEquals($count, count($world->users)); })-> То(‘/^имя у первого пользователя ’([^’]+)’$/’, function($world, $username) { assertEquals($username, $world->users[0]->getName()); });
  • 46. РЕАЛИЗАЦИЯ <?php # ./user.php class User { protected $name, $age; public function __construct($username, $age = 1) { $this->name = $username; $this->age = $age; } public function getName() { return $this->name; } public function getAge() { return $this->age; } }
  • 48. TODO 1. CommonWebSteps 2. Annotated class step definitions and hooks 3. JUnit formatter 4. PDF/HTML formatter 5. Selenium integration
  • 49. ССЫЛКИ ОФФИЦИАЛЬНЫЙ САЙТ http://everzet.com/Behat ОФФИЦИАЛЬНЫЙ РЕПОЗИТОРИЙ http://github.com/everzet/Behat ОФФИЦИАЛЬНАЯ GOOGLE GROUP http://groups.google.com/group/behat