Jan 22 2009
Unit testing your Ruby on Rails plugin
So you want to write some tests for your hot new Rails plugin that extends the behaviour of a ActiveRecord model? The thing is – for it to be decent tests it needs to be functional outside of the context of you Rails application, so you need to create a temporary testing environment. I think there is a few ways to this but the following is what I did.
In the plugin test folder I created a lib and a fixtures folder. In the lib folder I created two files activerecord_connector.rb and activerecord_test.rb.
acticerecord_connector.rb:
require "rubygems" require "active_record" require 'active_record/fixtures' conf = YAML::load(File.open(File.dirname(__FILE__) + '/../database.yml')) ActiveRecord::Base.establish_connection(conf['sqlite3'])
This file is required to make a connection to the database that is configured by database.yml that I placed in the test folder.
database.yml:
sqlite3: database: ":memory:" adapter: sqlite3 timeout: 500
This specifies a connection to a Sqlite database that is to be kept in memory. It means the database is just alive for the duration of our test – perfect.
activerecord_test.rb
require 'test/lib/activerecord_connector' require 'test/fixtures/schema.rb' class ActiverecordTest < Test::Unit::TestCase FIXTURES_PTH = File.join(File.dirname(__FILE__), '/../fixtures') dep = defined?(ActiveSupport::Dependencies) ? ActiveSupport::Dependencies : ::Dependencies dep.load_paths.unshift FIXTURES_PTH end
The code in this file does the following:
- It requires
activerecord_connector. - Requires a
schema.rbfile for populating the database. - Defines the ActiverecordTest class that define and store the path to your fixtures folder.
schema.rb:
ActiveRecord::Schema.define do
create_table "users", :force => true do |t|
t.string "first_name"
t.string "last_name"
t.integer "id"
end
endAs you can see, this creates the users table in the database.
I created a User model that is stored in the fixtures folder.
user.rb
class User < ActiveRecord::Base #this class might be extended by your plugin end
Also in the fixtures folder is a users.yml file to serve as test content in our database.
users.yml
david: id: 1 first_name: Thomas last_name: Black jamis: id: 2 first_name: Peter last_name: Martin
Lastly we have our test file.
hot_plugin_test.rb
require 'test/unit'
require 'test/lib/activerecord_test'
class HotPluginTest < ActiverecordTest
def setup
Fixtures.create_fixtures(FIXTURES_PTH, 'users')
end
def test_users
user = User.find(:first)
assert_equal "Thomas", user.login, "not working!!"
end
end- HotPluginTest inherits from ActiveRecordTest.
- The setup method creates the content in our database from the
users.ymlfile.
Now you can extend models that you place in the fixtures folder with your plugin and run tests against them in HotPluginTest.
As I said at the start, this is just a method of doing it – you might have some other ideas. I’ll be happy to hear about them. For another approach you might want to look at Plugin Test Helper.
Happy testing!
My credit to the following posts and plugin for leading to this solution:
- Rails Plugin Testing Guide
- Using ActiveRecord outside Rails
- will_paginate plugin that has a great test example
Popularity: 16% [?]

April 17th, 2009 at 2:43 pm
Hi,
Great writeup. I was wondering if you knew how to get something like ‘fixtures :all’ or ‘fixtures :users’ at the top of the test class to work or in a test do something like ‘chris = users(:chris)’. I realize that create_fixtures works just fine, but I’ve been dying to know how to get those last two pieces to work.
June 4th, 2009 at 9:22 pm
Hello!
Great article! I ran into an issue following these instructions that I thought I would share. Since you have a file named ‘activerecord_test.rb’ RakeTestLoader was throwing an exception about the file not containing a default test. If you rename ‘activerecord_test.rb’ to ‘activerecord_test_helper.rb’ then it doesn’t expect it to contain any tests and it works perfectly.
Thanks!
James