I use rspec and factory_girl in my organization for writing unit tests. However, it used to be very very slow. I took some steps to speed it up.

Using build_stubbed instead of build or create for creating objects using factories as much as possible

Using build_stubbed builds factories and stubs all associations for the object. There were a lot of specs which could use the build_stubbed method instead of create or build for creation/building of objects from factories. This resulted in a non-requirement of a database connection and neccesity to create associated objects which sped up the tests by about 55-60%.  For more details you can refer to the link –  https://robots.thoughtbot.com/use-factory-girls-build-stubbed-for-a-faster-test

Using an in-memory database

Database was a considerable bottleneck for the performance of our tests. This is a common scenario which happens either due to a slow disk or due to a large number/complexity (or both) of queries being executed.

To solve this problem, I used the memory_test_fix  gem which uses the sqlite3 database adapter and uses your memory as the database. This sped up the tests by about 18-20%.

Github link – https://github.com/mvz/memory_test_fix

Running multiple tests at once

Tests run only in a single process and results in under utilizing the processor (which is usually dual or quad core). Running multiple processes to run tests in parallel resulted in a much shorter duration than running them sequentially.

I used the parallel_tests gem and ran tests with 4 processes. This resulted in reducing the duration  by approximately 2.5-3 times. (This should have ideally been 4 times but since I had a lot of applications running the performance obtained is less).

Github Link – https://github.com/grosser/parallel_tests

Results

I had a test suite containing 100 unit tests. build_stubbed was used for only 4 tests (I should have done this for atleast 40 and ran the tests). Making improvements one by one on the same suite reduced the overall execution time from 20 minutes to 6 minutes. Here’s a Before-After table containing execution times (rounded to the minute).

Improvement Done Before After
Using build_stubbed for 4 out of 100 tests 20 minutes 19 minutes
Using an in-memory database 19 minutes 16 minutes
Using parallel_tests gem with 4 processes 16 minutes 6 minutes