26 February 2009

Экстремальное программирование, знакомство с Behavior Driven Development и RSpec

IT systems testing

Теория


Для начала, давайте разберемся, что же такое Behavior Driven Development(в дальнейшем BDD) и чем данная техника отличается от Test-Driven Development(в дальнейшем TDD)

Разрабо́тка че́рез тести́рование (англ. test-driven development) — техника программирования, при которой модульные тесты для программы или её фрагмента пишутся до самой программы (англ. test-first development) и, по существу, управляют её разработкой. Является одной из основных практик экстремального программирования.

Хотя подход с предварительным тестированием работает у многих, он подходит не для всех. На каждого разработчика приложений, с успехом применяющего TDD, найдется несколько разработчиков, активно отрицающих этот подход. Несмотря на многочисленность инфраструктур тестирования, таких как TestNG, Selenium и FEST, все равно находится много причин не выполнять тестирование кода.

Две обычные причины отказа от TDD – «у нас недостаточно времени для тестирования» и «код слишком сложный и трудно проверяемый». Другой преградой для программирования с предварительным написанием тестов является сама концепция «тест пишется до кода». Большинство рассматривает тестирование как осязаемое действие, скорее конкретное, нежели абстрактное. Опыт подсказывает, что невозможно проверить то, что еще не существует. Для некоторых разработчиков, остающихся в рамках этой концепции, идея предварительного тестирования — просто оксюморон.

Но что если вместо того, чтобы думать в терминах написания тестов и тестирования компонентов, начать думать о функциональности? Говоря про функциональность, я имею в виду как приложение должно вести себя, фактически его спецификацию.

На самом деле большинство из нас уже и так думает подобным образом. Смотрите:

Фрэнк: Что такое стек?

Линда: Это структура данных, хранящая объекты в порядке «первым вошел, последним вышел» или «последним вошел, первым вышел». Обычно у этой структуры есть API с такими методами, как push() и pop(). Иногда присутствует метод peek().

Фрэнк: Что делает метод push()?

Линда: Метод push() принимает входной объект, например, foo и помещает его во внутренний контейнер, например, массив. Метод push() обычно ничего не возвращает.

Фрэнк: Что будет, если передать методу push() два объекта, например, сначала foo, а потом bar?

Линда: Второй объект bar должен оказаться наверху концептуального стека, содержащего по крайней мере два объекта, так что при вызове метода pop() объект bar должен быть извлечен первым, до первого объекта foo. Если метод pop() вызвать еще раз, должен быть возвращен объект foo и стек должен стать пустым (предполагается, что в нем ничего не было до того, как мы добавили эти два объекта).

Фрэнк: Так метод pop() удаляет самый последний элемент, добавленный в стек?

Линда: Да, метод pop() должен удалить верхний элемент, при этом предполагается, что в стеке есть элементы, чтобы их удалять. Метод peek() работает точно также, но при этом объект не удаляется. Метод peek() должен оставить верхний элемент в стеке.

Фрэнк: Что будет, если вызвать метод pop(), когда в стек еще ничего не было добавлено?

Линда: Метод pop() должен выдать исключение, показывающее, что в стек еще ничего не добавлялось.

Фрэнк: Что будет, если выполнить команду push() null?

Линда: Стек должен выдать исключение, так как null не является допустимым значением для метода push().

Можно ли выделить что-нибудь особенное в этом диалоге, кроме того, что Фрэнк не силен в структурах данных? Нигде не использовалось слово «тестирование». Однако слово «должен» проскальзывало регулярно и звучало довольно естественно.

В подходе BDD нет ничего нового или революционного. Это просто эволюционное ответвление подхода TDD, где слово «тест» заменено словом «должен». Если отложить в сторону слова, то многие найдут понятие «должен» более естественным для процесса разработки, чем понятие «тест». Мышление в терминах функциональности (того, что код должен делать), приводит к подходу, когда сначала пишутся классы для проверки спецификации, которые, в свою очередь, могут оказаться очень эффективным инструментом реализации.

Практика


RSpec — это BDD framework для Ruby

Установка:
[sudo] gem install rspec
либо
git clone git://github.com/dchelimsky/rspec.git
cd rspec
rake gem
rake install_gem
Давайте представим, что вашим заказчиком является банк. Проиллюстрируем, еще раз, диалог с заказчиком, в стиле BDD:
Вы: Пожалуйста, опишите, каким должен быть счет после его создания?
Заказчик: Счет должен иметь баланс равный $0.

Вот как мы опишем данный разговор в RSpec:
describe Account, " when first created" do

 before do
  @account = Account.new
 end

 it "should have a balance of $0" do
  @account.balance.should eql(Money.new(0, :dollars))
 end
 
 after do
  @account = nil
 end

end

* This source code was highlighted with Source Code Highlighter.

Если выполнить этот пример, RSpec может вернуть подобное описание:
Account, when first created
— should have a balance of $0

Пример того, как вы можете использовать #before и/или #after блоки, в вашем коде:
describe Thing do
 before(:all) do
  # This is run once and only once, before all of the examples
  # and before any before(:each) blocks.
 end

 before(:each) do
  # This is run before each example.
 end

 before do
  # :each is the default, so this is the same as before(:each)
 end

 it "should do stuff" do
  ...
 end

 it "should do more stuff" do
  ...
 end

 after(:each) do
  # this is before each example
 end
 
 after do
  # :each is the default, so this is the same as after(:each)
 end

 after(:all) do
  # this is run once and only once after all of the examples
  # and after any after(:each) blocks
 end
 
end

* This source code was highlighted with Source Code Highlighter.

В заключение


Если статья получит положительные отзывы, то появиться цикл статей на данную тему.
Для затравки, ниже несколько ссылок для углубленного, самостоятельного изучения:

Оффициальная документация (англ.)
Хороший пошаговый мануал (англ.)
Разработка через тестирование (рус.)
Знакомство с Behavior Driven Development (BDD) (рус.)
Определение BDD (англ.)
Кратки мануал по RSpec (англ.)
Определение TDD (рус.)
Tags: Behavior Driven Development Test-Driven Development TDD BDD RSpec тесты разработка через тестирование экстремальное программирование
Hubs: IT systems testing
+45
37.1k 99
Comments 36
Ads
Top of the day