Everyone wants their tests to run faster. I want my tests to run faster. That’s why I’ve been using parallel when I need to run my whole test suite (or at least a large part of it, e.g., unit tests). And VCR makes it really easy to record HTTP interactions to play back later, which means your tests will run faster and will pass even when you’re not online.
A lot of the time I just want to run a single test file (or single test method)—and this, for me, takes an annoyingly long time. If you have a lot of fixtures like I do, then you may want to read on. Let’s start with the test benchmarks.
1 2 3 4 5 6 7 8 |
|
Fifteen whole seconds to wait for a simple set of unit tests to run! and most of that time is spent just preparing to run the tests. My first step was to use spork, which speeds up testing by preloading the Rails env and forking when you want to run your tests.
1 2 3 4 5 6 7 8 |
|
Quite an improvement! Spork shaved off about 6s from the total time to run the test just by preloading the Rails env.
But 9s is still along time to run a few simple tests. Digging through test.log I realized an absurd amount of time was being spent loading in fixtures.* The worst part is that there is really no need to reload the fixtures into the DB once they are in there as long as you are using transactional fixtures—I only need Rails to know which fixtures are present so I can easily access the AR objects I need by the names they have in the fixtures. This part doesn’t take long at all. Most of the time loading in fixtures is spent putting them in the DB.
After some digging through ActiveSupport::TestCase and finding my way into ActiveRecord::Fixtures, I realized that if I could stub out the database adapter methods that are used to load in the fixtures then I could get the benefit of having Rails know which fixtures exist without actually spending the time to reload them into the database. Here’s how I modified my test/test_helper.rb to achieve this using mocha (only relevant code shown):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
Now when I run my test with the DB methods stubbed out:
1 2 3 4 5 6 7 8 |
|
And with spork (must start the spork server w/ SF=true):
1 2 3 4 5 6 7 8 |
|
So by using spork and skipping loading fixtures every time I was able to go from 15s to ~3.5s. I can live with that. I can be productive with that.
* This app was started a long, long time ago and migrating to factories would be way too painful.