21 декабря 2010 в 13:53

PHP + BDD = Behat, или сказ о чудо-библиотеке из песочницы

PHP*
Каждый, кто всерьез занимался разработкой на Ruby, знает про замечательный гем Cucumber. Вкратце — это библиотека для автоматизированного тестирования, заточенная под BDD. Подробнее можно почитать в топике хабраюзера dapi, а еще лучше посмотреть подкаст от Райна Бэйтса. Основная прелесть «огурца» состоит в том, что он позволяет писать тесты на понятном человеку языке, и даже не обязательно английском. Выглядит это так:

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 50 into the calculator
      And I have entered 70 into the calculator
     When I press add
     Then The result should be 120 on the scree

Благодаря Cucumber я подсел на BDD на рельсах. Но вот на PHP, с которым приходится работать основную часть времени, отношения с BDD как-то не сложились. И в первую очередь из-за отсутствия достойного инструментария. Но однажды судьба завела меня на страницу библиотеки Behat (написанной, кстати говоря, хабраюзером everzet). И на меня свалилось счастье…

Установка и предварительная настройка


Собственно, Behat — это «Cucumber от мира PHP». Тот же синтаксис (используется язык Gherkin), та же структура файлов, практически идентичный метод определения шагов. Видно, что автор вдохновлялся «старшим братом» своей библиотеки, чего он и не скрывает. С виду все красиво, но не смотреть же мы на нее пришли. Пора испробовать продукт в деле.

Сразу оговорюсь — Behat для своей работы требует PHP 5.3.1. Поэтому, если вы еще не обзавелись оным, самое время это сделать.

Автор на сайте предлагает несколько путей для установки Behat. Я выберу самый первый и самый простой — через Pear:
$ pear channel-discover pear.everzet.com
$ pear install everzet/behat-beta

Тадам! Мы — счастливые обладатели Behat :) В принципе, можно уже хоть сейчас идти в папку с тестируемым проектом и начинать писать сценарии, но я предпочитаю немножко «протюнинговать» библиотеку. Итак, первым делом создадим в папке с проектом родную для Behat среду обитания. Она, как уже упоминалось, заимствована у Cucumber и имеет следующий вид:

|-- features
   `-- steps
   |   `-- *_steps.php
   `-- support
       `-- env.php


Подробнее о том, что мы имеем:
  • features — это папка, где у нас будут храниться сценарии (файлы *.feature, о них чуть позже);
  • features/steps — это папка с описаниями «шагов» тестирования;
  • features/support — папка со скриптами поддержки. Особую важность здесь имеет файл env.php, в котором описывается конфигурация среды. Его и откроем.

Изначально файл env.php пуст. Основная его важность для нас состоит в том, что он выполняется каждый раз перед выполнением очередного сценария. И именно здесь удобно подключить все нужные нам библиотеки и файлы проекта. Здесь же удобно определить переменные и функции, которые понадобятся нам в тестах. Для их хранения, кстати, очень удобно использовать переменную $world, которая подается нам на входе, каждый раз новая. По большому счету, для использования базового функционала нам нет никакой необходимости что-то настраивать, вполне хватит того, что предоставляет нам Behat и сам PHP. Но мне все же нравится использовать функции проверок из PHPUnit, и я их, с вашего позволения, подключу.

Если у вас не установлен PHPUnit, устанавливается он крайне просто, через тот же Pear:
$ pear channel-discover pear.phpunit.de
$ pear channel-discover components.ez.no
$ pear channel-discover pear.symfony-project.com
$ pear install phpunit/PHPUnit

Готово, осталось только прописать в env.php:
<?php
require_once 'PHPUnit/Autoload.php';
require_once 'PHPUnit/Framework/Assert/Functions.php';
?>

Так же, чтобы у нас были доступны классы и функции из нашего проекта, нужно бы подключить к среде соответствующие файлы. Я не люблю захламлять инициализацию среды посторонними включениями, а потому объединю их в один файл — includes.php, а его уже подключу к среде. В итоге файл env.php имеет вид:

<?php
require_once 'PHPUnit/Autoload.php';
require_once 'PHPUnit/Framework/Assert/Functions.php';
include 'includes.php';
?>

Описываем фичи и производим первый запуск


