test-prof 0.7.5 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +174 -107
- data/LICENSE.txt +1 -1
- data/README.md +9 -3
- data/lib/minitest/base_reporter.rb +18 -12
- data/lib/minitest/test_prof_plugin.rb +8 -8
- data/lib/test_prof/any_fixture.rb +3 -3
- data/lib/test_prof/before_all/adapters/active_record.rb +11 -0
- data/lib/test_prof/before_all/isolator.rb +18 -0
- data/lib/test_prof/before_all.rb +82 -2
- data/lib/test_prof/cops/rspec/aggregate_failures.rb +6 -6
- data/lib/test_prof/event_prof/custom_events/factory_create.rb +27 -45
- data/lib/test_prof/event_prof/custom_events/sidekiq_inline.rb +8 -38
- data/lib/test_prof/event_prof/custom_events/sidekiq_jobs.rb +7 -25
- data/lib/test_prof/event_prof/instrumentations/active_support.rb +1 -1
- data/lib/test_prof/event_prof/minitest.rb +4 -4
- data/lib/test_prof/event_prof/monitor.rb +45 -8
- data/lib/test_prof/event_prof/rspec.rb +4 -11
- data/lib/test_prof/event_prof.rb +6 -6
- data/lib/test_prof/ext/factory_bot_strategy.rb +24 -0
- data/lib/test_prof/factory_bot.rb +1 -1
- data/lib/test_prof/factory_default.rb +1 -1
- data/lib/test_prof/factory_doctor/fabrication_patch.rb +12 -0
- data/lib/test_prof/factory_doctor/factory_bot_patch.rb +5 -1
- data/lib/test_prof/factory_doctor/minitest.rb +4 -4
- data/lib/test_prof/factory_doctor/rspec.rb +15 -12
- data/lib/test_prof/factory_doctor.rb +29 -7
- data/lib/test_prof/factory_prof/factory_builders/fabrication.rb +1 -1
- data/lib/test_prof/factory_prof/factory_builders/factory_bot.rb +2 -17
- data/lib/test_prof/factory_prof/printers/flamegraph.rb +6 -2
- data/lib/test_prof/factory_prof/printers/simple.rb +8 -6
- data/lib/test_prof/factory_prof.rb +29 -15
- data/lib/test_prof/recipes/logging.rb +86 -21
- data/lib/test_prof/recipes/minitest/before_all.rb +3 -2
- data/lib/test_prof/recipes/minitest/sample.rb +5 -5
- data/lib/test_prof/recipes/rspec/any_fixture.rb +3 -1
- data/lib/test_prof/recipes/rspec/before_all.rb +12 -3
- data/lib/test_prof/recipes/rspec/factory_all_stub.rb +5 -1
- data/lib/test_prof/recipes/rspec/let_it_be.rb +27 -12
- data/lib/test_prof/rspec_dissect/rspec.rb +2 -6
- data/lib/test_prof/rspec_dissect.rb +13 -19
- data/lib/test_prof/rspec_stamp/parser.rb +1 -1
- data/lib/test_prof/rspec_stamp/rspec.rb +1 -1
- data/lib/test_prof/rspec_stamp.rb +14 -14
- data/lib/test_prof/ruby_prof/rspec.rb +2 -6
- data/lib/test_prof/ruby_prof.rb +32 -24
- data/lib/test_prof/stack_prof/rspec.rb +5 -6
- data/lib/test_prof/stack_prof.rb +23 -15
- data/lib/test_prof/tag_prof/printers/simple.rb +4 -4
- data/lib/test_prof/tag_prof/result.rb +3 -3
- data/lib/test_prof/tag_prof/rspec.rb +9 -14
- data/lib/test_prof/utils/html_builder.rb +1 -1
- data/lib/test_prof/utils/sized_ordered_set.rb +1 -1
- data/lib/test_prof/version.rb +1 -1
- data/lib/test_prof.rb +6 -12
- metadata +35 -14
data/lib/test_prof/before_all.rb
CHANGED
|
@@ -17,13 +17,89 @@ module TestProf
|
|
|
17
17
|
|
|
18
18
|
def begin_transaction
|
|
19
19
|
raise AdapterMissing if adapter.nil?
|
|
20
|
-
|
|
20
|
+
|
|
21
|
+
config.run_hooks(:begin) do
|
|
22
|
+
adapter.begin_transaction
|
|
23
|
+
end
|
|
24
|
+
yield
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def within_transaction
|
|
28
|
+
yield
|
|
21
29
|
end
|
|
22
30
|
|
|
23
31
|
def rollback_transaction
|
|
24
32
|
raise AdapterMissing if adapter.nil?
|
|
25
|
-
|
|
33
|
+
|
|
34
|
+
config.run_hooks(:rollback) do
|
|
35
|
+
adapter.rollback_transaction
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def config
|
|
40
|
+
@config ||= Configuration.new
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def configure
|
|
44
|
+
yield config
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
class HooksChain # :nodoc:
|
|
49
|
+
attr_reader :type, :after, :before
|
|
50
|
+
|
|
51
|
+
def initialize(type)
|
|
52
|
+
@type = type
|
|
53
|
+
@before = []
|
|
54
|
+
@after = []
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def run
|
|
58
|
+
before.each(&:call)
|
|
59
|
+
yield
|
|
60
|
+
after.each(&:call)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
class Configuration
|
|
65
|
+
HOOKS = %i[begin rollback].freeze
|
|
66
|
+
|
|
67
|
+
def initialize
|
|
68
|
+
@hooks = Hash.new { |h, k| h[k] = HooksChain.new(k) }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Add `before` hook for `begin` or
|
|
72
|
+
# `rollback` operation:
|
|
73
|
+
#
|
|
74
|
+
# config.before(:rollback) { ... }
|
|
75
|
+
def before(type)
|
|
76
|
+
validate_hook_type!(type)
|
|
77
|
+
hooks[type].before << Proc.new
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Add `after` hook for `begin` or
|
|
81
|
+
# `rollback` operation:
|
|
82
|
+
#
|
|
83
|
+
# config.after(:begin) { ... }
|
|
84
|
+
def after(type)
|
|
85
|
+
validate_hook_type!(type)
|
|
86
|
+
hooks[type].after << Proc.new
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def run_hooks(type) # :nodoc:
|
|
90
|
+
validate_hook_type!(type)
|
|
91
|
+
hooks[type].run { yield }
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
private
|
|
95
|
+
|
|
96
|
+
def validate_hook_type!(type)
|
|
97
|
+
return if HOOKS.include?(type)
|
|
98
|
+
|
|
99
|
+
raise ArgumentError, "Unknown hook type: #{type}. Valid types: #{HOOKS.join(", ")}"
|
|
26
100
|
end
|
|
101
|
+
|
|
102
|
+
attr_reader :hooks
|
|
27
103
|
end
|
|
28
104
|
end
|
|
29
105
|
end
|
|
@@ -33,3 +109,7 @@ if defined?(::ActiveRecord::Base)
|
|
|
33
109
|
|
|
34
110
|
TestProf::BeforeAll.adapter = TestProf::BeforeAll::Adapters::ActiveRecord
|
|
35
111
|
end
|
|
112
|
+
|
|
113
|
+
if defined?(::Isolator)
|
|
114
|
+
require "test_prof/before_all/isolator"
|
|
115
|
+
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
3
|
+
require "rubocop"
|
|
4
|
+
require "test_prof/utils"
|
|
5
5
|
|
|
6
6
|
module RuboCop
|
|
7
7
|
module Cop
|
|
@@ -38,7 +38,7 @@ module RuboCop
|
|
|
38
38
|
class << self
|
|
39
39
|
def supported?
|
|
40
40
|
return @supported if instance_variable_defined?(:@supported)
|
|
41
|
-
@supported = TestProf::Utils.verify_gem_version(
|
|
41
|
+
@supported = TestProf::Utils.verify_gem_version("rubocop", at_least: "0.51.0")
|
|
42
42
|
|
|
43
43
|
unless @supported
|
|
44
44
|
warn "RSpec/AggregateFailures cop requires RuboCop >= 0.51.0. Skipping"
|
|
@@ -62,7 +62,7 @@ module RuboCop
|
|
|
62
62
|
add_offense(
|
|
63
63
|
node,
|
|
64
64
|
location: :expression,
|
|
65
|
-
message:
|
|
65
|
+
message: "Use :aggregate_failures instead of several one-liners."
|
|
66
66
|
)
|
|
67
67
|
end
|
|
68
68
|
|
|
@@ -140,7 +140,7 @@ module RuboCop
|
|
|
140
140
|
%(#{method_name} "works", :aggregate_failures do)
|
|
141
141
|
end
|
|
142
142
|
|
|
143
|
-
def body_from(node, base_indent =
|
|
143
|
+
def body_from(node, base_indent = "")
|
|
144
144
|
method, _args, body = *node
|
|
145
145
|
body_source = method.method_name == :its ? body_from_its(method, body) : body.source
|
|
146
146
|
"#{base_indent}#{indent}#{body_source}"
|
|
@@ -162,7 +162,7 @@ module RuboCop
|
|
|
162
162
|
end
|
|
163
163
|
|
|
164
164
|
def indent
|
|
165
|
-
@indent ||= " " * (config.for_cop(
|
|
165
|
+
@indent ||= " " * (config.for_cop("IndentationWidth")["Width"] || 2)
|
|
166
166
|
end
|
|
167
167
|
end
|
|
168
168
|
end
|
|
@@ -1,56 +1,38 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "test_prof/factory_bot"
|
|
4
|
+
require "test_prof/ext/factory_bot_strategy"
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
module FactoryCreate # :nodoc: all
|
|
7
|
-
module RunnerPatch
|
|
8
|
-
def run(strategy = @strategy)
|
|
9
|
-
return super unless strategy == :create
|
|
10
|
-
FactoryCreate.track(@name) do
|
|
11
|
-
super
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
class << self
|
|
17
|
-
def setup!
|
|
18
|
-
@depth = 0
|
|
19
|
-
TestProf::FactoryBot::FactoryRunner.prepend RunnerPatch
|
|
20
|
-
end
|
|
6
|
+
using TestProf::FactoryBotStrategy
|
|
21
7
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
else
|
|
33
|
-
yield
|
|
34
|
-
end
|
|
35
|
-
ensure
|
|
36
|
-
@depth -= 1
|
|
37
|
-
end
|
|
38
|
-
res
|
|
39
|
-
end
|
|
8
|
+
TestProf::EventProf::CustomEvents.register("factory.create") do
|
|
9
|
+
if defined?(TestProf::FactoryBot) || defined?(Fabricate)
|
|
10
|
+
if defined?(TestProf::FactoryBot)
|
|
11
|
+
TestProf::EventProf.monitor(
|
|
12
|
+
TestProf::FactoryBot::FactoryRunner,
|
|
13
|
+
"factory.create",
|
|
14
|
+
:run,
|
|
15
|
+
top_level: true,
|
|
16
|
+
guard: ->(strategy = @strategy) { strategy.create? }
|
|
17
|
+
)
|
|
40
18
|
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
19
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
20
|
+
if defined?(Fabricate)
|
|
21
|
+
TestProf::EventProf.monitor(
|
|
22
|
+
Fabricate.singleton_class,
|
|
23
|
+
"factory.create",
|
|
24
|
+
:create,
|
|
25
|
+
top_level: true
|
|
26
|
+
)
|
|
27
|
+
end
|
|
47
28
|
else
|
|
48
|
-
TestProf.log(
|
|
49
|
-
|
|
50
|
-
|
|
29
|
+
TestProf.log(
|
|
30
|
+
:error,
|
|
31
|
+
<<~MSG
|
|
32
|
+
Failed to load factory_bot / factory_girl / fabrication.
|
|
51
33
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
34
|
+
Make sure that any of them is in your Gemfile.
|
|
35
|
+
MSG
|
|
36
|
+
)
|
|
55
37
|
end
|
|
56
38
|
end
|
|
@@ -1,50 +1,20 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module TestProf::EventProf::CustomEvents
|
|
4
|
-
module SidekiqInline # :nodoc: all
|
|
5
|
-
module ClientPatch
|
|
6
|
-
def raw_push(*)
|
|
7
|
-
return super unless Sidekiq::Testing.inline?
|
|
8
|
-
SidekiqInline.track { super }
|
|
9
|
-
end
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
class << self
|
|
13
|
-
def setup!
|
|
14
|
-
@depth = 0
|
|
15
|
-
Sidekiq::Client.prepend ClientPatch
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def track
|
|
19
|
-
@depth += 1
|
|
20
|
-
res = nil
|
|
21
|
-
begin
|
|
22
|
-
res =
|
|
23
|
-
if @depth == 1
|
|
24
|
-
ActiveSupport::Notifications.instrument(
|
|
25
|
-
'sidekiq.inline'
|
|
26
|
-
) { yield }
|
|
27
|
-
else
|
|
28
|
-
yield
|
|
29
|
-
end
|
|
30
|
-
ensure
|
|
31
|
-
@depth -= 1
|
|
32
|
-
end
|
|
33
|
-
res
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
3
|
TestProf::EventProf::CustomEvents.register("sidekiq.inline") do
|
|
40
4
|
if TestProf.require(
|
|
41
|
-
|
|
5
|
+
"sidekiq/testing",
|
|
42
6
|
<<~MSG
|
|
43
7
|
Failed to load Sidekiq.
|
|
44
8
|
|
|
45
9
|
Make sure that "sidekiq" gem is in your Gemfile.
|
|
46
10
|
MSG
|
|
47
11
|
)
|
|
48
|
-
TestProf::EventProf
|
|
12
|
+
TestProf::EventProf.monitor(
|
|
13
|
+
Sidekiq::Client,
|
|
14
|
+
"sidekiq.inline",
|
|
15
|
+
:raw_push,
|
|
16
|
+
top_level: true,
|
|
17
|
+
guard: ->(*) { Sidekiq::Testing.inline? }
|
|
18
|
+
)
|
|
49
19
|
end
|
|
50
20
|
end
|
|
@@ -1,38 +1,20 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module TestProf::EventProf::CustomEvents
|
|
4
|
-
module SidekiqJobs # :nodoc: all
|
|
5
|
-
module ClientPatch
|
|
6
|
-
def raw_push(*)
|
|
7
|
-
return super unless Sidekiq::Testing.inline?
|
|
8
|
-
SidekiqJobs.track { super }
|
|
9
|
-
end
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
class << self
|
|
13
|
-
def setup!
|
|
14
|
-
Sidekiq::Client.prepend ClientPatch
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def track
|
|
18
|
-
ActiveSupport::Notifications.instrument(
|
|
19
|
-
'sidekiq.jobs'
|
|
20
|
-
) { yield }
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
3
|
TestProf::EventProf::CustomEvents.register("sidekiq.jobs") do
|
|
27
4
|
if TestProf.require(
|
|
28
|
-
|
|
5
|
+
"sidekiq/testing",
|
|
29
6
|
<<~MSG
|
|
30
7
|
Failed to load Sidekiq.
|
|
31
8
|
|
|
32
9
|
Make sure that "sidekiq" gem is in your Gemfile.
|
|
33
10
|
MSG
|
|
34
11
|
)
|
|
35
|
-
TestProf::EventProf
|
|
12
|
+
TestProf::EventProf.monitor(
|
|
13
|
+
Sidekiq::Client,
|
|
14
|
+
"sidekiq.jobs",
|
|
15
|
+
:raw_push,
|
|
16
|
+
guard: ->(*) { Sidekiq::Testing.inline? }
|
|
17
|
+
)
|
|
36
18
|
TestProf::EventProf.configure do |config|
|
|
37
19
|
config.rank_by = :count
|
|
38
20
|
end
|
|
@@ -6,7 +6,7 @@ module TestProf::EventProf
|
|
|
6
6
|
module ActiveSupport
|
|
7
7
|
class << self
|
|
8
8
|
def subscribe(event)
|
|
9
|
-
raise ArgumentError,
|
|
9
|
+
raise ArgumentError, "Block is required!" unless block_given?
|
|
10
10
|
|
|
11
11
|
::ActiveSupport::Notifications.subscribe(event) do |_event, start, finish, *_args|
|
|
12
12
|
yield (finish - start)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
3
|
+
require "minitest/base_reporter"
|
|
4
|
+
require "minitest/event_prof_formatter"
|
|
5
5
|
|
|
6
6
|
module Minitest
|
|
7
7
|
module TestProf
|
|
@@ -10,7 +10,7 @@ module Minitest
|
|
|
10
10
|
super
|
|
11
11
|
@profiler = configure_profiler(options)
|
|
12
12
|
|
|
13
|
-
log :info, "EventProf enabled (#{@profiler.events.join(
|
|
13
|
+
log :info, "EventProf enabled (#{@profiler.events.join(", ")})"
|
|
14
14
|
|
|
15
15
|
@formatter = EventProfFormatter.new(@profiler)
|
|
16
16
|
@current_group = nil
|
|
@@ -45,7 +45,7 @@ module Minitest
|
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
@current_example = {
|
|
48
|
-
name: example.gsub(/^test_(?:\d+_)?/,
|
|
48
|
+
name: example.gsub(/^test_(?:\d+_)?/, ""),
|
|
49
49
|
location: location_with_line_number(group, example)
|
|
50
50
|
}
|
|
51
51
|
|
|
@@ -4,17 +4,54 @@ module TestProf
|
|
|
4
4
|
module EventProf
|
|
5
5
|
# Wrap methods with instrumentation
|
|
6
6
|
module Monitor
|
|
7
|
+
class BaseTracker
|
|
8
|
+
attr_reader :event
|
|
9
|
+
|
|
10
|
+
def initialize(event)
|
|
11
|
+
@event = event
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def track
|
|
15
|
+
TestProf::EventProf.instrumenter.instrument(event) { yield }
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class TopLevelTracker < BaseTracker
|
|
20
|
+
attr_reader :id
|
|
21
|
+
|
|
22
|
+
def initialize(event)
|
|
23
|
+
super
|
|
24
|
+
@id = :"event_prof_monitor_#{event}"
|
|
25
|
+
Thread.current[id] = 0
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def track
|
|
29
|
+
Thread.current[id] += 1
|
|
30
|
+
res = nil
|
|
31
|
+
begin
|
|
32
|
+
res =
|
|
33
|
+
if Thread.current[id] == 1
|
|
34
|
+
super { yield }
|
|
35
|
+
else
|
|
36
|
+
yield
|
|
37
|
+
end
|
|
38
|
+
ensure
|
|
39
|
+
Thread.current[id] -= 1
|
|
40
|
+
end
|
|
41
|
+
res
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
7
45
|
class << self
|
|
8
|
-
def call(mod, event, *mids)
|
|
46
|
+
def call(mod, event, *mids, guard: nil, top_level: false)
|
|
47
|
+
tracker = top_level ? TopLevelTracker.new(event) : BaseTracker.new(event)
|
|
48
|
+
|
|
9
49
|
patch = Module.new do
|
|
10
50
|
mids.each do |mid|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
) { super }
|
|
16
|
-
end
|
|
17
|
-
SRC
|
|
51
|
+
define_method(mid) do |*args, &block|
|
|
52
|
+
next super(*args, &block) unless guard.nil? || instance_exec(*args, &guard)
|
|
53
|
+
tracker.track { super(*args, &block) }
|
|
54
|
+
end
|
|
18
55
|
end
|
|
19
56
|
end
|
|
20
57
|
|
|
@@ -14,15 +14,13 @@ module TestProf
|
|
|
14
14
|
example_group_started
|
|
15
15
|
example_group_finished
|
|
16
16
|
example_started
|
|
17
|
-
|
|
18
|
-
example_passed
|
|
19
|
-
example_pending
|
|
17
|
+
example_finished
|
|
20
18
|
].freeze
|
|
21
19
|
|
|
22
20
|
def initialize
|
|
23
21
|
@profiler = EventProf.build
|
|
24
22
|
|
|
25
|
-
log :info, "EventProf enabled (#{@profiler.events.join(
|
|
23
|
+
log :info, "EventProf enabled (#{@profiler.events.join(", ")})"
|
|
26
24
|
end
|
|
27
25
|
|
|
28
26
|
def example_group_started(notification)
|
|
@@ -43,11 +41,6 @@ module TestProf
|
|
|
43
41
|
@profiler.example_finished notification.example
|
|
44
42
|
end
|
|
45
43
|
|
|
46
|
-
# NOTE: RSpec < 3.4.0 doesn't have example_finished event
|
|
47
|
-
alias example_passed example_finished
|
|
48
|
-
alias example_failed example_finished
|
|
49
|
-
alias example_pending example_finished
|
|
50
|
-
|
|
51
44
|
def print
|
|
52
45
|
@profiler.each(&method(:report))
|
|
53
46
|
end
|
|
@@ -145,8 +138,8 @@ module TestProf
|
|
|
145
138
|
end
|
|
146
139
|
|
|
147
140
|
# Register EventProf listener
|
|
148
|
-
TestProf.activate(
|
|
149
|
-
TestProf::EventProf::CustomEvents.activate_all(ENV[
|
|
141
|
+
TestProf.activate("EVENT_PROF") do
|
|
142
|
+
TestProf::EventProf::CustomEvents.activate_all(ENV["EVENT_PROF"])
|
|
150
143
|
|
|
151
144
|
RSpec.configure do |config|
|
|
152
145
|
listener = nil
|
data/lib/test_prof/event_prof.rb
CHANGED
|
@@ -31,19 +31,19 @@ module TestProf
|
|
|
31
31
|
class Configuration
|
|
32
32
|
# Map of supported instrumenters
|
|
33
33
|
INSTRUMENTERS = {
|
|
34
|
-
active_support:
|
|
34
|
+
active_support: "ActiveSupport"
|
|
35
35
|
}.freeze
|
|
36
36
|
|
|
37
37
|
attr_accessor :instrumenter, :top_count, :per_example,
|
|
38
38
|
:rank_by, :event
|
|
39
39
|
|
|
40
40
|
def initialize
|
|
41
|
-
@event = ENV[
|
|
41
|
+
@event = ENV["EVENT_PROF"]
|
|
42
42
|
@instrumenter = :active_support
|
|
43
|
-
@top_count = (ENV[
|
|
44
|
-
@per_example = ENV[
|
|
45
|
-
@rank_by = (ENV[
|
|
46
|
-
@stamp = ENV[
|
|
43
|
+
@top_count = (ENV["EVENT_PROF_TOP"] || 5).to_i
|
|
44
|
+
@per_example = ENV["EVENT_PROF_EXAMPLES"] == "1"
|
|
45
|
+
@rank_by = (ENV["EVENT_PROF_RANK"] || :time).to_sym
|
|
46
|
+
@stamp = ENV["EVENT_PROF_STAMP"]
|
|
47
47
|
|
|
48
48
|
RSpecStamp.config.tags = @stamp if stamp?
|
|
49
49
|
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module TestProf
|
|
4
|
+
# FactoryBot 5.0 uses strategy classes for associations,
|
|
5
|
+
# older versions and top-level invocations use Symbols.
|
|
6
|
+
#
|
|
7
|
+
# This Refinement should be used FactoryRunner patches to check
|
|
8
|
+
# that strategy is :create.
|
|
9
|
+
module FactoryBotStrategy
|
|
10
|
+
refine Symbol do
|
|
11
|
+
def create?
|
|
12
|
+
self == :create
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
if defined?(::FactoryBot::Strategy::Create)
|
|
17
|
+
refine Class do
|
|
18
|
+
def create?
|
|
19
|
+
self <= ::FactoryBot::Strategy::Create
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module TestProf # :nodoc: all
|
|
4
|
-
FACTORY_GIRL_NAMES = {
|
|
4
|
+
FACTORY_GIRL_NAMES = {"factory_bot" => "::FactoryBot", "factory_girl" => "::FactoryGirl"}.freeze
|
|
5
5
|
|
|
6
6
|
FACTORY_GIRL_NAMES.find do |name, cname|
|
|
7
7
|
TestProf.require(name) do
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "test_prof/ext/factory_bot_strategy"
|
|
4
|
+
|
|
3
5
|
module TestProf
|
|
4
6
|
module FactoryDoctor
|
|
5
7
|
# Wrap #run method with FactoryDoctor tracking
|
|
6
8
|
module FactoryBotPatch
|
|
9
|
+
using TestProf::FactoryBotStrategy
|
|
10
|
+
|
|
7
11
|
def run(strategy = @strategy)
|
|
8
|
-
FactoryDoctor.within_factory(strategy) { super }
|
|
12
|
+
FactoryDoctor.within_factory(strategy.create? ? :create : :other) { super }
|
|
9
13
|
end
|
|
10
14
|
end
|
|
11
15
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
3
|
+
require "minitest/base_reporter"
|
|
4
|
+
require "test_prof/ext/float_duration"
|
|
5
5
|
|
|
6
6
|
module Minitest
|
|
7
7
|
module TestProf # :nodoc:
|
|
@@ -47,7 +47,7 @@ module Minitest
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
@example_groups[group] << {
|
|
50
|
-
description: example.name.gsub(/^test_(?:\d+_)?/,
|
|
50
|
+
description: example.name.gsub(/^test_(?:\d+_)?/, ""),
|
|
51
51
|
location: location_with_line_number(example),
|
|
52
52
|
factories: result.count,
|
|
53
53
|
time: result.time
|
|
@@ -87,7 +87,7 @@ module Minitest
|
|
|
87
87
|
private
|
|
88
88
|
|
|
89
89
|
def pluralize_records(count)
|
|
90
|
-
count == 1 ?
|
|
90
|
+
count == 1 ? "1 record" : "#{count} records"
|
|
91
91
|
end
|
|
92
92
|
end
|
|
93
93
|
end
|
|
@@ -12,9 +12,7 @@ module TestProf
|
|
|
12
12
|
|
|
13
13
|
NOTIFICATIONS = %i[
|
|
14
14
|
example_started
|
|
15
|
-
|
|
16
|
-
example_failed
|
|
17
|
-
example_pending
|
|
15
|
+
example_finished
|
|
18
16
|
].freeze
|
|
19
17
|
|
|
20
18
|
def initialize
|
|
@@ -45,11 +43,6 @@ module TestProf
|
|
|
45
43
|
@time += result.time
|
|
46
44
|
end
|
|
47
45
|
|
|
48
|
-
# NOTE: RSpec < 3.4.0 doesn't have example_finished event
|
|
49
|
-
alias example_passed example_finished
|
|
50
|
-
alias example_failed example_finished
|
|
51
|
-
alias example_pending example_finished
|
|
52
|
-
|
|
53
46
|
def print
|
|
54
47
|
return log(:info, SUCCESS_MESSAGE) if @example_groups.empty?
|
|
55
48
|
|
|
@@ -65,9 +58,15 @@ module TestProf
|
|
|
65
58
|
MSG
|
|
66
59
|
|
|
67
60
|
@example_groups.each do |group, examples|
|
|
68
|
-
|
|
61
|
+
group_time = examples.sum { |ex| ex.metadata[:time] }
|
|
62
|
+
group_count = examples.sum { |ex| ex.metadata[:factories] }
|
|
63
|
+
|
|
64
|
+
msgs << "#{group.description} (#{group.metadata[:location]}) " \
|
|
65
|
+
"(#{pluralize_records(group_count)} created, " \
|
|
66
|
+
"#{group_time.duration})\n"
|
|
67
|
+
|
|
69
68
|
examples.each do |ex|
|
|
70
|
-
msgs << " #{ex.description} (#{ex.metadata[:location]}) "\
|
|
69
|
+
msgs << " #{ex.description} (#{ex.metadata[:location]}) " \
|
|
71
70
|
"– #{pluralize_records(ex.metadata[:factories])} created, "\
|
|
72
71
|
"#{ex.metadata[:time].duration}\n"
|
|
73
72
|
end
|
|
@@ -122,7 +121,7 @@ module TestProf
|
|
|
122
121
|
end
|
|
123
122
|
|
|
124
123
|
# Register FactoryDoctor listener
|
|
125
|
-
TestProf.activate(
|
|
124
|
+
TestProf.activate("FDOC") do
|
|
126
125
|
TestProf::FactoryDoctor.init
|
|
127
126
|
|
|
128
127
|
RSpec.configure do |config|
|
|
@@ -138,7 +137,11 @@ TestProf.activate('FDOC') do
|
|
|
138
137
|
config.after(:suite) { listener&.print }
|
|
139
138
|
end
|
|
140
139
|
|
|
141
|
-
RSpec.shared_context "factory_doctor:ignore"
|
|
140
|
+
RSpec.shared_context "factory_doctor:ignore" do
|
|
142
141
|
around(:each) { |ex| TestProf::FactoryDoctor.ignore(&ex) }
|
|
143
142
|
end
|
|
143
|
+
|
|
144
|
+
RSpec.configure do |config|
|
|
145
|
+
config.include_context "factory_doctor:ignore", fd_ignore: true
|
|
146
|
+
end
|
|
144
147
|
end
|