Making RSpec, Rake, and Bundler play well together

Posted by: Rick DeNatale on 06/25/2010

I'm working a project which uses RSpec, Bundler, and Rails 2.3.4.

The team has been struggling with the changes in gem management with Bundler. The "Old School" rails way to configure gems for different rails environments is to conditionally execute gem.configure based on the rails environment. Then use the rake:gems:install task to gem install the gems, one for each environment.

Bundler does things a bit differently. It uses groups to segregate gems by environment, so you name the gems needed for the test environment in a :test group. When you run bundle install, it installs all of the gems for all of the groups (unless you opt out of some groups. It uses the groups at run time, to selectively expose only gems applicable to the current environment.

This cause problems for things like the spec rake task. If you run

rake spec

without explicitly setting the Rails environment.

The way the spec rake task works is that it depends on a rails provided rake task called :environment, which 'boots' the rails environment, then the spec_helper file which each spec whould require, sets ENV['RAILS_ENV'] to 'test' if it's not already set, then it requires needed gem code, like 'spec/rails'.

In the old school approach this works, since those gems are installed and visible. With bundler, it fails since they won't be exposed, since the bundler environment got set up using the development environment, so gems in the :test group aren't available.

In an attempt to fix this, other members on the team were mixing things up, doing things like putting conditional tests of the rails environment in the Gemfile, and then running the bundle command with different overrides of the RAILS_ENV environment variable.

But that way lies madness.

This morning I worked out a solution which involves deferring setting up the bundle environment.

  1. I needed to keep the spec task from running the environment task. The project was already using a variation of override_rake_task, so I added an override in a task within the lib directory:
          override_task :spec do
            Rake::Task["spec:original"].execute
          end
        
  2. The next step was to bootstrap the rails environment in spec_helper. To do this I started it with:
          ENV["RAILS_ENV"] ||= 'test'
    
          RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
          environment_path = File.expand_path(File.join(RAILS_ROOT, 'config', 'environment'))
          require(environment_path)
            require 'spec/rails'
            #... any other needed requires
        

    It's crucial to expand the path which ensures that the same string is used whenever the environment file is required. Before I did that I was having problems with the environment being required a second time, presumably for the second spec. If you have any code which patches anything using alias_method_chain, or a similar technique, loading that code a second time can cause infinite loops which can be mystifying.

So this seems to be working. I'll try to update if I find anything else, but in the meantime I hope some folks find it useful.


Original article writen by Rick DeNatale and published on Talk Like A Duck | direct link to this article | If you are reading this article elsewhere than Talk Like A Duck, it has been illegally reproduced and without proper authorization.


About Rick DeNatale

Rick  DeNatale

I am a long-time object oriented technologies, practitioner, evangelist, and provocateur. I've been a Ruby programmer and consultant since 2006.

Some highlights from my 32 year career at IBM include: the development of the initial proof of concept for IBM VisualAge/Smalltalk, a distributed implementation of the Smalltalk

language, work on VisualAge Micro Edition for Java (the precursor to Eclipse), serving as a founding member and secretary of

the X3J20 Smalltalk committee, and appearances in the

early decades of OOPSLA.

I've had the opportunity to know, work, and interact with many of those who laid the groundwork for what we do with Ruby and how we do it.

My sporadic thoughts, mostly about the Ruby language and related topics can be found at my blog. http://talklikeaduck.denhaven2.com

More About Rick »

NFJS, the Magazine

December Issue Now Available
  • BDD and REST

    by Brian Sletten
  • Mocks and Stubs in Groovy Tests

    by Kenneth Kousen
  • Algorithms for Better Text Search Results

    by John Griffin
  • Knowns and Unknowns of Scrum and Agile

    by Brian Tarbox
Learn More »