I’ve been working on a number of gems that are basically packaged Ruby on Rails engine plugins. It turns out that turning gems into plugins is pretty easy to do. However, testing them can be a pain. Here are a few things I came up with.
After looking at how Clearance handles tests I’ve decided that it’s ok to embed a basic Rails application in your test directory.
The next trick is getting the gem you are working on to load in your embedded Rails application. The Clearance guys added a file in config/initializers that looks like this:
# This simulates loading the clearance gem, but without relying on # vendor/gems clearance_path = File.join(File.dirname(__FILE__), *%w(.. .. .. ..)) clearance_lib_path = File.join(clearance_path, "lib") $LOAD_PATH.unshift(clearance_lib_path) load File.join(clearance_path, 'rails', 'init.rb') </pre>
I thought that was brilliant but it didn't work for me. After messing around in the Rails code for a bit I found a bit of helpful documentation on 'plugin_locators': The classes that handle finding the desired plugins that you‘d like to load for your application. By default it is the Rails::Plugin::FileSystemLocator which finds plugins to load in vendor/plugins. You can hook into gem location by subclassing Rails::Plugin::Locator and adding it onto the list of plugin_locators. That sounded like the perfect solution to my problem. I figured I would simply add a plugin locator that pointed to the root of the gem I was building. Turns out that works great. In the embedded rails application inside of config/environment.rb I added this code:class TestGemLocator < Rails::Plugin::Locator def plugins Rails::Plugin.new(File.join(File.dirname(__FILE__), *%w(.. .. ..))) end end Rails::Initializer.run do |config| config.time_zone = 'UTC' config.plugin_locators << TestGemLocator end </pre>
Now my tests load correctly and all is well. Context is important. If you want to have a look at the full project I put it into a gem called disguise which you can get from github.