Skip to content
holywarez edited this page Feb 21, 2012 · 11 revisions

Настройка #cucumber, #bdd, #spork, #guard

Задача

Организовать удобный процесс тестирования проекта Try-Ruby. Подзадачи:

  • Внедрить тестирование через Cucumber
  • Сократить время запуска тестов с помощью Spork'а
  • Организовать автоматическое тестирование с помощью Guard

Cucumber и Spork

Добавим поддержку в проект

# Gemfile

group :test do
  gem "rspec-rails"
  gem 'cucumber-rails', require: false
  gem 'database_cleaner'
  gem 'spork-rails'
end

Настраиваем сразу с поддержкой spork.

 $ bundle install
 $ rails g cucumber:install --spork

Подготавливаем spork к поддержке cucumber'а

 $ spork cucumber --bootstrap

Пробуем запустить

 $ spork

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

Первый сценарий

Запустим в отдельной консоли spork:

 $ spork

Опишем работу нашего окна выполнения запроса:

# features/eval.feature

Feature: Eval ruby code

  Background:
    When I am on home page

  Scenario Outline: Evaluate code
    When I send a <code>
    Then I should se a <result>

  Examples:
    | code                                  | result      |
    | 2 + 1                                 | 3           |
    | "abc" * 3                             | "abcabcabc" |
    | 2 ** 10                               | 1024        |
    | class X; def x; 23; end; end; X.new.x | 23          |

И определим шаги для этого сценария:

# features/step_definitions/eval_steps.rb

When /^I am on home page$/ do
  visit '/'
end

When /^I send a (.*)$/ do |code|
  fill_in 'code', with: code
  find('[name=commit]').click
end

Then /^I should se a (.*)$/ do |result|
  page.should have_content("=> #{result}")
end

Запускаем:

 $ cucumber

Тест должен выполниться успешно.

 $ git add .
 $ git commit -am 'done: Cucumber with Spork support'

Guard

Уже круто, тесты выполняются в уже загруженном окружении. Но вот хочется, чтобы при сохранении сценариев и связанных файлов тесты выполнялись повторно, а еще лучше выборочно, только те, которые были измененны.

Что ж, для этого есть Guard. Приступим.

Установим сам Guard, а так же поддержку для Spork'а и Cucumber'а:

# Gemfile

group :development do
  gem "guard"
  gem "ruby_gntp"

  gem 'guard-spork'
  gem 'guard-cucumber'
end

И настраиваем:

 $ bundle install
 $ guard init
 $ guard init spork
 $ guard init cucumber

Доводим полученный Guard файл до следующего состояния:

# A sample Guardfile
# More info at https://github.com/guard/guard#readme

guard 'spork', rspec: false, test_unit: false, cucumber_env: {'RAILS_ENV' => 'test'} do
  watch('config/application.rb')
  watch('config/environment.rb')
  watch(%r{^config/environments/.+\.rb$})
  watch(%r{^config/initializers/.+\.rb$})
  watch('Gemfile')
  watch('Gemfile.lock')
  #watch('spec/spec_helper.rb') { :rspec }
  #watch('test/test_helper.rb') { :test_unit }
  watch(%r{features/support/}) { :cucumber }
end

guard 'cucumber', all_on_start: false, keep_failed: false, cli: '--drb --profile default -c' do
  watch(%r{^features/.+\.feature$})
  watch(%r{^features/support/.+$})          { 'features' }
  watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
end

Останавливаем spork, открытый ранее в отдельной консоли и пробуем запустить Guard:

 $ guard

По сообщениям в консоли должно стать понятно, что запущен Spork с поддержкой Cucumber.

Guard uses GNTP to send notifications.
Guard is now watching at '/Users/holywarez/work/labs/try-ruby'
Starting Spork for Cucumber
Using Cucumber, Rails
Preloading Rails environment
Loading Spork.prefork block...
Spork is ready and listening on 8990!
Spork server for Cucumber successfully started

Давайте попробуем поправить Guardfile, чтобы свойство all_on_start для cucumber'а было true. Guard должен отловить это изменение и перезапуститься. В результате должен выполниться наш тест.

В целом, свойство all_on_start можно удалить.

Теперь попробуем изменить eval_steps.rb так, чтобы отправка формы выглядела так:

  find('input[name=commit]').click

После сохранения заново должны выполниться только тесты для features/eval.feature. Так работает guard-cucumber, он видит что изменились step definition'ы для eval.feature, и поэтому определяет, что нужно выполнить заново только один feature-файл. Тоже самое произойдет, если внести правки в сам feature-файл.

Вот и Guard испекли.

 $ git add .
 $ git commit -am 'done: Guard support added'

Примечания

  • Если в консоли, выполняющей guard процесс, нажать Enter, запустятся все cucumber сценарии. Нажатый несколько раз Enter заставит выполнить в холостую несколько раз все ваши сценарии, что можно загрузить ваш компьютер на какое-то время. Будьте осторожны.
  • Если guard-cucumber не найдет прямого соответсвия между измененным step definition'ом и feature-файлом, то будут запущенны заново все сценарии проекта.

Debug в IDE

Если вы пользуетесь IDE (скажем, RubyMine) то вам захочется, кроме того, что тесты выполняется guard'ом, выполнить конкретный сценарий с использованием дебаггера. По крайней мере в RubyMine 4.0.1 у меня не вышло запустить сценарий в debug'е так, чтобы срабатывали breakpoint'ы.

Объяснение этому простое. Настройки по умолчанию для cucumber-конфигураций RubyMine'а берут профиль Cucumber'а под названием default. А если мы посмотрим в config/cucumber.yml, то увидим, что для этого профиля используется флаг --drb, и то, что мы запускаем из rubymine'а, выполняется в контексте Spork'а. Для того, чтобы постоянно не вписывать для конфигураций в RubyMine'е --profile, определим в файле config/cucumber.yml новый профиль spork и исправим default:

spork: --drb <%= std_opts %> features
default: <%= std_opts %> features

Затем исправим Guardfile таким образом, чтобы он использовал новый профиль:

  guard 'cucumber', keep_failed: false, cli: '--drb --profile spork -c' do
    # ...

Теперь любая конфигурация для cucumber'а должна работать отдельно от spork'а.

  $ git commit -am 'done: Cucumber profiles for supporting IDE'
  $ git push origin master

Ссылки

Отправные точки для дальнейшего изучения:

Clone this wiki locally