Eliot Sykes

Faster RSpec: Profiling FactoryGirl

One way to speed up a slow test suite is to optimize how FactoryGirl is used, but where do you focus your efforts?

Before tuning your factory usage, consider measuring which factories are adding the most time to your test runs. You may discover the time spent in factories is fine and decide to speed up another area of your suite.

Introduce FactoryGirlProfiler below to an RSpec project. It will only report when the --profile/-p flag is passed to the rspec command:

# File: spec/support/factory_girl_profiler.rb
# Ensure this file is required by spec_helper.rb or rails_helper.rb
class FactoryGirlProfiler

  attr_accessor :results

  def self.setup
    profiler = self.new

    RSpec.configure do |config|
      config.before(:suite) { profiler.subscribe }
      config.after(:suite) { profiler.dump }

  def initialize
    self.results = {}

  def subscribe
    ActiveSupport::Notifications.subscribe("factory_girl.run_factory") do |name, start, finish, id, payload|
      factory, strategy = payload.values_at(:name, :strategy)

      factory_result = results[factory] ||= {}
      strategy_result = factory_result[strategy] ||= { duration_in_secs: 0.0, count: 0 }

      duration_in_secs = finish - start
      strategy_result[:duration_in_secs] += duration_in_secs
      strategy_result[:count] += 1

  def dump
    puts "\nFactoryGirl Profiles"
    total_in_secs = 0.0
    results.each do |factory_name, factory_profile|
      puts "\n  #{factory_name}"
      factory_profile.each do |strategy, profile|
        puts "    #{strategy} called #{profile[:count]} times took #{profile[:duration_in_secs].round(2)} seconds total"
        total_in_secs += profile[:duration_in_secs]
    puts "\n Total FactoryGirl time #{total_in_secs.round(2)} seconds"


RSpec.configure do |config|
  config.add_setting :profile_factories, default: false
  config.profile_factories = config.profile_examples? || ARGV.include?('--profile') || ARGV.include?('-p')
  FactoryGirlProfiler.setup if config.profile_factories?

Source: https://github.com/eliotsykes/rails-testing-toolbox/blob/master/factory_girl_profiler.rb

Now run rspec --profile and review the output to find results formatted like below:

FactoryGirl Profiles

    create called 4 times took 0.18 seconds total

    build called 7 times took 0.07 seconds total
    create called 17 times took 0.22 seconds total

    build called 12 times took 0.06 seconds total
    build_stubbed called 2 times took 0.01 seconds total
    create called 28 times took 1.51 seconds total

 Total FactoryGirl time 2.05 seconds

This will show the factories that are taking up the most time and help you decide where to focus your optimization work.

ES ·

Grow Your Rails Expertise Faster