Jan 22 2009

Unit testing your Ruby on Rails plugin

Category: Rails, Rubysiebert @ 12:51 pm

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.rb file 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
end

As 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.yml file.

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:

Popularity: 16% [?]

Share and Enjoy:
  • Digg
  • del.icio.us
  • Slashdot
  • Technorati

2 Responses to “Unit testing your Ruby on Rails plugin”

  1. chris says:

    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.

  2. James Smith says:

    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

Leave a Reply