module TestProf::FactoryDoctor

FactoryDoctor is a tool that helps you identify tests that perform unnecessary database queries.

Constants

IGNORED_QUERIES_PATTERN

Attributes

count[R]
queries_count[R]
time[R]

Public Class Methods

config() click to toggle source
# File lib/test_prof/factory_doctor.rb, line 57
def config
  @config ||= Configuration.new
end
configure() { |config| ... } click to toggle source
# File lib/test_prof/factory_doctor.rb, line 61
def configure
  yield config
end
ignore() { || ... } click to toggle source

Do not analyze code within the block

# File lib/test_prof/factory_doctor.rb, line 106
def ignore
  @ignored = true
  res = yield
ensure
  @ignored = false
  res
end
ignore!() click to toggle source
# File lib/test_prof/factory_doctor.rb, line 114
def ignore!
  @ignored = true
end
ignore?() click to toggle source
# File lib/test_prof/factory_doctor.rb, line 118
def ignore?
  @ignored == true
end
init() click to toggle source

Patch factory lib, init counters

# File lib/test_prof/factory_doctor.rb, line 66
def init
  reset!

  @running = false

  log :info, "FactoryDoctor enabled (event: \"#{config.event}\", threshold: #{config.threshold})"

  # Monkey-patch FactoryBot / FactoryGirl
  TestProf::FactoryBot::FactoryRunner.prepend(FactoryBotPatch) if
    defined?(TestProf::FactoryBot)

  # Monkey-patch Fabrication
  ::Fabricate.singleton_class.prepend(FabricationPatch) if
    defined?(::Fabricate)

  subscribe!

  @stamp = ENV["FDOC_STAMP"]

  RSpecStamp.config.tags = @stamp if stamp?
end
result() click to toggle source
# File lib/test_prof/factory_doctor.rb, line 101
def result
  Result.new(count, time, queries_count)
end
stamp?() click to toggle source
# File lib/test_prof/factory_doctor.rb, line 88
def stamp?
  !@stamp.nil?
end
start() click to toggle source
# File lib/test_prof/factory_doctor.rb, line 92
def start
  reset!
  @running = true
end
stop() click to toggle source
# File lib/test_prof/factory_doctor.rb, line 97
def stop
  @running = false
end
within_factory(strategy) { || ... } click to toggle source
# File lib/test_prof/factory_doctor.rb, line 122
def within_factory(strategy)
  return yield if ignore? || !running? || (strategy != :create)

  begin
    ts = TestProf.now if @depth.zero?
    @depth += 1
    @count += 1
    yield
  ensure
    @depth -= 1

    @time += (TestProf.now - ts) if @depth.zero?
  end
end

Private Class Methods

reset!() click to toggle source
# File lib/test_prof/factory_doctor.rb, line 139
def reset!
  @depth = 0
  @time = 0.0
  @count = 0
  @queries_count = 0
  @ignored = false
end
running?() click to toggle source
# File lib/test_prof/factory_doctor.rb, line 159
def running?
  @running == true
end
subscribe!() click to toggle source
# File lib/test_prof/factory_doctor.rb, line 147
def subscribe!
  ::ActiveSupport::Notifications.subscribe(config.event) do |_name, _start, _finish, _id, query|
    next if ignore? || !running? || within_factory?
    next if IGNORED_QUERIES_PATTERN.match?(query[:sql])
    @queries_count += 1
  end
end
within_factory?() click to toggle source
# File lib/test_prof/factory_doctor.rb, line 155
def within_factory?
  @depth > 0
end