June 5, 2010
Rails 3, RSpec, and Cucumber
This is a walkthrough of getting Rails 3 up and running with RSpec and Cucumber.
Rails 3 and Rails 2 don’t play nicely together, so I recommend you use RVM to create a separate gemset for Rails 3. (I did all this under Ruby 1.9.1 just for fun. YMMV.)
Rails 3
To install the latest rails pre-release (Rails 3 beta 3 at the time of this writing):
gem install rails --pre
It’s got a lot of dependencies nowadays, so enjoy watching them all scroll past.
Now let’s create a little Rails app to try it out. The laws of Rails physics dictate that it must be a blog, so:
rails new blog --skip-testunit
(If you’re on a version of Rails 3 earlier than beta 4, you’ll need to leave out the “new” from the above command.)
Given we’re going to be installing RSpec, I've told it to skip over creating the test directory.
If you’re a git user (which you should be), now is a good time to check stuff in:
cd blog git init git add . git commit -m "Initial import."
Rails 3 has, rather thoughfully, already set up a .gitignore file for you, and sprinkled .gitkeep files in directories that need to stick around.
RSpec
Ok, now you need to start getting friendly with Bundler. Edit your app’s Gemfile and add the following:
group :test do gem 'rspec-rails', '>= 2.0.0.beta.10' end
Then, to install the gems, just run this from your app’s root directory:
bundle install
Now to add the necessary bits and bobs to your app:
script/rails generate rspec:install
(Notice how all the various commands under the script directory have gone away in Rails 3? Everything now lives under the single rails command.)
Magic! Now you can tell Rails 3’s fancy new generators to always use RSpec rather than Test::Unit. Open up your config/applicaton.rb and find the commented out section relating to generators. Add this:
config.generators do |g| g.test_framework :rspec end
Let’s try it out:
$ script/rails generate model post title:string body:text published:boolean
invoke active_record
create db/migrate/20100605021005_create_posts.rb
create app/models/post.rb
invoke rspec
create spec/models/post_spec.rb
Check it out! A migration, a model, and a spec file. Fancy, huh? Does it really work?
$ rake db:migrate == CreatePosts: migrating ==================================================== -- create_table(:posts) -> 0.0021s == CreatePosts: migrated (0.0022s) =========================================== $ rake spec * Finished in 0.01027 seconds 1 example, 0 failures, 1 pending Pending: Post add some examples to (or delete) ./spec/models/post_spec.rb (Not Yet Implemented) # ./spec/models/post_spec.rb:4
Yep, sure does! It even gives you a helpful pending spec to cajole you into writing some proper tests.
Cucumber
Setting up Cucumber is a similar process. First add this to your Gemfile:
group :cucumber do gem 'capybara' gem 'database_cleaner' gem 'cucumber-rails' gem 'cucumber', '0.7.3' gem 'rspec-rails', '>= 2.0.0.beta.10' gem 'spork' gem 'launchy' # So you can do Then show me the page end
Then use Bundler to install everything:
bundle install
And set up your Rails app:
script/rails generate cucumber:skeleton --rspec --capybara
Now you’re off and running, and can start adding features and step definitions to your heart’s content.
I recommend not using the feature generator. It generates feature-coupled steps, which is considered an anti-pattern. Write your own feature files from scratch, and put your steps in files corresponding to the models they work with. The RSpec Beta Book has really good advice on how to structure your features and steps.
(As of this writing, rake cucumber spits out a rather noisy warning when you run it. If you’re lucky, they've already been fixed by the time you’re reading this. If not, you can safely ignore them.)
What Now?
I strongly recommend you check out the latest RailsCasts on Rails 3, in which Ryan Bates is doing an awesome job of covering the best new features.
Awesome post! Thank you for the step by step description.
Hey great article. Very helpful for me :)
I would just add one thing: make sure that the rubygems version is 1.3.6 or higher, as anything before that seems to cause a ton of warnings before any cucumber or rake command.
Thanks!
Thanks for the great info. I found that everything installed fine but when I tried running cucumber it didn’t work. I removed the version parameter for cucumber in the gemfile, rebundled and it all worked. This installed v0.8.3. With this version the generate command is now cucumber:install instead of cucumber:skeleton.
I got no such file to load — gherkin/parser/tag_expression
when trying this with Rails 3.0.0.rc
I changed the cucumber requirement from ‘0.7.3’ to ‘0.8.5’ and it works. The moral of the tale: Check for the latest cucumber version!
This seemed to work for me: ruby script/rails generate cucumber:install —rspec
Thanks for the writeup Pete, great stuff! I didn’t see the pending spec when I ran ‘rake spec’ and then found this that explains why:
http://blog.davidchelimsky.net/2010/07/11/rspec-rails-2-generators-and-rake-tasks-part-ii/
After making the change to put rspec-rails in :development things are all good.
Would you happen to know where script/spec has gone? Rake spec works fine, but how would I run an individual spec? If I use the global spec command I get: .rvm/rubies/ruby-1.8.7-p299/lib/ruby/site_ruby/1.8/rubygems.rb:335:in `bin_path': can’t find executable spec for rspec-2.0.0.beta.19 (Gem::Exception).
This all works fine for me until “script/rails generate cucumber:skeleton —rspec —capybara” which results in “Could not find generator cucumber:skeleton”.
My only deviation from the instructions above is that I'm specifying ‘rspec-rails’, ‘>= 2.0.0.beta.10’ and ‘cucumber’, ‘0.8.5’.
Thanks for the helpful post! I noticed a small typo: apparently as of rails 3.0.0rc, the arg is —skip-test-unit (note extra dash). I think it doesn’t affect the outcome of the content here, but it may surprise some folks that the stock tests would get created anyway.
tomtt,
The spec command is gone in rspec 2. It’s become “rspec”.
If you want to use spec for say rspec 1.3.0, you’ll want to do “spec 1.3.0 spec/something”
Take a look here for info: https://rspec.lighthouseapp.com/projects/5645/tickets/953-having-rspec2-on-the-system-breaks-rspec-13#ticket-953-15
So this post inspired me to update a project of mine called Beet. The steps above are simple, but I hate repeating them on each new idea/prototype/etc, so I've updated Beet to a) work with rails 3 and b) do these steps for you.
You can take a look at the rails 3 branch here:
http://github.com/jackdempsey/beet/tree/rails3
Currently you’ll need the source checked out to do this, but once you've cloned it, you can quickly repeat the above steps with just this command:
$ beet_top_level/bin/beet -g -r rails3/testing/cucumber
-g generates a new project, and -r specifies a recipe to run. This does assume that your rails command is bound to the rails 3 version, and the recipe currently doesn’t do the —skip-test-unit piece. I'm thinking about allowing recipes to setup options for the rails command itself, but that will require some more rejiggering.
Anyway, hope you find it useful.
Yes. Great post. Thank you for the info!
Steve Jorgensen,
You need use:
rails g cucumber:install —rspec —capybara
Thanks for this intro, but please update the cucumber version to 0.8.5. I also had issues with 0.7.3.
thanks!
I did what you say, but I commented out the gem versions, so I will get newest cucumber and rspec gems. Got 0.10.0 and 2.2.0, respectively
And I get this:
Any hint where should I look?
I get it too. Cucumber 0.10.0 rspec (2.4.0, 2.1.0, 1.3.1) rspec-rails (2.4.1, 2.1.0, 1.3.3) rspec-expectations (2.4.0, 2.1.0) Jruby 1.6.0 RC1 on Solaris
group :test, :cucumber do gem ‘cucumber-rails’ gem ‘spork’ gem ‘webrat’ gem ‘factory_girl’ end
I tried with fresh features/support/env.rb, and i tried adding this to features/support/paths.rb: World(NavigationHelpers) World(Rack::Test::Methods) World(Webrat::Methods) World(Webrat::Matchers)
Great post, too bad I didn’t start this at the beg. of the project. I have 5 failures and 30 pending to sort through now!
Thank you man! You really save my day !
Thank you man! You really save my day ! (2)
Hi all, im new in cucumber/watir and have any question: can you help me please ?
i don’t know how do for example use the sentences cucumber into ruby class.
I knew for java have so:
import cucumber.annotation.en.Given;
public class SomeOtherStepsdef {
for ruby what is the gem ?
Yesterday was brutal for me. I was lucky I only had one class to teach after I threw up the first time. I had to take 10 mitunes from my class to run to the staff bathroom and have the rest of my lunch violently force its way up. My body had drained all its fluids 40 mitunes later, so I was basically choking on this thick sludge as it made its way up my throat.[descriptive enough for ya? haha]I was weak today, but my stomach hasn’t given me any troubles. Luckily I have good co-teachers and some compassionate students, otherwise yesterday would've been a nightmare!Glad to hear all your things are being sorted out. It can be a nerve-wracking process trying to seal the deal on these things when you have to leave the country so soon!
8iSvHb <a href="http://jfgqjabqeuhq.com/">jfgqjabqeuhq</a>
En8SAo <a href="http://oxvayiqjvngz.com/">oxvayiqjvngz</a>