How to test a gem that changes ActiveRecord

The code given here comes from my gem, safe_attributes, which can be retrieved from https://github.com/bjones/safe_attributes. Some of the code for setting up this testing environment originally came from or was inspired by octopus, which is also available on github.

The strategy for testing my gem is to test the code against ActiveRecord outside of a Rails environment. A simple google search shows that this is one way in which people use ActiveRecord and it definitely seems like it would be easier to setup. I’ll explore testing a gem that operates with ActionController in a future post.

The following example is for rspec, and is taken as an example of testing a gem that modifies some part of ActiveRecord behavior. This is the content of spec_helper.rb.

$LOAD_PATH.unshift(File.dirname(__FILE__))
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))

This code is just ensuring the spec directory and the gem’s lib directory are part of the load path.

require 'rubygems'
gem 'activerecord', '>= 3.0.0'
require 'active_record'
gem 'activesupport', '>= 3.0.0'
require 'active_support'

This should probably be done with bundler, especially given that I’m using bundler already elsewhere. The point here is activerecord is loaded.

require 'safe_attributes'

Require in the gem’s code.

require 'rspec'
require 'rspec/autorun'

Rspec stuff, you need at least the first one here.

root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
ActiveRecord::Base.establish_connection(
:adapter => "sqlite3",
:database => "#{root}/db/safeattributes.db"
)

This establishes a connection to a simple sqlite database for testing. There happen to be tasks to setup this test database in the gem’s Rakefile.

RSpec.configure do |config|
end

Finally, configure rspec with defaults.

Here’s a look at the most interesting parts of the safe_attributes_spec.rb, which tests the gem.

require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')

ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS 'my_models'")
ActiveRecord::Base.connection.create_table(:my_models) do |t|
    t.string :class
    t.string :bad_attribute
    t.string :good_attribute
end

class MyModel < ActiveRecord::Base
    include SafeAttributes
    bad_attribute_names :bad_attribute, :bad_attribute=
end

describe MyModel do

    before(:each) do
        ActiveRecord::Base.connection.increment_open_transactions
        ActiveRecord::Base.connection.begin_db_transaction
        @model = MyModel.new
    end

    after(:each) do
        ActiveRecord::Base.connection.rollback_db_transaction
        ActiveRecord::Base.connection.decrement_open_transactions
    end

The before/after hooks are used to start a transaction and roll it back after each test case finishes. The table and model are created within the spec itself rather than outside of it, but either way would work.

Thanks to octopus for the inspiration and I hope this helps someone else.

Advertisements
This entry was posted in rails and tagged , , . Bookmark the permalink.

2 Responses to How to test a gem that changes ActiveRecord

  1. Matt Huggins says:

    I see you reference db/safeattributes.db, but I don’t see that file anywhere in your codebase. How do you go about creating that file? Do you have to do it manually before the tests can run, and if so, what’s the process?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s