views:

844

answers:

1

I'm creating some gems that can be used within Rails controllers and views. I'd like to be able to test the gems independently. But I've not been able to figure out how to create an instance of Rails inside the gem to test that the gem will work inside a Rails app.

I strongly prefer to use RSpec, but could probably adapt a Test::Unit solution, or just use Test::Unit.

I'd also be interested in similar solutions for Rails plugins.

(I tried Googling, but "rails gem testing" shows me gems that are used for testing, not how to test a gem. I'm pretty sure I've seen an article or 2 on this topic.)

+3  A: 

Take a look at others plugins (plugins and gems, same thing) test suites.

Testing plugins that enhances Active Record is pretty easy. You can use Active Record anywhere, so all you got to do in that case is to connect Active Record to a database (e.g. a in-memory sqlite database) and test your codez.

# test/test_helper.rb
$LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
require 'your_thing'

ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :dbfile => ":memory:")

ActiveRecord::Schema.define(:version => 1) do
  create_table :posts do |t|
    t.string :title
    t.text :excerpt, :body
  end
end

class Post < ActiveRecord::Base
  validates_presence_of :title
end

# test/my_test.rb
require 'test_helper'

class MyTest < Test::Unit::TestCase
  def test_thing
    # use Post here
  end
end

It gets harder when you want to test controller actions and such. My live validations plugin has a pretty extensive test suite that mocks out lots of things and lets me pass ERb views as a string, you could take a look at that.

Adapting these Test::Unit examples to RSpec should be trivial, as they do not piggyback on anything in Test::Unit.

August Lilleaas
This was very helpful; thanks! Is there a way to keep ActiveRecord loaded (ala spec_server or spork) so that loading ActiveRecord and creating the database every time doesn't slow my tests down so much?
Chinasaur
I'm sure there is a way to do that. If you use sqlite3 file storage, instead of memory storage like my live validations plugin uses, you can check if the .sqlite3 database file exists and not run the migrations if it does etc.
August Lilleaas