Ну, вот и все, мы готовы к тестированию, можно начинать описывать фичи. В качестве примера я решил взять такую сложную в реализации и тестировании вещь, как сложение двух чисел. Итак, создаем в папке features файл calc.feature и пишем:

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

    Scenario:
       Given I have an calculator
        When I have entered 30 as first number
         And I have entered 20 as second number
         And I press 'Add'
        Then The result should be 50


Сохраняем, и вбиваем в консоль команду
$ behat features

На выходе получаем:
1 scenario (1 undefined)
5 steps (5 undefined)
0.091s

You can implement step definitions for undefined steps with these snippets:

$steps->Given('/^I have an calculator$/', function($world) {
    throw new \Everzet\Behat\Exception\Pending();
});

$steps->When('/^I have entered (\d+) as first number$/', function($world, $arg1) {
    throw new \Everzet\Behat\Exception\Pending();
});

$steps->And('/^I have entered (\d+) as second number$/', function($world, $arg1) {
    throw new \Everzet\Behat\Exception\Pending();
});

$steps->And('/^I press \'([^\']*)\'$/', function($world, $arg1) {
    throw new \Everzet\Behat\Exception\Pending();
});

$steps->Then('/^The result should be (\d+)$/', function($world, $arg1) {
    throw new \Everzet\Behat\Exception\Pending();
});

Это говорит нам о том, что у нас не определены «шаги» сценария. Но мы-то знаем еще больше — у нас нет класса калькулятора. Напишем, не проблема.

class Calc {
    protected $first = 0;
    protected $second = 0;
    protected $result = 0;

    public function setFirst($num){ $this->first = $num; }
    public function setSecond($num){ $this->second = $num; }
    public function add(){ $this->result = $this->first + $this->second; }
    public function getResult(){ return $this->result; }
}

Описываем шаги и проводим успешный тест


Ну, а теперь можем перейти к описанию шагов. Да, кстати, не забудьте подключить файл с классом калькулятора в файл features/support/includes.php. Как мы видим, Behat любезно предложил нам шаблоны определения шагов. Скопируем их, немного подправим и сохраним в файл features/steps/calc_steps.php. Должно получиться примерно следующее:
<?php
$steps->Given('/^I have an calculator$/', function($world) {
    $world->calc = new Calc();
});
$steps->When('/^I have entered (\d+) as first number$/', function($world, $num) {
    $world->calc->setFirst($num);
});
$steps->When('/^I have entered (\d+) as second number$/', function($world, $num) {
    $world->calc->setSecond($num);
});
$steps->When('/^I press \'Add\'$/', function($world) {
    $world->calc->add();
});
$steps->Then('/^The result should be (\d+)$/', function($world, $res) {
    assertEquals($res,$world->calc->getResult());
});
?>

Запускаем тест заново — вуаля! Тест пройден :)

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

  Scenario:                                # features/calc.feature:6
    Given I have an calculator             # features/steps/calc_steps.php:5
    When I have entered 30 as first number # features/steps/calc_steps.php:9
    And I have entered 20 as second number # features/steps/calc_steps.php:13
    And I press 'Add'                      # features/steps/calc_steps.php:17
    Then The result should be 50           # features/steps/calc_steps.php:21

1 scenario (1 passed)
5 steps (5 passed)
0.114s

Пытаемся тестировать страницу


Тестирование работы классов — это, безусловно, важная часть проекта. Но заказчик по обыкновению хочет от нас не рабочие классы, а правильно (по его мнению) функционирующее приложение. Проще говоря — ему нужна правильная работа интерфейса. Проверкой чего мы сейчас и займемся. В Ruby on Rails для тестирования страниц традиционно используется связка cucumer+webrat+nokogiri. В мире PHP все оказалось несколько сложнее… Сам everzet на своей странице предлагает использовать для этого дела библиотеку Goutte, основанную на Symfony 2. Данная библиотека сильно уступает по возможностям вышеупомянутой связке, но лучше в интернетах ничего найти не удалось (если оное кому-то известно, отпишитесь, пожалуйста). Goutte устанавливается крайне просто — скачиваем phar-архив и подключаем его к env.php.

