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?