BACKTRACE

(condense)

Back to Posts List

GET

Ninja testing your Rails plugins

Testing plugins is much like testing your rails application, it uses the same rake and directory structure conventions which makes it a lot easier for who ever is already testing his Rails applications (you don’t? go away!).

Getting started will require you’ll have basic/advanced knowledge of the Rails conventions, testing methods and tools:

  • Test::Unit
  • Rail’s database schema management
  • rake

I’ll try to cover as much as possible but i assume that if you have any issues with one of the following, you should probably go ahead and read up the Rails testing guide and maybe some of the other guides around while you are at it.

Testing standalone plugins

Testing plugins as part of a Rails application is pretty straight forward, you simply call:

rake test:plugins
or ,if you wish to run a specific plugin:
rake test:plugins PLUGIN=name

Yeah, that easy.

That worked out for actually for a while, but i came to the conclusion that i shouldn’t force people to embed my plugin into their applications even before they were able to test it and see that it’s actually working.
Another reason is that forcing people to include the plugin in an application, is making the process of contributing to it (assuming it’s open sourced, and it should be :) ) a bit more annoying.
Encapsulating the entire plugin test suit into the actual plugin tree and removing all non-required dependencies, gives your plugin a more generic and independent form.

General directory layout

Like i noted before, the Rails plugin’s test directory is very similar to Rails’s own test directory structure:

test/
fixtures/
lib/
functionals/
db/
unit/
Rakefile
test_helper.rb

You don’t actually have to have all of those in your plugin test directory, depends on what you are actually testing, you might want to remove folders that are not related to your plugin’s functionality, for example ActiveRecord plugins will not need the functionals/ directory on most cases, but will probably need some application structure stubs (i’ll get to that in the next section).

Testing ActiveRecord plugins

If your plugin has some functionality that extends ActiveRecord, or that relays on some ActiveRecord related built in functionality (associations for example) you’ll need to require the activerecord gem in your test_helper.rb:

require ‘active_record’

Creating a standalone database

Next, you’ll need a database. since you are not running as part of a Rails application test suit, you can’t use the default test database that ships with the Rails default test environment, you’ll have to create one.
Since the goal we are after here, is to create somewhat a standalone plugin testing suit, the best way to get a standalone database is to create an in-memory sqlite3 database, which is also easy to configure:

Loading the schema

The plugin’s schema file is the file that hold all the database tables DDL that you will need in order to test your plugin. The syntax is just like the one Rails uses in its own db/schema.rb. To keep the conventions gods happy, i suggest creating a db/ directory in your plugin root and create schema.rb there, here’s an example just in case:

After the schema is ready, we’ll need to load it by adding this line to test_helper.rb:

load ‘test/db/schema.rb’
(we include test/ in the path because we will be running rake from the plugin’s root directory).

Fixtures

Since we want a standalone testing suit, we will have to settle for fixtures as our database population tool and not on an external gem. create your *.yml fixtures under the fixtures/ directory, then just require 'active_record/fixtures' in your test_helper.rb:

Models

Since we require the activerecord gem, you can create ActiveRecord models. Personally i create a directory named app/ under the plugin’s root directory and mock a real application directory. (e.g creating models/, views/, controllers/ and whatever).

After you are done creating your model you’ll need to load them in your test_helper.rb:

Dir[‘test/db/app/models/**/*.rb’].each { |f| require f }
should do it.

note that you can use the same to require controller files, just change the path to include the controllers/ subdirectory as well.

Testing ActionPack plugins

Controllers

Testing a controller extension is somewhat easier than testing ActiveRecord extentions, all you basically need to do is to require:

require ‘action_controller’
require ‘action_controller/test_process’

create routes.rb under app/config, add routes to match your controller and load it in test_helper.rb. Of course you’ll have to create the controller class under app/controllers/ and the test files under functionals/.
Your actual tests should look like regular rails functional tests.

Helpers

The straight forward approach is to include the helper’s class in the matching unit test, and test every helper method. Sometimes some helpers might expect ActiveRecord to be around as well, i suggest mocking (Using Ruby’s included OpenStuct) to avoid the mess.

Testing Rake Tasks

Some plugins offer rake tasks as part of their functionality, in order to test rake tasks you’ll need to require rake:

require ‘rake’

and quickly setup a rake object on test_helper.rb:
@rake = Rake::Application.new

load your tasks like you did with the schema.rb file and invoke tasks in your tests simply by:

@rake[“db:migrate”].invoke

Your Rakefile

Assuming you generated your plugin with the Rails script/generate plugin command, you should have a file name Rakefile in your plugin’s root directory that looks kind of like that:
http://gist.github.com/232531

note that it loads several libs (lines 10-11), replicated these rows to include any library that you wish to include in the search path. In this file i included the lib/ directory so i won’t have to require my files with a complete path, but by simply specifying their names (require 'my_plugin' instead of require 'lib/my_plugin').

oh yeah, your actual plugin code

Well, if your plugin is well structured, you’ll have a .rb file under lib/ named like your plugin, and if other files are required as well, that file will be responsible to require them.
With that being said, the only thing that you’ll need to do is to actually include that file on test_helper.rb:

require ‘lib/my_plugin’
will require lib/my_plugin.rb. on the last note, you’ll have to include test/unit as well:
require ‘test/unit’

and you are all set. your plugin is available for standalone testing.

POST

blog comments powered by Disqus

I Don't have cookies.

ELAD ENV

Variable Value
LINKEDIN
TWITTER
FACEBOOK
GITHUB
WWR
IRC
{ 'irc.freenode.net' => [ '#rubyonrails', '#railsbridge', '#ruby', '#mootools' ]}
SKYPE
eladmeidar

You're seeing this error because I think it is funny.