BDD с помощью Cucumber

    Если вы привыкли сначала писать код, а потом его тестировать, то с BDD такой подход совсем не уместен. Сила BDD в том, что он помогает вести разработку начиная со стадии оформления ТЗ. Для BDD это список свойств (фич), который уместно писать вместе с заказчиком.

    Но самое главное, что по этому же списку происходит автоматическое тестирование проекта. Инструмент тестирования (в нашем случае это Cucumber) методично пройдет по вашему перечню и дотошно проверит реализацию каждой фичи.

    Разработка с использованием Cucumber состоит из 3-х основных этапов.
    1. Описание фич проекта простым человеческим языком. И даже необязательно английским.
    2. Определение поступков (step definition) на Ruby
    3. Цикл разработки: проверка фич кукумбером и реализация не прошедших тестирование фич ручками.


    По завершению этого цикла, когда все свойства проходят контроль cucumber-а, мы утверждаем с заказчиком новый список фич и заново проходим весь цикл. Делаем это до тех пор, пока не реализуем (добавим и проверим) все свойства.

    1-й этап. Фичи.



    Список

    Например, мы, как всегда, разрабатываем новый blog. Вот и запишем свойства нашего блога в файл ./features/blog.features. Для каждого свойства опишем также понятия Зачем, Кто и Что (In order, A, Should). Это пожелания BDD, на самом деле на результат они не влияют, но зато помогают нам самим более четко сформулировать чего-же мы хотите от этой фичи.

    Feature: Post articles
    
      In order to show trip photos
      A owner
      Should be abble to post article
    
    Feature: Make comments
    
      In order to contact
      A user
      Should be abble to make comments
    


    Конечно, не обязательно сразу выписывать все свойства, достаточно тех, которые вы намереваетесь реализовать в ближайшем этапе.

    Сценарии


    Свойство имеет одно или несколько сценариев поведения. Именно по этим сценарием и происходит тестирование. Каждый сценарий описывается тремя категориями: Условие (Given), Событие (When), Результат (Then). Если у вас несколько условий, событий или результатов, то дополнительные прописывается через And/But.

    Feature: Post articles
    
      In order to show trip photos
      A owner
      Should be abble to post article
     
      Scenario: Post article by owner
    
        Given I signed up as owner
        When I write article "About my last nigh trip"
        And text of article is "It was very hard night.."
        And I post article
        Then I should see "Article is created"
    
      Scenario: Post article by user
    
        Given I signed up as user
        When I write article "My fantazy"
        And text of article is "..no more"
        And I post article
        Then I should see "You have no access to post articles"
    


    На этом этапе мы уже имеем понятный человеку и инструменту тестирования список фич. И уже сейчас можно запускать:

    > cucumber features/blog.features
    
    ...
    
    2 scenarios (2 undefined)
    12 steps (12 undefined)
    0m0.012s
    
    You can implement step definitions for undefined steps with these snippets:
    
    Given /^I signed up as owner$/ do
      pending
    end
    
    When /^I write article "([^\"]*)"$/ do |arg1|
      pending
    end
    
    When /^text of article is "([^\"]*)"$/ do |arg1|
      pending
    end
    
    When /^I post article$/ do
      pending
    end
    
    Then /^I should see "([^\"]*)"$/ do |arg1|
      pending
    end
    


    Cucumber подсказывает что делать дальше, какие поступки нам необходимо определить (step definition).

    Этап 2. Определение поступков (step definition)



    Копируем подсказку cucumber-а в /features/step_definitions/blog_steps.rb и прописываем поступки, например:

        Given /^I signed up as (.*)$/ do |role|
           current_user=User.find_by_role(role)
        end
    
        When /^I write article "([^\"]*)"$/ do |arg1|
            aricle=Article.create(:subject=>arg1,:user=>user)
            same_subject=subject
        end
    
        When /^text of article is "([^\"]*)"$/ do |arg1|
          aricle.text=arg1
        end
    
        When /^I post article$/ do
          artricle.save!
        end
    
        Then /^I should see "([^\"]*)"$/ do |arg1|
           response.should contain(arg1)
        end
    


    Теперь у нас готов и список фич и определено их поведение.

    Этап 3. Тестирование и разработка



    Запускаем тест:

    > cucumber  features/blog.features
    
    Feature: Post articles
      In order to show trip photos
      A owner
      Should be abble to post article
    
      Scenario: Post article by owner                                              # features/blog.features:6
        Given I signed up as owner                                                 # features/step_definitions/blog_steps.rb:1
          uninitialized constant User (NameError)
          features/blog.features:7:in `Given I signed up as owner'
        When I write article "About my last nigh trip"                             # features/step_de
    


    Как видно, cucumber сообщил о том, что не знает ни о каком User. В таком случае создаем код модели User.

    Опять запускаем Cucumber. На этот наз он ругается о другой ошибке — реализуем еще код дабы исправить ее и т.д. до тех пор.

    Когда у cucumber пройдут все тесты — весь код будет реализован. Таким образом мы закончили 3-й этап и можно переходить к дальнейшему дизайну приложения и реализации новых фич.

    Если интересно, в следующий раз расскажу и покажу как разрабатывается реальное приложение с Cucumber, Shoulda и волшебником webrat.

    PS



    Материалы:

    cukes.info — Сайт cucumber
    nlp.od.ua/behavoir-driven-development — На русском о BDD
    railscasts.com/episodes/155-beginning-with-cucumber — screencast Cucumber для начинающих
    github.com/thoughtbot/clearance/tree/master — Clearance имеет отличный пример использования cucumber-а
    Метки:
    Поделиться публикацией
    Похожие публикации
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 21
    • 0
      Спасибо за статью! Лучики вам счастья!
      • +2
        А почему не на русском, cucumber прекрасно с ним работает, вот пример:

        Функционал: Сложение чисел
        Чтобы не складывать в уме
        Все, у кого с этим туго
        Хотят автоматическое сложение целых чисел
        Сценарий: Сложение двух целых чисел
        Допустим я ввожу число 50
        И затем ввожу число 70
        Если я нажимаю "+"
        То результатом должно быть число 120

        Вот еще немного примеров

        Не знаю как вам, а мне очень нравится :)
        • 0
          Круто, самое то для заказчика!
          • 0
            Заставить заказчика писать тесты — это нереально круто. Может со временем научится make them pass :)
            • 0
              Не за него, а вместе с ним :)
          • 0
            Не знаю как вам, а мне очень нравится :)

            Тут вопрос даже не в том — нравится или нет. А в том — на каком языке вся остальная документация по проекту. Вообще важно писать сценарии приемочного тестирования на том же языке, что и вся остальная документация, так как таким образом не происходит расхождения в терминологии. Терминологические войны в проекте — та еще головная боль.
          • 0
            Интересная вещь.
            Есть аналоги для других языков?
            • 0
              Да, причем файл настроек не большой.

              С русским есть только одна проблема — интеграция со свойствами других проектов (плагинов и модулей) коих в своем великое множество — получается каша. Ну и еще по умолчанию некоторыми пакетами многие поступки уже прописываются на английском.
              • 0
                Если вы о языках програмирования, то Cucumber умеет работать с Java (Jruby).

                Так же ближайшим временем выйдет аналог под python, дайте только допилю до нормального состояния:).
                • 0
                  > Так же ближайшим временем выйдет аналог под python, дайте только допилю до нормального состояния:).
                  Очень ждем :)
                  Работа с ним будет такой же легкочитаемой? :)
                  • 0
                    Да, синтаксис feature-файлов копируем от Cucumber. В текущей реализации будет даже менее строго.
                • 0
                  Есть аналоги для других языков?

                  Behave for Python
                • –4
                  Я подумал, что речь о Binary decision diagrams пойдёт :)
                  • 0
                    Интересно, расскажи где они применяются и с чем едят.
                    • 0
                      Основная идея — использование преимуществ табличного подхода, не спотыкаясь о его недостатки. Т.е. повышение скорости (которая теперь линейно зависит от количества переменных) вычисления функции при небольшом размере структуры данных.

                      Применяться могут везде, где нам необходимо быстро получить результат для небыстрой функции с небольшой областью применения (для примеров из википедии, состоящей из 2 элементов, а по сути вспомним, что у нас везде биты — мы ведь можем выразить функцию как набор булевых функций, например). Также BDD обладают свойством уникальности — для данной функции при данном порядке переменных существует единственный ROBDD. Поэтому может применяться для формальной верификации, проверки на эквивалентность.

                      Мне в этой структуре нравятся три вещи

                      1. Идея реализовать булеву функцию в виде графа, ускоряя вычисления.
                      2. Возможность производить вычисления не распаковывая BDD.
                      3. Уникальность.

                      И не нравится, что нахождение оптимального порядка переменных — NP полная задача (O(N!) кажется).

                      К сожалению, это оффтопик, поэтому здесь остановлюсь.

                      И спасибо за статью!
                  • 0
                    Очень интересно! Продолжайте пожалуйста!
                    • +1
                      в целом весьма неплохо, но:

                      я, конечно, не гуру бдд, но перевод «step definition» как «описание поступков» сомнителен. я бы перевел как «описание шагов» либо «реализация шагов».

                      еще. пример не очень удачен. по крайней мере в том виде в котором он есть — работать не будет. по многим причинам. начиная с того, что article — локальная переменная, заканчивая тем, что контроллер не дергается, а соответственно response будет nil. и вообще, описание шага Then I should see «something» идет вместе в webrat'ом.

                      и еще. если уж речь идет о конкретном инструменте, неплохо для начала дать описание как настроить environment с cucumber'ом (хоть под рельсами, хоть без них), дать описание структуры директорий.

                      да, я зануда. извините.
                      • 0
                        Вы правы.

                        Дело в том, что цель статьи ознакомить с методикой и только. Хотя приведенные выше тесты в рамках cucumber-а рабочие — проверено. Что касается нюансов реализации поступков, то они описаны так умышленно, для упрощения понимания, опять таки работы самого cucumber-а.

                        Насчет «шагов» и «поступков» вы также правы. Но мне больше нравится слово «поступки», так как «шаги» часто употребляется с иными контекстом и может ввести в заблуждение. Слово шаги также подразумевает некоторую этапность, которая в случае с (step definition) отсутствует.

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

                        Согласен, нужно освятить этот вопрос более подробно, но для этого необходимо также ввести публику и shoulda, и в webrat, также желательно ознакомить factory_girl и mocha, иначе не будет понятно где мы говорим о BDD и огурце, а где применяем другие инструменты.

                        Предлагаю разделиться и написать нам статьи по этим темам. А в конце заключительную статью, в которой полностью рассмотрим разработку реального приложения с помощью этих инструментов.

                        Что выбираете?
                      • 0
                        Отличная тематика, если у вас есть, что рассказать, продолжайте, не останавливайтесь на этом!
                        • 0
                          Все конечно замечательно, спасибо и все такое, но… чем эта статья отличается от тупо перевода скринкаста, указанного в конце статьи? Там еще и подробнее все описано, и понятнее, и… работает!
                          • 0
                            Для BDD это список свойств (фич), который уместно писать вместе с заказчиком.

                            Уже набило оскомину утверждение, с заказчиком можно/нужно писать сценарии на Gherkin-е. С заказчиком нельзя написать полноценные сценарии тестирования. Заказчик — это такой зверь, которому нужно подавать решение его проблемы в самом вкусном и удобовоспринимаемом виде. Иначе не будет переварено.

                            Да даже, если речь идет о том, что вы при заказчике пишете сценарии, сами конвертируя в них его требования, то это не будет оценено по достоинству. Заказчику нужна картинка.

                            Это может быть, например, презентация с набором диаграмм (например user story и job story), но никак не техническая спецификация, коей является Gherkin.

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

                            В других же случаях Gherkin при работе с заказчиком пригодится лишь на этапе утверждения объема работы на разработку. Мол мы вам привели в формально изложенном виде то что будет нами сделано, вы утвердили, мы разрабатываем. И делать это нужно только когда все это было уже изложено в более удобоваримом виде.

                            В общем, хватит людей в заблуждение вводить. Тут явно должны быть какие то другие формулировки. (Никаких претензий к переводчику, так как в общем статья полезная)

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