Use Spin for Faster Test Iterations


Do you ever re-run the same Rails test file over & over while working on a feature and trying to “make it green?” Change the code, run the test, change the code, run the test, etc. (I’m talking about when you want to re-run a specific test, not using guard to autodetect which tests to run.)

When you do that you have to wait a long time for the Rails environment and your app’s initializers to load. You pay this price every time you re-run the test—even if you’re not changing your initializers. I get ants in my pants sitting around waiting for the environment to load.

I just learned about a new gem that doesn’t require any changes to your tests and that speeds up this test-code-test-code cycle by only loading your environment once: it’s called spin.

Basically you do this:

  • In one terminal window type spin serve. This launches the spin server, which waits for commands over a socket.
  • In another terminal, when you want to run the tests in a single file, type spin push path/to/testfile.rb
  • You can push multiple filenames at once if you like.
  • One limitation: it does not let you use the :linenum syntax that rspec uses to run just one test in a file.

That’s it. I tried it on a test file that takes 8 seconds (after everything has been loaded). Total time to load and run this file went down from 26 seconds to 13 seconds when I used spin.

I looked at the source. It’s short and simple. Here’s how it works:

  • spin serve preloads your app’s config/application.rb.
  • Then it waits for commands on a socket.
  • When a command comes in it forks a new process and runs tests in the fork. The fork doesn’t have to reload the Rails environment or initializers because they’re already loaded.
  • When done, the fork just exits and spin is ready for a new command.

Remember that if you do change your initializers or anything else that is loaded by application.rb you should restart the spin server. Another time you may want to restart it: after checking out a different branch in git.

Safe and easy. Faster tests. What could be better?

6 thoughts on “Use Spin for Faster Test Iterations”

  1. I think TestR is better (note: I’m biased because I’m one of its authors) because it combines the best of spin + guard + autotest into a small (less than 380 lines of code), unobtrusive (no changes to your source code or test suite needed), and single package (simply gem install and run!).

    1. Thanks for the link, sunaku. TestR looks interesting. One question I have after reading the Readme: I didn’t see an example showing how to invoke a test file on demand. The use case I’m thinking of is the one I described in this blog post: you keep wanting to re-run a single file on demand instead of automatically via a watcher.

      Does TestR support this?

      (I am also a fan of automatically running tests with a watcher such as guard, but when the test suite is big and slow I fall back to on-demand testing.)

      1. Absolutely, you can re-run any test file by simply saving it! When you do, TestR tries to figure out which tests inside your newly saved test file have changed (using diff and some simple regexps) and then attempts to run just those. To override this behavior and have it run all tests in your saved file, simply save the test file *again* (this is the 2nd save so far).

        The testr(1) bin script provides a simple command-line UI that lets you (among other things) re-run all currently failing tests, all currently passing tests, or just everything. So that’s taken care of too. 🙂

    2. Thanks…but that wasn’t what I meant by “on demand.” What if I’m changing the application–not the test? And I want to run only that one test (or file), not any of the other tests & files that might be run when I change the app.

      And I still don’t want to pay the price of waiting for the Rails environment to load.

      Sometimes heuristics are great. But there are other times you just want to tell the computer what to do.

      1. I see. By default, TestR does not come with Rails heuristics enabled; you have to manually require it in your configuration file. Instead, it has [basic Ruby heursitics]( built in. So you could perform your semi-automatic testing that way; or if that’s too much, you could:

        * Redefine its entire configuration (OpenStruct object) and fill in what you want.

        * Open up another terminal, run `testr-master` and tell it (see its man page for details: `testr-master –help`) exactly which files to run. This is very similar to spin, but it operates on STDIN rather than a UNIX socket.

Leave a Reply

Your email address will not be published. Required fields are marked *

Feel free to use <a>, <b>, <i>, <strong>, <em>, <strike>, <code>.

Code blocks:
[code language="ruby/javascript/html/css/sass/bash"]