aslakhellesoy / cucumber

BDD that talks to domain experts first and code second

Home | Edit | New

Migration From RSpec Stories

Migrating from RSpec Stories to Cucumber

Migrating from RSpec stories is not as hard as you might think. This guide is based on my experience from
migrating over a relatively large set of stories in a Rails project.

First, follow the Cucumber installation instructions for Rails. This should leave you with a features directory that looks like this:

+-features/
  +-step_definitions/
    +-webrat_steps.rb
  +-support/
    +-env.rb

The env.rb loads the environment and is a good place to move any pertinent code from your old stories/helper.rb. For example, if you had been monkey-patching the Spec::Story::World module to add global story helpers you can move its contents directly into env.rb.

Move a plain text story over

For example:

[git|svn] mv stories/foo.story features/foo.feature

You can do this in bash if you are under a Unix system:


cd stories
for file in $(ls *.txt); do [svn|git] mv $file ../features/`echo $file | sed s/.txt/.feature/`; done;

Try to run the feature you moved:

rake features

At this point you should see a lot of yellow (pending steps).

If you see a Cucumber::TreetopParser::Feature::SyntaxError, you may have to tweak your file – according to the error message. The syntax (grammar) for RSpec stories and Cucumber features should be similar, but you might run into differences.

Move over your step definitions

[git|svn] mv stories/steps/*.rb features/steps

Remove the ‘steps_for’ declaration and corresponding block out of your step files, just leaving your Given, When, and Then step definitions.

Try to run the feature again:

rake features

If you’re like me – you haven’t got your steps exactly in the directory that cucumber expects by default
(features/steps/*.rb), you may want to pass some options to the rake task.

In my project I had rails-specific steps under steps/rails and watir-specific ones under steps/watir.
In order to run features without watir I had to do this:

Cucumber::Rake::Task.new(:rails) do |t|
  t.cucumber_opts = "--format pretty --require features/steps/env.rb --require features/steps/common_webrat.rb"
  t.step_pattern = "features/steps/rails"
end

Later, I moved the env.rb and common_webrat.rb files under the steps/rails directory and removed the —require
arguments. This was much cleaner:

Cucumber::Rake::Task.new(:rails) do |t|
  t.cucumber_opts = "--format pretty"
  t.step_pattern = "features/steps/rails"
end

Migrating your Story Listeners

With the story runner StoryListeners were being used to function as setup and teardown mechanisms. Cucumber has Before and After methods, similar to RSpec’s example framework, for setup and teardown between scenarios. All global setup can be done in the env.rb file, and for global teardown the at_exit hook can be used in the env.rb file as well.

Here is a simple example of the conversion process. Given this story listener:


  class MyStoryListener
    def run_started(number_of_scenarios)
      # Global setup
      ActionMailer::Base.delivery_method = :test
      ActionMailer::Base.perform_deliveries = true
    end
    
    def scenario_started(story, scenario)
      # Scenario setup
      ActionMailer::Base.deliveries.clear
    end
    
    def scenario_succeeded(*args)
      # Scenario teardown
      DatabaseCleaner.clean
    end
    alias :scenario_pending :scenario_succeeded
    alias :scenario_failed :scenario_succeeded
    
    def run_ended
      # Global teardown
      TempFileManager.clean_up
    end
  end
  
The resulting Cucumber conversion would look like this (in your env.rb file):

  # Global setup
  ActionMailer::Base.delivery_method = :test
  ActionMailer::Base.perform_deliveries = true
  
  Before do
    # Scenario setup
    ActionMailer::Base.deliveries.clear
  end
  
  After do
    # Scenario teardown
    DatabaseCleaner.clean
  end
  
  at_exit do
    # Global teardown
    TempFileManager.clean_up
  end
Last edited by gramos, Fri Jun 19 12:28:54 -0700 2009
Home | Edit | New
Versions: