Rails Testing

I have often been told and red not to test the database. To avoid useless round trips and that my tests should be testing the code, not the database. That is the key to fast testing. But how fast exactly does this change? I took it upon myself to figure it out. I wanted to know the affects of slow vs fast testing and measure it.

Slow tests often come from round trip to the database. I decided to measure the performance impact using a gem I generally use for testing: FactoryGirl

I used my template to create a new blank rails project (You can find the template I use here) with the necessary gems to test this the way I usually test my applications (RSpec & FactoryGirl).

Once installed, create a model to put under test:

rails generate model Person name

I created a quick test that actually does not do anything except instantiating (and / or) creating the object in the database.

My tests looked like this

# spec/models/person_spec.rb

require 'rails_helper'
require 'benchmark'

describe Person, type: :model do
  it 'works' do
    n = 50_000
    Benchmark.bm do |x|
      %i(build build_stubbed create).each do |method|
        x.report(method) { n.times { send(method, :person) } }
      end
    end
  end
end

Running this test with

bundle exec rspec spec/models/person_spec.rb

will highlight some of the key differences.

The report on my machine (though your based on the time, the processes running and the machine it’s run on may alter the times) looked as following:

  user system total real
build 6.970000 0.130000 7.100000 ( 7.140500)
build_stubbed 11.500000 0.220000 11.720000 ( 11.779517)
create 55.800000 5.580000 61.380000 ( 70.141748)

This show nearly a tenfold slower.

Conclusion

This highlights the importance of well written tests. There are many of blogposts out there to illustrate how to write your tests in an understandable manner. While this blogpost does not reflect what is right / wrong with running tests against a database it does show with a measurable quantity the impact of writing / reading to the database