Original - https://gist.github.com/ramontayag/1045123
Problem: I learned how to run RSpec to test classes and modules in my gem. But, if I wanted to test my gem as if it were already included in a Rails app, I couldn't find much info about it online.
I usually do unit tests with RSpec, and I test the whole stack with Cucumber. So here we will just setup Cucumber to run the Rails app that you embed in your gem.
Before we begin:
- This tutorial is for people who already know how to make gems, and who have used RSpec and Cucumber before in a Rails app.
MyGem
andmy_gem
below refer to the name of the gem we are creating. Replace this with your own name.- I use jeweler to create the gem, since I haven't mastered all the required stuff for creating gems. If you like using bundler or newgem to create your gems, then you still should be able to follow this tutorial easily.
Before we continue, let's install some required gems.
gem install jeweler rails-3.1.0.rc4
Why Rails 3.1? The new version of Rails has a plugin generator that creates the embedded dummy app we need. If you need to make a gem < Rails 3.1, then make changes to the config/boot.rb of a plain ol' generated Rails app to something similar to the one created by the Rails 3.1 plugin generator. You'll see below what I mean about the load paths.
rails plugin new my_gem
You'll see that in the test
directory of that plugin you created, there's a directory called dummy
. That's a Rails application with a few lines changed, so that it has a different load path [TODO: explain why]. I believe that only config/boot.rb
is different. However, I find it much easier to just generate this dummy app via the rails plugin new
command.
Let's move this dummy app to our current working directory.
mv my_gem/test/dummy .
We can now delete the plugin we made, since we don't need that plugin any longer:
rm -fr my_gem
Use the --cucumber
and --rspec
options to generate these with the spec
and features
directories mostly setup, along with the gems in the Gemfile
.
jeweler my_gem --cucumber --rspec
Cucumber knows what is where and how things should be setup in its own "environment file". It's called env.rb
and can be found in features/support/
.
Add the following to the start of features/support/env.rb
:
ENV["RAILS_ENV"] ||= "test"
require File.expand_path("../../../spec/dummy/config/environment.rb", __FILE__)
What did we just do?
- Cucumber should run in the test environment. If this isn't there, it will run in the development environment and cause problems.
- Load the environment file of the dummy Rails application, so that you can access the models and such of the dummy Rails app from Cucumber steps.
Add the following to the end of features/support/env.rb
:
require File.expand_path("../../../spec/dummy/config/environment.rb", __FILE__)
ENV["RAILS_ROOT"] ||= File.dirname(__FILE__) + "../../../spec/dummy"
require 'cucumber/rails'
What did we just do?
require File.expand_path("../../../spec/dummy/config/environment.rb", __FILE__)
where our Rails app is, since it's not where it usually is anymore -- it's all the way in thespec
directory.ENV["RAILS_ROOT"] ||= File.dirname(__FILE__) + "../../../spec/dummy"
sets aRAILS_ROOT
environment variable that Cucumber uses to the path of the Rails app.require 'cucumber/rails'
loads thecucumber/rails
file which loads a bunch of other files. If you look through the Cucumber source, you'll see that Cucumber sets theENV["RAILS_ROOT"]
file to something else if it doesn't exist yet. But since we're setting it, it won't overwrite it.
If you go to the root of your gem and run cucumber
you should see that it runs and it doesn't complain.