I've seen a few examples of dummy Rails apps (for testing, so they live under test or spec dirs, typically) for use with the Appraisals gem that supposedly work with both Rails 3.x and Rails 4, but they seem hackish and not fully functional. It is somewhat expected, as it is a stripped down Frankenstein monster that is trying to be compatible with various versions of Rails 3 as well as Rails 4.
I've referred to projects that attempt to do this sort of testing (as of late March 2013) like less-rails and ember-rails, but this way to test with various version of Rails doesn't seem very clean, and it is non-trivial to try to debug a non-standard Rails application, especially in a beta version of Rails.
It would be great to have a cleaner way to test that allows you to have a full Rails application for each version of Rails to test with that through some magic is not that difficult to setup or maintain and don't require non-standard path hacks in places, etc.
What are the available strategies for testing gems with various versions of Rails (including at least latest Rails 3.1.x, 3.2.x, and 4.0.0.beta1), and what are the pros and cons of each?
There's a third option : using multiple gemfiles and multiple dummy apps.
Gemfiles
Bundler has an useful option named
--gemfile
. With it, you can specify what file to use instead ofGemfile
, and it will generate a lock file after the same name :This will generate Gemfile.rails3.lock and Gemfile.rails4.lock. So, those Gemfiles can be a copy of your main Gemfile forcing rails version :
Using gemfiles from dummy apps
Then you have two dummy apps, one for rails-3 and one for rails-4. To use their proper gemfile while running (for example) migrations :
Yeah, that's probably the worst part. But this is mostly a one time setup.
Using gemfiles from rake
To instruct which version to use while running tests, set the environment variable BUNDLE_GEMFILE in Rakefile :
I prefer to ask the user to pass RAILS_VERSION instead of directly BUNDLE_GEMFILE because it's easier to remember and we can just pass "3" or "4".
Using correct dummy app from tests
Finally, in test_helper, switch the dummy app depending on what rails version has been asked for :
From your user perspective
For your user to run tests, he will have to do a one time setup by running the migration tasks with BUNDLE_GEMFILE, which is not that sexy.
But once done, user can run tests against rails-3 and rails-4 without the need to generate the Gemfile each time he wants to switch version, and you can have version specific code and configuration within your test apps without having to put
if Rails.version >= '4'
statements everywhere.To run specs :
You can see an example for this method in my activerecord_any_of gem.
A few options from the related thread on the rails-core list:
Option 1: Appraisal gem and single Rails dummy app
Ken Collins mentioned using appraisal and a Rails "dummy" app:
Similar techniques are used in less-rails, ember-rails, and high_voltage among others.
I used a similar setup to high_voltage in restful_json (v3.3.0) but with a full Rails app created with 4.0.0-beta1 that I modified minimally to also work with Rails 3.1.x/3.2.x.
Update: May want to see permitters for more recent example.
Pros: Fairly simple. Can test against various Rails versions from command-line, etc. Can be very minimal Rails app configuration, or can use full Rails app with minor differences.
Cons: Still reusing same Rails app for multiple Rails versions, so some conditionals and unneeded config. (Possible issues with some files not being applicable in another version of Rails, etc. but does not appear to be a big problem.)
Option 2: Rails version as environment variable with single Gemfile, single Rails dummy app, relying on travis-ci to test in multiple versions
Steve Klabnik mentioned a solution that works with a single Gemfile, a single full Rails app (even though under "dummy" dir, and no use of the appraisal gem, by relying on travis-ci to test:
Pros: Simple. No dependency on appraisal gem (not that it is a problem, but may be easier to maintain).
Cons: Still reusing same Rails app for multiple Rails versions from what I can tell. Unless using travis-ci or something that starts with a clean gemset (i.e. if running at command-line), not currently differentiating gemsets so newer gem may be used with older Rails, etc., but Steve said if that were to cause a problem, you could just blow away the lock and re-bundle.