Skip to content

Instantly share code, notes, and snippets.

@ramontayag
Created June 24, 2011 16:21
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ramontayag/1045123 to your computer and use it in GitHub Desktop.
Save ramontayag/1045123 to your computer and use it in GitHub Desktop.
Rails 3.1: How to embed a dummy Rails app in a gem for Cucumber testing purposes

Intro

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 and my_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.

Setup

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.

Create a "plugin" using Rails 3.1

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

Create the skeleton of the 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

Show Cucumber where your Rails app is

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?

  1. Cucumber should run in the test environment. If this isn't there, it will run in the development environment and cause problems.
  2. 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?

  1. 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 the spec directory.
  2. ENV["RAILS_ROOT"] ||= File.dirname(__FILE__) + "../../../spec/dummy" sets a RAILS_ROOT environment variable that Cucumber uses to the path of the Rails app.
  3. require 'cucumber/rails' loads the cucumber/rails file which loads a bunch of other files. If you look through the Cucumber source, you'll see that Cucumber sets the ENV["RAILS_ROOT"] file to something else if it doesn't exist yet. But since we're setting it, it won't overwrite it.

Try it!

If you go to the root of your gem and run cucumber you should see that it runs and it doesn't complain.

Contribute

Making tutorials on a gist is cool because people can fork and, make changes, and I can merge them back in. If you want to add anything, fork off and let me know of any changes!

@gonzalo-bulnes
Copy link

Hello @ramontayag and @chrisgaunt, your two gists are demoing the same thing, thanks to both of you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment