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

5,747 views

Published on

0 Comments
10 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
5,747
On SlideShare
0
From Embeds
0
Number of Embeds
70
Actions
Shares
0
Downloads
36
Comments
0
Likes
10
Embeds 0
No embeds

No notes for slide

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

  1. 1. BEHAVIOR DRIVEN DEVELOPMENT ДЛЯ PHP ПРОЕКТОВ @everzet
  2. 2. КТО Я symfony-разработчик С 2007 года СОЗДАТЕЛЬ BEHAT ВЕДУЩИЙ РАЗРАБОТЧИК DEV.BY ПРОГРАММИСТ С РОЖДЕНИЯ http://everzet.com
  3. 3. РАЗРАБОТКА INSIDE-OUT
  4. 4. Тесты соединений Тесты двигателя Тесты колес UNIT Тесты электрики ТЕСТЫ
  5. 5. TDD + = ? качественный unit-тесты разработка продукт
  6. 6. TDD + = качественный- unit-тесты разработка продукт
  7. 7. UNIT-ТЕСТЫ ОТДЕЛЬНЫХ МОДУЛЕЙ НЕ ГАРАНТИРУЮТ КАЧЕСТВО РАБОТЫ СИСТЕМЫ В ЦЕЛОМ
  8. 8. РАЗРАБОТКА OUTSIDE-IN
  9. 9. ВХОДНЫЕ/ВЫХОДНЫЕ ДАННЫЕ выходные входные данные данные
  10. 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. 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. 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. 13. BDD unit-тесты +( + )= качественный ПОВЕДЕНИЕ продукт разработка
  14. 14. ТЕХНИКА КОММУНИКАЦИЙ
  15. 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. 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. 17. ИДЕЯ Хочу онлайн-боулинг с блэкджеком и... и он будет ПЛАТНЫМ
  18. 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 разработка написание спек идея
  19. 19. ФУНКЦИОНАЛ 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
  20. 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. 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. 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. 23. БИБЛИОТЕКИ ASSERTIONS Test::Unit, RSpec BROWSER Webrat, Capybara, Selenium RUNNER Autotest, RStakeout, Watchr
  24. 24. ОПРЕДЕЛЕНИЯ 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
  25. 25. ОПРЕДЕЛЕНИЯ 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
  26. 26. МИНУСЫ 1. Не все PHP-разработчики знают/хотят знать Ruby 2. Сложность при описании входных условий 3. Невозможность использования PHP библиотек 4. Скорость работы кросс-языкового решения
  27. 27. 1. Написан с нуля на PHP5.3 2. Написан с применением Symfony Components 3. Старается быть Cucumber’ом с входными/выходными данными 4. Полностью нативное решение на PHP 5. Столь же быстр, что и Cucumber (проверено) 6. Поддерживает полную и17ю 7. Полностью расширяем и настраиваем 8. Поддерживает различные типы лоадеров
  28. 28. ФУНКЦИОНАЛ 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
  29. 29. ОПРЕДЕЛЕНИЯ <?php $steps->Then(‘/^it should (fail|pass)$/’, function($world, $status) { if (‘fail’ === $success) { assertNotEquals(0, $world->return); } else { assertEquals(0, $world->return); } } );
  30. 30. ОПРЕДЕЛЕНИЯ <?php ТИП ОПРЕДЕЛЕНИЯ $steps->Then(‘/^it should (fail|pass)$/’, function($world, $status) { if (‘fail’ === $success) { assertNotEquals(0, $world->return); } else { assertEquals(0, $world->return); } } );
  31. 31. ОПРЕДЕЛЕНИЯ <?php РЕГУЛЯРНОЕ ВЫРАЖЕНИЕ $steps->Then(‘/^it should (fail|pass)$/’, function($world, $status) { if (‘fail’ === $success) { assertNotEquals(0, $world->return); } else { assertEquals(0, $world->return); } } );
  32. 32. ОПРЕДЕЛЕНИЯ <?php $steps->Then(‘/^it should (fail|pass)$/’, function($world, $status) { if (‘fail’ === $success) { assertNotEquals(0, $world->return); } else { CALLBACK assertEquals(0, $world->return); } } );
  33. 33. ИСПОЛНЕНИЕ 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) { ... } );
  34. 34. ИСПОЛНЕНИЕ 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’ } );
  35. 35. СТАТУСЫ <?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(); });
  36. 36. СТАТУСЫ <?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’ });
  37. 37. ПРИМЕР ИСПОЛЬЗОВАНИЯ
  38. 38. УСТАНОВКА $> pear channel-discover pear.everzet.com $> pear install everzet/behat-beta
  39. 39. HOW MUCH IS THE FISH? <?php # ./user.php class User { public function __construct($username, $age = 1) { } public function getName() {} public function getAge() {} }
  40. 40. FEATURE # ./features/user.feature # language: ru Функционал: Базовый Пользователь Чтобы работать с пользователями Как разработчик сайта Я хочу иметь доступ к пользовательской модели Сценарий: Создание пользователя Допустим у нас нет пользователей Если мы добавим пользователя ‘everzet’ То у нас должно быть 1 пользователей И имя у первого пользователя ‘everzet’
  41. 41. GET SNIPPETS
  42. 42. ОПРЕДЕЛЕНИЯ <?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()); });
  43. 43. WATCH IT FAILS
  44. 44. РЕАЛИЗАЦИЯ <?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; } }
  45. 45. WATCH IT PASSES
  46. 46. TODO 1. CommonWebSteps 2. Annotated class step definitions and hooks 3. JUnit formatter 4. PDF/HTML formatter 5. Selenium integration
  47. 47. ССЫЛКИ ОФФИЦИАЛЬНЫЙ САЙТ http://everzet.com/Behat ОФФИЦИАЛЬНЫЙ РЕПОЗИТОРИЙ http://github.com/everzet/Behat ОФФИЦИАЛЬНАЯ GOOGLE GROUP http://groups.google.com/group/behat
  48. 48. ВОПРОСЫ?
  49. 49. 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

×