Every time you run a test in a Rails application, the whole environment is loaded, including libraries that don’t change between two consecutive runs. That can take a considerable amount of time. What if we could load the environment once, and only reload the changing parts before each run? Introducing RailsTestServing.
With RailsTestServing, the run time of a single test file has gone from 8 seconds down to .2 of a second on my computer. That’s a x40 speed improvement. Now, I don’t think twice before hitting ⌘R in TextMate. It feels liberating!
Features
Minimal reloading time: loads routes and
application.rbbefore the run, starts clearing them in the background afterwards.Transparency: test files can still be run from the console and TextMate.
Graceful fallback to normal operation when the test server is not started.
Unobtrusive: three lines at the top of
test/test_helper.rb.Test::Unitoptions: the full set is still handled.
Usage
Install
RailsTestServing:$ gem install Roman2K-rails-test-serving -v '>= 0.1.4' -s http://gems.github.comIn case you get an error saying the gem can’t be found, then:
$ curl -O http://roman.flucti.com/wp-content/uploads/2009/02/rails-test-serving-0.1.4.gem $ gem install rails-test-serving-0.1.4.gemInsert the following at the very top of
test/test_helper.rb:require 'rubygems' require 'rails_test_serving' RailsTestServing.bootFix TextMate and/or your Ruby load path, following this short guide.
Start the test server (one for each of your Rails applications):
$ ruby test/test_helper.rb --serveWait for the following message to be displayed:
** Test server started (#94574)Open a second console window and run your tests as usual:
$ ruby test/unit/account_test.rbOr in TextMate, open
test/unit/account_test.rband hit ⌘R. Once the test has finished running, you should see the following message in the first window:>> test/unit/account_test.rb (709 ms)If you run the test from TextMate, you may encounter the following error in the RubyMate window:
/Users/roman/usr/rubygems/gems/builder-2.1.2/lib/blankslate.rb:84:in `blank_slate_method_added': stack level too deep (SystemStackError) from /Users/roman/usr/rubygems/gems/builder-2.1.2/lib/blankslate.rb:84:in `blank_slate_method_added' from /Applications/TextMate.app/Contents/SharedSupport/Support/lib/builder.rb:86:in `method_added'This error is not related to
RailsTestServing. The fix is to insert the following line at the very top oftest/test_helper.rb(even beforerequire 'rubygems'):$:.reject! { |e| e.include? 'TextMate' }To stop the server, reopen the window you started the server from, and hit ^C.
As of v0.1.2, options are supported. As of v0.1.4, hotkeys have been added too. Please see the README for the lists and documentation on how to use them.
How it works
The server loads the environment and keeps it in memory to avoid having to reload it with every run.
When you run a test from the root of a Rails application, and if the corresponding test server is started, the process spawned acts as a client:
- this client process hands its arguments over to the server. In turn, the server:
- loads the routes and
application.rb, - runs the test by processing the arguments,
- returns its output to the client,
- starts clearing every constant defined since step 2, in the background,
- the client prints out the output.
That way, the client-server interaction is totally transparent to the user, either TextMate or yourself from the console.
Status
Has worked like a charm for me for over a month.
Only supports
Test::Unit. RSpec already has something, thespec_servercommand.Has only been tested with Rails from 2.1.2 up to 2.0.2 RC2. It is compatible with those as of v0.1.1 and is not guaranteed to work with a version of Rails out of that range.
I would like to add (or see added) support for Autotest in the future, although I am almost certain it would require patching Autotest to modify the list of arguments passed to the Ruby interpreter. The same goes for tests run from Rake tasks.
Source code
RailsTestServing repository on GitHub.
Article updates
UPDATED 2008-11-17: This article now reflects compatibility fixes applied to v0.1.1. This version fixes load path issues and incompatibility with Rails lower than 2.2.0. Thanks Justin Ko for reporting these!
UPDATED 2008-11-18: There were still issues with the load path and TextMate. Step 3 has been updated to link to the fix.
UPDATED 2008-11-18 #2: Version 0.1.2 has been released after Justin Ko had figured out the key to making it work on his machine, which hopefully is the same for more people. The article over there has been updated according to the discovery: see the link at step 3.
UPDATED 2008-11-19: v0.1.2 turned out not to be as flawless as expected. The next version is in the works with encouraging results. If you get weird assertion failures from the second run onwards, you ought to try the development version:
$ git clone git://github.com/Roman2K/rails-test-serving.git
$ cd rails-test-serving && rake clean gem && gem install pkg/rails-test-serving-*.gem
UPDATED 2008-11-21: v0.1.3 released. This article has been updated accordingly.
UPDATED 2009-02-08: v0.1.4 released. This article has been updated accordingly.

Add New Comment
Viewing 37 Comments
Thanks. Your comment is awaiting approval by a moderator.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Add New Comment