В качестве примера для тестирования я набросал простенькую страничку:
<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <div><?
            if ($_GET["submit"]) {
                echo "Text = "     . $_GET['textfield'] . "<br />";
                echo "Checkbox = " . $_GET['checkbox']  . "<br />";
                echo "Radio = "    . $_GET['radio']     . "<br />";
                echo "Select = "   . $_GET['selectbox'] . "<br />";
            }
        ?></div>
        <form method="get" action="behat.php">
            <div>
                <input type="text" name="textfield" value="">
            </div>
            <div>
                <input type="checkbox" name="checkbox" value="checkbox">
            </div>
            <div>
                <input type="radio" name="radio" value="radio1" checked="checked">
                <input type="radio" name="radio" value="radio2">
                <input type="radio" name="radio" value="radio3">
            </div>
            <div>
                <select name="selectbox">
                    <option value="option1" selected="selected">option1</option>
                    <option value="option2">option2</option>
                    <option value="option3">option3</option>
                </select>
            </div>
            <div>
                <input type="submit" name="submit" value="Submit">
            </div>
            <div id="linkdiv">
                <a href="behat.php?textfield=text&checkbox=checkbox&radio=radio3&selectbox=option2&submit=Submit">Click me</a>
            </div>
        </form>
    </body>
</html>

Задача: проверить работу формы на ней. Да, задача весьма синтетическая, но это просто пример :) Итак, накидаем перечень тестов:
Feature: tests
    After submit form all values of fields
    Should be showed in top of page

    Scenario: Fill field
        Given I'm on test page
         When I fill in 'textfield' with 'some text' in form 'Submit'
          And I submit form 'Submit'
         Then I should see 'Text = some text'

    Scenario: Checking checkbox
        Given I'm on test page
         When I tick checkbox 'checkbox' in form 'Submit'
          And I submit form 'Submit'
         Then I should see 'Checkbox = checkbox'

    Scenario: Selecting radio
        Given I'm on test page
         When I select 'radio2' in radio 'radio' in form 'Submit'
          And I submit form 'Submit'
         Then I should see 'Radio = radio2'
         Then I should not see 'Radio = radio1'

    Scenario: Selecting option in selectbox
        Given I'm on test page
         When I select 'option3' in selectbox 'selectbox' in form 'Submit'
          And I submit form 'Submit'
         Then I should see 'Select = option3'
         Then I should not see 'Select = option1'

    Scenario: Fill some fields
        Given I'm on test page
         When I fill in following in form 'Submit':
            | textfield | some text |
            | checkbox  | true      |
            | radio     | radio3    |
            | selectbox | option2   |
          And I submit form 'Submit'
         Then I should see 'Text = some text'
          And I should see 'Checkbox = checkbox'
          And I should see 'Radio = radio3'
          And I should see 'Select = option2' within 'div'

    Scenario: Clicking on link
        Given I'm on test page
         When I click on link 'Click me' within '#linkdiv'
         Then I should see 'Text = text'
          And I should see 'Checkbox = checkbox'
          And I should see 'Radio = radio3'
          And I should see 'Select = option2' within 'div'
          And the 'textfield' field in form 'Submit' should be blank


Небольшое пояснение, почему форма в тестах носит имя «Submit». В Goutte выбор формы осуществляется по кнопке сабмита на ней. Сама же кнопка ищется по id или value. А кнопка на тестовой странице носит гордое имя Submit, отсюда и такая формулировка.

Шагов много, шаги разные, и все замешаны на работе с Goutte. К счастью, все эти шаги уже описаны мною и собраны в файл. Стянуть искомое можно с git-репозитория git://github.com/DarthSim/behat_websteps.git. В репозитории вы найдете:
  • Файл features/support/env.php с уже настроенным для тестирования страниц окружением;
  • Файл features/support/paths.php для описания путей (подробности чуть ниже);
  • Файл features/support/includes.php для подключения ваших классов;
  • Файл features/support/goutte.phar — собственно Goutte;
  • Файл features/steps/custom.php с описаниями шагов для тестирования страниц.

Копируем файлы в папку с вашим проектом, сохраняя иерархию, и запускаем тест. И получаем ошибку…

Unknown path 'test page'. You can define it in [features_folder]/support/paths.php

