Spin speeds up your Rails testing workflow.
By preloading your Rails environment in one process and then using fork(2) for each test run you don't load the same code over and over and over... Spin works with an autotest(ish) workflow.
Spin is available as a rubygem.
gem i spin
Spin is a tool for Rails 3 apps. It is compatible with the following testing libraries:
- any version of test/unit or MiniTest
- RSpec 2.x
There are two components to Spin, a server and client. The server has to be running for anything interesting to happen. You can start the Spin server from your
Rails.root with the following command:
As soon as the server is running it will be ready to accept from clients. You can use the following command to specify a file for the server to load:
spin push test/unit/product_test.rb
Or push multiple files to be loaded at once:
spin push test/unit/product_test.rb test/unit/shop_test.rb test/unit/cart_test.rb
Or, when using RSpec, run the whole suite:
spin push spec
Running a single RSpec example by adding a line number is also possible, e.g:
spin push spec/models/user_spec.rb:14
If you experience issues with
test_helper.rb not being available you may need to add your test directory to the load path using the
spin serve -Itest
Send a SIGQUIT to spin serve (
Ctrl+\) if you want to re-run the last files that were ran via
spin push [files].
As mentioned, this tool works best with an autotest(ish) workflow. I haven't actually used with with
autotest itself, but it works great with kicker. Here's the suggested workflow for a Rails app:
Start up the spin server
kickerusing the custom binary option (and any other options you want)
kicker -r rails -b 'spin push'
Faster testing workflow!
A few months back I did an experiment. I opened up the source code to my local copy of the ActiveRecord gem. I added a line at the top of
active_record/base that incremented a counter in Redis each time it was evaluated. After about a week that counter was well above 2000!
How did I load the ActiveRecord gem over 2000 times in one week? Autotest. I was using it all day while developing. The Rails version that the app was tracking doesn't change very often, yet I had to load the same code over and over again.
Given that there's no way to compile Ruby code into a faster representation I immediately thought of fork(2). I just need a process to load up Rails and wait around until I need it. When I want to run the tests I just fork(2) that idle process and run the test. Then I only have to load Rails once at the start of my workflow, fork(2) takes care of sharing the code with each child process.
I threw together the first version of this project in about 20 minutes and noticed an immediate difference in the speed of my testing workflow. Did I mention that I work on a big app? It takes about 10 seconds(!) to load Rails and all of the gem dependencies. With a bit more hacking I was able to get the idle process to load both Rails and my application dependencies, so each test run just initializes the application and loads the files needed for the test run.
(10 seconds saved per test run) x (2000 test runs per week) = (lots of time saved!)
How is it different from Spork?
There's another project (spork) that aims to solve the same problem, but takes a different approach.
Your application needs to know about Spork, Spin works entirely outside of your application.
You'll need to add spork to your Gemfile and introduce your
test_helper.rbto spork. Spork needs to know details about your app's loading process.
Spin is designed so that your app never has to know about it. You can use Spin to run your tests while the rest of your team doesn't even know that Spin exists.
Spin should work out of the box with any Rails app. No custom configuration required.
It doesn't do any crazy monkey patching.
I take pull requests, and it's commit bit, and there are no tests.
If Spin isn't scratching your itch then one of these projects might: