Module: TestProf::FactoryDoctor

Extended by:
Logging
Defined in:
lib/test_prof/factory_doctor.rb,
lib/test_prof/factory_doctor/rspec.rb,
lib/test_prof/factory_doctor/fabrication_patch.rb,
lib/test_prof/factory_doctor/factory_bot_patch.rb

Overview

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

Defined Under Namespace

Modules: FabricationPatch, FactoryBotPatch Classes: Configuration, RSpecListener, Result

Constant Summary collapse

IGNORED_QUERIES_PATTERN =
%r{(
  pg_table|
  pg_attribute|
  pg_namespace|
  show\stables|
  pragma|
  sqlite_master/rollback|
  \ATRUNCATE TABLE|
  \AALTER TABLE|
  \ABEGIN|
  \ACOMMIT|
  \AROLLBACK|
  \ARELEASE|
  \ASAVEPOINT
)}xi.freeze

Constants included from Logging

Logging::COLORS

Class Attribute Summary collapse

Class Method Summary collapse

Methods included from Logging

log

Class Attribute Details

.countObject (readonly)

Returns the value of attribute count.



55
56
57
# File 'lib/test_prof/factory_doctor.rb', line 55

def count
  @count
end

.queries_countObject (readonly)

Returns the value of attribute queries_count.



55
56
57
# File 'lib/test_prof/factory_doctor.rb', line 55

def queries_count
  @queries_count
end

.timeObject (readonly)

Returns the value of attribute time.



55
56
57
# File 'lib/test_prof/factory_doctor.rb', line 55

def time
  @time
end

Class Method Details

.configObject



57
58
59
# File 'lib/test_prof/factory_doctor.rb', line 57

def config
  @config ||= Configuration.new
end

.configure {|config| ... } ⇒ Object

Yields:



61
62
63
# File 'lib/test_prof/factory_doctor.rb', line 61

def configure
  yield config
end

.ignoreObject

Do not analyze code within the block



106
107
108
109
110
111
112
# File 'lib/test_prof/factory_doctor.rb', line 106

def ignore
  @ignored = true
  res = yield
ensure
  @ignored = false
  res
end

.ignore!Object



114
115
116
# File 'lib/test_prof/factory_doctor.rb', line 114

def ignore!
  @ignored = true
end

.ignore?Boolean

Returns:

  • (Boolean)


118
119
120
# File 'lib/test_prof/factory_doctor.rb', line 118

def ignore?
  @ignored == true
end

.initObject

Patch factory lib, init counters



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# 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

.resultObject



101
102
103
# File 'lib/test_prof/factory_doctor.rb', line 101

def result
  Result.new(count, time, queries_count)
end

.stamp?Boolean

Returns:

  • (Boolean)


88
89
90
# File 'lib/test_prof/factory_doctor.rb', line 88

def stamp?
  !@stamp.nil?
end

.startObject



92
93
94
95
# File 'lib/test_prof/factory_doctor.rb', line 92

def start
  reset!
  @running = true
end

.stopObject



97
98
99
# File 'lib/test_prof/factory_doctor.rb', line 97

def stop
  @running = false
end

.within_factory(strategy) ⇒ Object



122
123
124
125
126
127
128
129
130
131
132
133
134
135
# 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