Ошибка говорит сама за себя — тест не знает, что за «test page» мы хотим проверить. Исправить проще простого — прописать путь для страницы «test page» в файле features/support/paths.php. Предположим, что тестовая страница у нас размещена по адресу tests.dev/behat.php, значит в файле путей нам нужно прописать

$world->paths['test page'] = "http://tests.dev/behat.php";

Запускаем тест — отлично, тест пройден! Разбор остальных шагов я оставляю читателю, благо они похожи на аналоги из webrat. Конечно, полученный функционал много беднее, чем у webrat, но, думаю, это только начало, дальше будет лучше.

Делаем выводы и приводим ссылки


Итак, можно с уверенностью сказать, что Behat является достойным наследником Cucumber в мире PHP. Библиотека еще не доросла до версии 1.0, но уже представляет собой качественный, законченный продукт. Пожелаем разработчику успехов в развитии его детища и пошлем ему лучи добра. Ниже — некоторые полезные ссылки:

Репозиторий Behat на GitHub
Behat WIKI
Behat API
Репозиторий Goutte
Symfony 2 API (поможет в работе с Goutte)
Сергей @DarthSim
карма
25,0
рейтинг 0,0
Самое читаемое Разработка

Комментарии (42)

  • +8
    В Ruby on Rails для тестирования страниц традиционно используется связка cucumer+webrat+nokogiri. В мире PHP все оказалось несколько сложнее…

    Ну вообще-то, Webrat уже доживает свое и на смену ему давненько пришел Capybara.
    Написанием альтернативы Capybara для php 5.3 я сейчас и занимаюсь полным ходом ;-)
    • 0
      Ты уже мой самый любимый разработчик) Повторно лучи добра)
      • 0
        Собственно, «done»: Mink.
  • 0
    {grammar_nazi_on} features, а не fetures, а не (поиском найдете)
    {grammar_nazi_off}
    А вообще интересная тема, спасибо.
    • 0
      хабрапарсер сожрал скобки, имелось в виду тэг head, а не header
      • 0
        Упс) Спасибо, поправил
  • 0
    Раз уж вы освоили Ruby и добрались до Cucumber, зачем вам на работе PHP?
    • 0
      Ruby, к превеликому сожалению, крайне непопулярен у нас в городе. Сейчас стараюсь целиком уйти в рельсо-фриланс. Небезуспешно, тьфу-тьфу…
      • 0
        Переезжайте в Киев, тут вас на части разорвут)
        • 0
          Менять гражданство ради работы с Ruby — не самая лучшая идея имхо) Но за приглашение спасибо)
    • 0
      Какая разница на чем писать, если ты делаешь это качественно?
      Я вас уверяю, нет никакой разницы на чем писать говно и никакой разницы на чем писать «конфетку».
      Да, у PHP есть недостатки и их море, но у Ruby и рельс нет ничего такого, что бы нельзя было написать или использовать в PHP.
      Проблема не в языках и фреймворках, а в нашем коде и том, как мы его пишем!
      • +2
        Проблема в языках тоже. ЯП должен поощрять и подталкивать к написанию хорошего кода.
        Вообще, на тему «можно написать и использовать». А что было придумано в PHP за все его время существования? Ничего. Все (абсолютно все?) идеи копируются из других языков. Мы только в 2010 увидим «правильные» веб фреймворки, ORM, BDD-фреймворки. Возможно, потому, что это стало возможно только с появлением PHP 5. Сейчас многие языки разиваются в сторону распараллеливания и тредов. Можно ли это в пхп написать и использовать? Нет, никто не будет писать. Неизвестно даже будет ли UTF-8 и PHP 5.6 вообще…
        Ну а Behat клевый.
        • 0
          *упс, PHP 6
        • 0
          Мы только в 2010 увидим «правильные» веб фреймворки, ORM, BDD-фреймворки. Возможно, потому, что это стало возможно только с появлением PHP 5.

          Это случается как раз потому, что нашлись люди, которые осознали, что «нет никакой разницы на чем писать говно и никакой разницы на чем писать «конфетку»». Вместо того, чтобы скакать с языка на язык, эти люди делают по максимуму в том сообществе, в котором они выросли и учились.
          Начни в свое время рубисты переходит на более интересные языки (а такие были) — не было бы того Ruby коммьюнити, что есть сейчас. Да и рельс бы не было!
          Проблема не в языках, а в том, что мы на них пишем и насколько хорошо мы это делаем!

          Сейчас многие языки разиваются в сторону распараллеливания и тредов. Можно ли это в пхп написать и использовать? Нет, никто не будет писать.

          У многих языков (включая Ruby) давно есть поддержка тредов. Все проекты их примененяют? Нет? А почему? Потому что это не серебряная пуля! Потому что сложность и затратность разработки проектов с активным параллелизмом на основе тредов перекрывает большинство итоговых плюсов подобных проектов. Дешевая альтернатива тредам — событийные системы на основе евент-лупов, а они в Ruby точно так же не развиты, как и треды в PHP! Но это не значит, что Ruby — плохой язык и что всем надо срочно переходить на node.js. Это лишь значит, что для некоторого набора задач node.js с его event-driven натурой подходит больше, чем Ruby.

          Ну и по поводу
          никто не будет писать
          Не так давно многие думали, что и красивого BDD под PHP быть не может и никто его не будет писать!
          • 0
            Все верно
            Начни в свое время рубисты переходит на более интересные языки
            (оффтоп, по-моему, кроме python и не было ничего в то время)
            В том то и дело, что PHP не относился к более интересным язык и вообще интересным. На руби остались, да, написали рельсы.

            Про треды был просто пример темпа развития PHP (в нем нет даже намеков на
            это как в руби).
            Если язык не так важен, то почему ни у кого нет желания переходить с других языков писать тот самый качественный код на PHP? потому, что он, как язык, ничем не примечателен и допустил слишком много legacy-программистов и legacy-кода.

            За Behat спасибо.
        • 0
          а можно спросить, что не так с поддержкой utf8 у текущей версии PHP?
      • +1
        Для заказчика зачастую никакой, да. Но мы тут говорим о программистах. Любую задачу можно качественно решить и на ASM'е, но отчего-то никто на нем вебы не программирует. Ruby банально удобнее PHP, тут даже холиварить не нужно. Практически все, что появляется нового в PHP уже давно есть в Ruby. Практически все, что появляется в топовых PHP-фреймворках, уже давно есть в Рельсах. При этом зачастую один и тот же функционал выглядит в Рельсах гораздо красивее в плане синтаксиса (посмотрите, например, на валидации в Yii и в Рельсах).
        Не могу спорить, что PHP и его фреймворки когда-то дорастут до RoR, но нынешние темпы развития как-то не располагают верить в это…
        • 0
          Любую задачу можно качественно решить и на ASM'е, но отчего-то никто на нем вебы не программирует.

          Ну давайте не будем сравнивать красное с деревянным. Вы же прекрасно понимаете, что драйвера и микроконтроллеры на Ruby/PHP тоже не напишешь. Мы говорим про языки одного уровня. В данном случае, повторюсь: в Ruby нет ничего, что бы было невозможно использовать/написать в PHP!

          Ruby банально удобнее PHP, тут даже холиварить не нужно.

          Дела вкуса. Я не питаю иллюзий. PHP в достаточной степени ужасен, чтобы его ненавидеть. Но в нем есть все, что нужно чтобы писать и использовать красивые приложения. Нужен синтаксический сахар? Так опять же, есть языки и покрасивее/полаконичнее Ruby.

          Практически все, что появляется нового в PHP уже давно есть в Ruby.

          Это достоинство коммьюнити, а не языка. Смотрите мой коммент выше! Если бы с Ruby все в свое время многие начали переходить на более интересный язык — ничего бы из того что «уже давно есть в Ruby» не было!

          При этом зачастую один и тот же функционал выглядит в Рельсах гораздо красивее в плане синтаксиса (посмотрите, например, на валидации в Yii и в Рельсах).
          Не могу спорить, что PHP и его фреймворки когда-то дорастут до RoR.

          Посмотрите на Symfony2+Doctrine2. PHP не надо «дорастать до RoR», чтобы писать на нем фрэймворки уровня, а то и лучше (а мне действительно многое в sf2 нравится больше) рельс.
          • 0
            PHP в достаточной степени ужасен, чтобы его ненавидеть.

            Вот этим все и сказано.

            Если бы с Ruby все в свое время многие начали переходить на более интересный язык — ничего бы из того что «уже давно есть в Ruby» не было

            Коммьюнити у PHP во много раз больше, чем у Ruby. А толку от этого мало. Не PHP плох из-за ухода людей, а люди уходят, потому что PHP плох.
            И вообще ход мыслей странный. Зачем использовать неудобный язык, если есть удобный, ты его знаешь и имеешь возможность его использовать?

            Посмотрите на Symfony2+Doctrine2. PHP не надо «дорастать до RoR», чтобы писать на нем фрэймворки уровня, а то и лучше (а мне действительно многое в sf2 нравится больше) рельс.

            Symfony, к сожалению, настолько не знаю, чтобы спорить на его счет, но пока столкновения с ним не вселили веру в победу PHP.
            • 0
              Вот этим все и сказано.

              «Bad parts» есть в каждом языке и это ровным счетом ни о чем не говорит.

              Не PHP плох из-за ухода людей, а люди уходят, потому что PHP плох.

              Люди уходят потому что склонны верить в сказки об идеальных языках и фреймворках. Люди считают, что вот сейчас на PHP они пишут гавно, а перейдя завтра на Ruby они станут штамповать конфетки. Такого нет и не будет. Человеку, неспособному писать красиво на PHP будет в 1000 раз легче писать некрасиво и на Ruby. На node.js сейчас пишутся красивые библиотеки не оттого, что javascript не позволяет писать гавно. В JS гавна на порядки больше, чем в PHP и возможности писать гавно там на порядки выше, да и «bad parts» там в разы больше! Но красивые библиотеки для node.js пишут. Все дело в том, что пишут их вчерашние Ruby девелоперы с опытом «писать код красиво»! Вот и все. Коммьюнити решает, а не язык. PHP уже неоднократно доказал свою состоятельность как языка, на котором можно писать красиво. Мне этого достаточно.

              Зачем использовать неудобный язык, если есть удобный

              Понятие удобства каждый определяет для себя сам. Для меня удобно все, где с минимальными затратами я могу написать красивый код, который будет работать стабильно. Мою компетенцию в красивом и стабильном коде можете оценить по Behat, jade.php и другим моим проектам.
              А многим людям приходится для своего удобства писать новый язык программирования. Но это не значит, что все старые языки сразу становятся ужасными. Это лишь значит, что понятия удобства каждый из нас определяет для себя сам.
              • 0
                Ладно, тут спорить бесполезно… Все доводы сводятся к «на PHP можно тоже писать хороший код»… Просто если что-то можно написать на языке, код на котором займет меньше времени и сил, будет короче и нагляднее без потерь в качестве, я выберу этот язык. У Вас, очевидно, несколько другой взгляд…
                • 0
                  У меня просто взгляд человека, который понимает, что не язык развивает коммьюнити, а коммьюнити развивает язык.
                  Я просто стараюсь сделать мир лучше с теми знаниями, что имею ;-)
                • 0
                  Даже если действительно можно писать код на ruby, который займёт меньше времени и сил, чем на php, то на выбор языка влияет не только этот фактор. Даже для разработки «под себя», не говоря уж о заказной.

                  Навскидку, у PHP больше сообщество (больше вероятность что в твоем коде разберётся разработчик «с улицы», да и стоить он, скорее всего, будет дешевле) и более развитая инфраструктура (больше вероятность, что твой код заработает на произвольном хостинге, да и самих php-хостингов больше, а значит они дешевле)

                  P.S. А лично мне не показалось что проще, если иметь в виду традиционную веб разработку: многие нужные в вебе вещи в php являются частью языка, а в ruby требуют дополнительных усилий — для банального «hello %username%» нужно чуть ли не свой сервер и шаблонизатор писать или использовать только CGI и писать код типа «puts 200 OK...». Впрочем, это касается многих ЯП общего назначения, от ассемблера до функциональных. Но это вызывает неудобство для перехода с PHP даже для оценки, а вдруг действительно другие языки лучше. Сам язык оценишь — вроде лучше, пытаешься написать hello world и с такими закидонами встречаешься
                  • 0
                    Вы привели чудесный набор мифов о Ruby =) Если есть желание — в личку могу опровергнуть.
                    • 0
                      Вы про какую часть коммента? Если про первую (до постскриптума) — то возможно и мифы (откуда-то знаю, но сам анализ точно не проводил специально), а если про вторую, то это личный опыт попыток расширения кругозора.
                      • 0
                        Про обе.

                        По первой части:
                        — у Ruby есть замечательное сообщество, оно меньше по численности, но намного сплоченнее, приезжайте на RubyConfUA 2011 в сентябре, чтобы убедится.
                        — Инфраструктура Ruby и Rails в разы лучше чем вы можете себе представить: инструменты для развертывания серверов и деплоя applications (Chef, Capistrano), замечательные серверные средства (Unicorn, Passenger), мощнейшие фреймворки для тестирования и CI, в общем, вот так практически для всего (см. ruby-toolbox.com).
                        — Разработчик на PHP дешевле на старте, но с учетом вышесказанного и учитывая более мощный и читаемый язык, проекты которые больше чем homepage стоят в разы дешевле.

                        По второй части:
                        — Никто не пишет puts 200 OK, для низкого уровня есть rack.rubyforge.org/, над rack есть Sinatra и Rails.
                        — Для банального hello %username% есть Erb, HAML и Liquid

                        В общем, было бы желание и человек которого поспрашивать можно.
                  • 0
                    Пардон, что в PHP является частью языка и чего нет в Ruby? Если уж на то пошло, ответ сервера формирует не PHP, а, собственно, сервер. Ну, напишите на Ruby puts 'hello %username%', пользуйте mod_fastcgi под тот же апач, в чем проблема-то? В том, что не mod_php?
                    А если под Ruby имелись ввиду Рельсы, то приведенный пример характерен для чуть более чем 99,999455646% фреймворков.
                    • 0
                      Парсинг HTTP запроса (метод, параметры, куки, прозрачная реализация сессий), поддержка формирования ответа (поверю на слово, что его формирует сервер, а не интерпретатор, хотя был уверен в обратном, казалось что любое fastcgi приложение передаёт серверу готовый ответ, а сервер, в общем случае, лишь берёт на себя его доставку клиенту), «нативный» шаблонизатор (ещё бы :) ).

                      Как мне кажется, puts 'hello %username%' будет недостаточно для валидного HTTP ответа, как минимум нужно puts '200' сначала. И это будет, афаик, CGI, а не FastCGI. Для последнего, если не ошибаюсь, нужно писать дополнительную обвязку, пускай и из стандартных компонентов и не на уровне слушания сокетов и работы с процессами/тредами, а чуть повыше, но всё же ниже HTTP.

                      Имелся в виду как раз чистый язык, если брать рельсы, то нужно сравнивать ror не с голым php, а, например, с symfony (пускай и многое позаимствовавшей у рельс во младенчестве) или zend, yii, kohana,…
  • 0
    Черт, нечаянно начал холивор. Вообще, я хотел сказать только то, что если человек начал писать на этом языке, он ему нравится и в другом языке не хватает нужных ему инструментов — то почему бы не начать на нем работать постоянно. (Вообще я хотел хитро человека захедхантить, но потом глянул в профиль ;)

    Холиворить на тему X programming language vs. Y programming language абсолютно бессмысленно, для меня Ruby — кусок хлеба, для кого-то PHP — кусок хлеба и никто никакими аргументами не заставит меня кушать хлеб X, если мне нравится хлеб Y. Но если человек хвалит хлеб X но продолжает есть хлеб Y, то, согласитесь, резонно предложить ему есть, то что ему нравится (при условии что на рынке избыток хлеба X).

    Автор Behat молодец и как человек который плотно имел дело с внутренностями capybara хочу пожелать удачи и терпения в этом непростом деле.
    • 0
      Тут холивар случился скорее не в плане языка, а скорее в плане критериев выбора языка.

      Холиворить на тему X programming language vs. Y programming language абсолютно бессмысленно

      Холиварить вообще бессмысленно, вне зависимости от темы :) В спорах рождается истина, а в холиварах она умирает (с)
      • 0
        Тут холивар случился скорее не в плане языка, а скорее в плане критериев выбора языка.


        Тем более. Критерии выбора языка настолько субъективная штука, что тут вообще бессмысленно что-то доказывать.

        Кстати, интересно, где сейчас фрилансеры рельсовые обитают?
        • 0
          Я на oDesk пока обитаю по привычке.
  • 0
    Вот скольку не пытаюсь въехать в суть BDD, как-то не пойму её плюсов перед TDD… Вроде те же тесты по сути…
    • 0
      Человекопонятные. Тесты для того же Behat можно писать в тандеме с заказчиком — и ему спокойно, что вы все правильно оценили, и у вас готовые тесты.
      • 0
        Человекопонятность (почти естественный язык, жаль что не русский) — это базовое свойство BDD или лишь best practice при использовании некоторых фреймворков? То есть BDD это просто смена PHPUnit на Behat или что-то большее? Технически разницу вроде вижу, а вот концептуально…

        • 0
          *То есть переход от TDD к BDD это просто
        • +1
          Это не смена. Хотя и BDD выросло из TDD, TDD никто не отменял и не заменял.
          BDD относится к Acceptance Tests, т.е. грубо говоря вы пишите пользовательские сценарии на обычном английском (можно и на русском) языке, given/when/then и автоматическая среда тестирования проверяет что результат соответствует then. Такие вот тесты интерфейса. Классы, объекты и тому подобная функциональная часть никуда не делась, поэтому Unit тесты по-прежнему надо писать с помощью TDD.

          Как примерно процесс выглядит хорошо написано тут.

          PS: Не знаю почему такой шум вокруг BDD, наверно, кушать хочется всем, а про TDD слушать уже надоело %)
          • 0
            Забыл отметить. В BDD есть интересная особенность. Тесты начинаются не с префикса 'test' (как в PHPUnit и других фреймворках), а начинаются с (или содержат) ensureThat (убедиться что) и should (должно). Это практику хорошо использовать для написания хороших unit тестов тоже, т.е. вместо:
            public function testTotalFee{/*php*/}
            будет
            /* @test */
            public function totalFeeShouldIncludeOurFeeAndTax{/*php*/}
          • +1
            Вы все намешали в одну кучу. BDD — это эволюция TDD в полном смысле этого слова.

            На определенном этапе, чтобы привлечь больше разработчиков к тестированию своих продуктов, было решено пересмотреть объект тестирования. Отсюда появился BDD и так называемые «Specification Tests» или просто «specs». Это обычные юнит-тесты со слегка измененным синтаксисом, позволяющим представлять описанные тесты в виде спецификаций тестируемых объектов. Примерами specs фрэймворков являются RSpec/JSpec. И к примеру, RSpec вполне себе заменяет классический TestUnit, которым с каждым днем пользуется все меньше и меньше Ruby разработчиков…

            Немногим позже, родилось еще одно ответвление от BDD — так называемые «Scenario Tests». Это тесты, строящиеся вокруг понятия «сценарий» и последовательностей выполняемых шагов для достижения тестируемого состояния системы. Примерами сценарно-ориентированных BDD фрэймворков являются Cucumber/Behat/JBehave. И да, вот scenario-тесты больше подходят для acceptance тестирования, нежели для юнит-тестов.

            Вообще, BDD — это практика, объединяющая в себе TDD, DDD и Acceptance TDP. BDD фрэймворки успешно пытаются объединить эти 3 техники в одну систему и ветвятся на 2 самодостаточных стэка: specs тесты и scenario тесты. Первые призваны заменить классические unit тесты, добавив туда описательную часть. Вторые заменяют собой acceptance тесты, превращая функциональные тесты в «поведенческие» сценарии.
            • 0
              Ничего и не намешал %) Я не знал про разделение тестов на «Scenario» и «Specification», но в контексте Behat и вообще как BDD выглядит сейчас, можно говорить что это «Scenario Tests»
              BDD — это эволюция TDD

              BDD — это больше эволюция процесса разработки ПО, а не TDD (замену test на should я бы назвал рекомендацией, а не эволюцией).

              Вообще я отвечал куда делся TDD, и последний комментарий — «BDD — это практика, объединяющая в себе TDD, DDD и Acceptance TDP» — в закладки.

            • 0
              А никто не встречал «Specification Tests» фреймворков для PHP, наподобии Jasmin и jSpec?

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.