test-prof 0.7.4 → 0.8.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 +26 -2
- data/README.md +5 -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 +12 -0
- data/lib/test_prof/before_all/isolator.rb +18 -0
- data/lib/test_prof/before_all.rb +9 -0
- data/lib/test_prof/cops/rspec/aggregate_failures.rb +6 -6
- data/lib/test_prof/event_prof/custom_events/factory_create.rb +1 -1
- data/lib/test_prof/event_prof/custom_events/sidekiq_inline.rb +2 -2
- data/lib/test_prof/event_prof/custom_events/sidekiq_jobs.rb +2 -2
- 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/rspec.rb +4 -11
- data/lib/test_prof/event_prof.rb +9 -8
- data/lib/test_prof/factory_bot.rb +1 -1
- data/lib/test_prof/factory_default.rb +1 -1
- data/lib/test_prof/factory_doctor/minitest.rb +4 -4
- data/lib/test_prof/factory_doctor/rspec.rb +7 -10
- data/lib/test_prof/factory_doctor.rb +5 -4
- data/lib/test_prof/factory_prof/factory_builders/fabrication.rb +1 -1
- data/lib/test_prof/factory_prof/factory_builders/factory_bot.rb +19 -1
- data/lib/test_prof/factory_prof/printers/flamegraph.rb +1 -1
- data/lib/test_prof/factory_prof.rb +6 -6
- data/lib/test_prof/logging.rb +1 -1
- data/lib/test_prof/recipes/logging.rb +89 -22
- 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 +13 -6
- data/lib/test_prof/recipes/rspec/factory_all_stub.rb +5 -1
- data/lib/test_prof/recipes/rspec/let_it_be.rb +4 -16
- data/lib/test_prof/rspec_dissect/rspec.rb +2 -6
- data/lib/test_prof/rspec_dissect.rb +15 -20
- 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 +16 -15
- data/lib/test_prof/ruby_prof/rspec.rb +2 -6
- data/lib/test_prof/ruby_prof.rb +36 -26
- data/lib/test_prof/stack_prof/rspec.rb +5 -6
- data/lib/test_prof/stack_prof.rb +26 -16
- 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/tag_prof.rb +3 -1
- 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 +13 -3
- metadata +41 -13
|
@@ -45,7 +45,7 @@ module TestProf::FactoryProf
|
|
|
45
45
|
node = paths[path]
|
|
46
46
|
node[:value] += 1
|
|
47
47
|
else
|
|
48
|
-
node = {
|
|
48
|
+
node = {name: sample, value: 1, total: result.raw_stats.fetch(sample)[:total]}
|
|
49
49
|
paths[path] = node
|
|
50
50
|
|
|
51
51
|
if parent.nil?
|
|
@@ -17,7 +17,7 @@ module TestProf
|
|
|
17
17
|
attr_accessor :mode
|
|
18
18
|
|
|
19
19
|
def initialize
|
|
20
|
-
@mode = ENV[
|
|
20
|
+
@mode = ENV["FPROF"] == "flamegraph" ? :flamegraph : :simple
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
# Whether we want to generate flamegraphs
|
|
@@ -39,7 +39,7 @@ module TestProf
|
|
|
39
39
|
return @stats if instance_variable_defined?(:@stats)
|
|
40
40
|
|
|
41
41
|
@stats = @raw_stats.values
|
|
42
|
-
|
|
42
|
+
.sort_by { |el| -el[:total] }
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def total
|
|
@@ -51,8 +51,8 @@ module TestProf
|
|
|
51
51
|
|
|
52
52
|
def sorted_stats(key)
|
|
53
53
|
@raw_stats.values
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
.map { |el| [el[:name], el[key]] }
|
|
55
|
+
.sort_by { |el| -el[1] }
|
|
56
56
|
end
|
|
57
57
|
end
|
|
58
58
|
|
|
@@ -120,7 +120,7 @@ module TestProf
|
|
|
120
120
|
def reset!
|
|
121
121
|
@stacks = [] if config.flamegraph?
|
|
122
122
|
@depth = 0
|
|
123
|
-
@stats = Hash.new { |h, k| h[k] = {
|
|
123
|
+
@stats = Hash.new { |h, k| h[k] = {name: k, total: 0, top_level: 0} }
|
|
124
124
|
flush_stack
|
|
125
125
|
end
|
|
126
126
|
|
|
@@ -137,6 +137,6 @@ module TestProf
|
|
|
137
137
|
end
|
|
138
138
|
end
|
|
139
139
|
|
|
140
|
-
TestProf.activate(
|
|
140
|
+
TestProf.activate("FPROF") do
|
|
141
141
|
TestProf::FactoryProf.run
|
|
142
142
|
end
|
data/lib/test_prof/logging.rb
CHANGED
|
@@ -1,43 +1,110 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
require "test_prof"
|
|
4
|
+
|
|
5
|
+
module TestProf
|
|
6
|
+
module Rails
|
|
7
|
+
# Add `with_logging` and `with_ar_logging helpers`
|
|
8
|
+
module LoggingHelpers
|
|
9
|
+
class << self
|
|
10
|
+
attr_writer :logger
|
|
11
|
+
|
|
12
|
+
def logger
|
|
13
|
+
return @logger if instance_variable_defined?(:@logger)
|
|
14
|
+
|
|
15
|
+
@logger = Logger.new(STDOUT)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def ar_loggables
|
|
19
|
+
return @ar_loggables if instance_variable_defined?(:@ar_loggables)
|
|
20
|
+
|
|
21
|
+
@ar_loggables = [
|
|
22
|
+
::ActiveRecord::Base,
|
|
23
|
+
::ActiveSupport::LogSubscriber
|
|
24
|
+
]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
|
28
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
|
29
|
+
def all_loggables
|
|
30
|
+
return @all_loggables if instance_variable_defined?(:@all_loggables)
|
|
31
|
+
|
|
32
|
+
@all_loggables = [
|
|
33
|
+
::ActiveSupport::LogSubscriber,
|
|
34
|
+
::Rails,
|
|
35
|
+
defined?(::ActiveRecord::Base) && ::ActiveRecord::Base,
|
|
36
|
+
defined?(::ActiveJob::Base) && ::ActiveJob::Base,
|
|
37
|
+
defined?(::ActionView::Base) && ::ActionView::Base,
|
|
38
|
+
defined?(::ActionMailer::Base) && ::ActionMailer::Base,
|
|
39
|
+
defined?(::ActionCable::Server::Base.config) && ::ActionCable::Server::Base.config,
|
|
40
|
+
defined?(::ActiveStorage) && ::ActiveStorage
|
|
41
|
+
].compact
|
|
42
|
+
end
|
|
43
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
44
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
|
45
|
+
|
|
46
|
+
def swap_logger(loggables)
|
|
47
|
+
loggables.map do |loggable|
|
|
48
|
+
was_logger = loggable.logger
|
|
49
|
+
loggable.logger = logger
|
|
50
|
+
was_logger
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def restore_logger(was_loggers, loggables)
|
|
55
|
+
loggables.each_with_index do |loggable, i|
|
|
56
|
+
loggable.logger = was_loggers[i]
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Enable verbose Rails logging within a block
|
|
62
|
+
def with_logging
|
|
63
|
+
*loggers = LoggingHelpers.swap_logger(LoggingHelpers.all_loggables)
|
|
64
|
+
yield
|
|
65
|
+
ensure
|
|
66
|
+
LoggingHelpers.restore_logger(loggers, LoggingHelpers.all_loggables)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def with_ar_logging
|
|
70
|
+
*loggers = LoggingHelpers.swap_logger(LoggingHelpers.ar_loggables)
|
|
71
|
+
yield
|
|
72
|
+
ensure
|
|
73
|
+
LoggingHelpers.restore_logger(loggers, LoggingHelpers.ar_loggables)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
if TestProf.rspec?
|
|
80
|
+
RSpec.shared_context "logging:verbose" do
|
|
5
81
|
around(:each) do |ex|
|
|
6
|
-
|
|
7
|
-
Rails.logger,
|
|
8
|
-
ActiveRecord::Base.logger
|
|
9
|
-
ActiveSupport::LogSubscriber.logger =
|
|
10
|
-
Rails.logger =
|
|
11
|
-
ActiveRecord::Base.logger = Logger.new(STDOUT)
|
|
12
|
-
ex.run
|
|
13
|
-
ActiveSupport::LogSubscriber.logger,
|
|
14
|
-
Rails.logger,
|
|
15
|
-
ActiveRecord::Base.logger = *loggers
|
|
82
|
+
with_logging(&ex)
|
|
16
83
|
end
|
|
17
84
|
end
|
|
18
85
|
|
|
19
|
-
RSpec.shared_context "logging:active_record"
|
|
86
|
+
RSpec.shared_context "logging:active_record" do
|
|
20
87
|
around(:each) do |ex|
|
|
21
|
-
|
|
22
|
-
ActiveSupport::LogSubscriber.logger
|
|
23
|
-
ActiveSupport::LogSubscriber.logger =
|
|
24
|
-
ActiveRecord::Base.logger = Logger.new(STDOUT)
|
|
25
|
-
ex.run
|
|
26
|
-
ActiveSupport::LogSubscriber.logger,
|
|
27
|
-
ActiveRecord::Base.logger = *loggers
|
|
88
|
+
with_ar_logging(&ex)
|
|
28
89
|
end
|
|
29
90
|
end
|
|
91
|
+
|
|
92
|
+
RSpec.configure do |config|
|
|
93
|
+
config.include TestProf::Rails::LoggingHelpers
|
|
94
|
+
config.include_context "logging:active_record", log: :ar
|
|
95
|
+
config.include_context "logging:verbose", log: true
|
|
96
|
+
end
|
|
30
97
|
end
|
|
31
98
|
|
|
32
99
|
TestProf.activate("LOG", "all") do
|
|
33
100
|
TestProf.log :info, "Rails verbose logging enabled"
|
|
34
101
|
ActiveSupport::LogSubscriber.logger =
|
|
35
102
|
Rails.logger =
|
|
36
|
-
ActiveRecord::Base.logger =
|
|
103
|
+
ActiveRecord::Base.logger = TestProf::Rails::LoggingHelpers.logger
|
|
37
104
|
end
|
|
38
105
|
|
|
39
106
|
TestProf.activate("LOG", "ar") do
|
|
40
107
|
TestProf.log :info, "Active Record verbose logging enabled"
|
|
41
108
|
ActiveSupport::LogSubscriber.logger =
|
|
42
|
-
ActiveRecord::Base.logger =
|
|
109
|
+
ActiveRecord::Base.logger = TestProf::Rails::LoggingHelpers.logger
|
|
43
110
|
end
|
|
@@ -14,7 +14,7 @@ module TestProf
|
|
|
14
14
|
def suites
|
|
15
15
|
# Make sure that sample contains only _real_ suites
|
|
16
16
|
Minitest::Runnable.runnables
|
|
17
|
-
|
|
17
|
+
.reject { |suite| CORE_RUNNABLES.include?(suite) }
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def sample_groups(sample_size)
|
|
@@ -39,10 +39,10 @@ module TestProf
|
|
|
39
39
|
|
|
40
40
|
# Overrides Minitest.run
|
|
41
41
|
def run(*)
|
|
42
|
-
if ENV[
|
|
43
|
-
MinitestSample.sample_examples(ENV[
|
|
44
|
-
elsif ENV[
|
|
45
|
-
MinitestSample.sample_groups(ENV[
|
|
42
|
+
if ENV["SAMPLE"]
|
|
43
|
+
MinitestSample.sample_examples(ENV["SAMPLE"].to_i)
|
|
44
|
+
elsif ENV["SAMPLE_GROUPS"]
|
|
45
|
+
MinitestSample.sample_groups(ENV["SAMPLE_GROUPS"].to_i)
|
|
46
46
|
end
|
|
47
47
|
super
|
|
48
48
|
end
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require "test_prof/any_fixture"
|
|
4
4
|
require "test_prof/recipes/rspec/before_all"
|
|
5
5
|
|
|
6
|
-
RSpec.shared_context "any_fixture:clean"
|
|
6
|
+
RSpec.shared_context "any_fixture:clean" do
|
|
7
7
|
extend TestProf::BeforeAll::RSpec
|
|
8
8
|
|
|
9
9
|
before_all do
|
|
@@ -12,6 +12,8 @@ RSpec.shared_context "any_fixture:clean", with_clean_fixture: true do
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
RSpec.configure do |config|
|
|
15
|
+
config.include_context "any_fixture:clean", with_clean_fixture: true
|
|
16
|
+
|
|
15
17
|
config.after(:suite) do
|
|
16
18
|
TestProf::AnyFixture.report_stats if TestProf::AnyFixture.reporting_enabled?
|
|
17
19
|
TestProf::AnyFixture.reset
|
|
@@ -9,13 +9,14 @@ module TestProf
|
|
|
9
9
|
def before_all(&block)
|
|
10
10
|
raise ArgumentError, "Block is required!" unless block_given?
|
|
11
11
|
|
|
12
|
-
return
|
|
12
|
+
return within_before_all(&block) if within_before_all?
|
|
13
13
|
|
|
14
14
|
@__before_all_activated__ = true
|
|
15
15
|
|
|
16
16
|
before(:all) do
|
|
17
|
-
BeforeAll.begin_transaction
|
|
18
|
-
|
|
17
|
+
BeforeAll.begin_transaction do
|
|
18
|
+
instance_eval(&block)
|
|
19
|
+
end
|
|
19
20
|
end
|
|
20
21
|
|
|
21
22
|
after(:all) do
|
|
@@ -23,6 +24,14 @@ module TestProf
|
|
|
23
24
|
end
|
|
24
25
|
end
|
|
25
26
|
|
|
27
|
+
def within_before_all(&block)
|
|
28
|
+
before(:all) do
|
|
29
|
+
BeforeAll.within_transaction do
|
|
30
|
+
instance_eval(&block)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
26
35
|
def within_before_all?
|
|
27
36
|
instance_variable_defined?(:@__before_all_activated__)
|
|
28
37
|
end
|
|
@@ -30,6 +39,4 @@ module TestProf
|
|
|
30
39
|
end
|
|
31
40
|
end
|
|
32
41
|
|
|
33
|
-
RSpec.
|
|
34
|
-
config.extend TestProf::BeforeAll::RSpec
|
|
35
|
-
end
|
|
42
|
+
RSpec::Core::ExampleGroup.extend TestProf::BeforeAll::RSpec
|
|
@@ -4,7 +4,11 @@ require "test_prof/factory_all_stub"
|
|
|
4
4
|
|
|
5
5
|
TestProf::FactoryAllStub.init
|
|
6
6
|
|
|
7
|
-
RSpec.shared_context "factory:stub"
|
|
7
|
+
RSpec.shared_context "factory:stub" do
|
|
8
8
|
prepend_before(:all) { TestProf::FactoryAllStub.enable! }
|
|
9
9
|
append_after(:all) { TestProf::FactoryAllStub.disable! }
|
|
10
10
|
end
|
|
11
|
+
|
|
12
|
+
RSpec.configure do |config|
|
|
13
|
+
config.include_context "factory:stub", factory: :stub
|
|
14
|
+
end
|
|
@@ -14,11 +14,6 @@ module TestProf
|
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
# Only works with RSpec 3.2.0
|
|
18
|
-
def supported?
|
|
19
|
-
TestProf::Utils.verify_gem_version('rspec-core', at_least: '3.2.0')
|
|
20
|
-
end
|
|
21
|
-
|
|
22
17
|
private
|
|
23
18
|
|
|
24
19
|
def modules
|
|
@@ -28,20 +23,15 @@ module TestProf
|
|
|
28
23
|
# Use uniq prefix for instance variables to avoid collisions
|
|
29
24
|
# We want to use the power of Ruby's unicode support)
|
|
30
25
|
# And we love cats!)
|
|
31
|
-
PREFIX = RUBY_ENGINE ==
|
|
26
|
+
PREFIX = RUBY_ENGINE == "jruby" ? "@__jruby_is_not_cat_friendly__" : "@😸"
|
|
32
27
|
|
|
33
28
|
def let_it_be(identifier, **options, &block)
|
|
34
|
-
unless LetItBe.supported?
|
|
35
|
-
TestProf.log :warn, "let_it_be requires RSpec >= 3.2.0. Fallback to let!"
|
|
36
|
-
return let!(identifier, &block)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
29
|
initializer = proc do
|
|
40
30
|
instance_variable_set(:"#{PREFIX}#{identifier}", instance_exec(&block))
|
|
41
31
|
end
|
|
42
32
|
|
|
43
33
|
if within_before_all?
|
|
44
|
-
|
|
34
|
+
within_before_all(&initializer)
|
|
45
35
|
else
|
|
46
36
|
before_all(&initializer)
|
|
47
37
|
end
|
|
@@ -72,7 +62,7 @@ module TestProf
|
|
|
72
62
|
LetItBe.module_for(self).module_eval do
|
|
73
63
|
define_method(identifier) do
|
|
74
64
|
# Trying to detect the context (couldn't find other way so far)
|
|
75
|
-
if
|
|
65
|
+
if /\(:context\)/.match?(@__inspect_output)
|
|
76
66
|
instance_variable_get(:"#{PREFIX}#{identifier}")
|
|
77
67
|
else
|
|
78
68
|
# Fallback to let definition
|
|
@@ -86,6 +76,4 @@ module TestProf
|
|
|
86
76
|
end
|
|
87
77
|
end
|
|
88
78
|
|
|
89
|
-
RSpec.
|
|
90
|
-
config.extend TestProf::LetItBe
|
|
91
|
-
end
|
|
79
|
+
RSpec::Core::ExampleGroup.extend TestProf::LetItBe
|
|
@@ -10,8 +10,7 @@ module TestProf
|
|
|
10
10
|
|
|
11
11
|
NOTIFICATIONS = %i[
|
|
12
12
|
example_group_finished
|
|
13
|
-
|
|
14
|
-
example_failed
|
|
13
|
+
example_finished
|
|
15
14
|
].freeze
|
|
16
15
|
|
|
17
16
|
def initialize
|
|
@@ -35,9 +34,6 @@ module TestProf
|
|
|
35
34
|
@examples_time += notification.example.execution_result.run_time
|
|
36
35
|
end
|
|
37
36
|
|
|
38
|
-
alias example_passed example_finished
|
|
39
|
-
alias example_failed example_finished
|
|
40
|
-
|
|
41
37
|
def example_group_finished(notification)
|
|
42
38
|
return unless notification.group.top_level?
|
|
43
39
|
|
|
@@ -127,7 +123,7 @@ module TestProf
|
|
|
127
123
|
end
|
|
128
124
|
|
|
129
125
|
# Register RSpecDissect listener
|
|
130
|
-
TestProf.activate(
|
|
126
|
+
TestProf.activate("RD_PROF") do
|
|
131
127
|
RSpec.configure do |config|
|
|
132
128
|
listener = nil
|
|
133
129
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "test_prof"
|
|
3
4
|
require "test_prof/rspec_stamp"
|
|
4
5
|
require "test_prof/logging"
|
|
5
6
|
|
|
@@ -20,10 +21,10 @@ module TestProf
|
|
|
20
21
|
Thread.current[:_rspec_dissect_let_depth] += 1
|
|
21
22
|
begin
|
|
22
23
|
res = if Thread.current[:_rspec_dissect_let_depth] == 1
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
RSpecDissect.track(:let, id) { super }
|
|
25
|
+
else
|
|
26
|
+
super
|
|
27
|
+
end
|
|
27
28
|
ensure
|
|
28
29
|
Thread.current[:_rspec_dissect_let_depth] -= 1
|
|
29
30
|
end
|
|
@@ -44,14 +45,14 @@ module TestProf
|
|
|
44
45
|
|
|
45
46
|
def initialize
|
|
46
47
|
@let_stats_enabled = true
|
|
47
|
-
@let_top_count = (ENV[
|
|
48
|
-
@top_count = (ENV[
|
|
49
|
-
@stamp = ENV[
|
|
50
|
-
@mode = ENV[
|
|
48
|
+
@let_top_count = (ENV["RD_PROF_LET_TOP"] || 3).to_i
|
|
49
|
+
@top_count = (ENV["RD_PROF_TOP"] || 5).to_i
|
|
50
|
+
@stamp = ENV["RD_PROF_STAMP"]
|
|
51
|
+
@mode = ENV["RD_PROF"] == "1" ? "all" : ENV["RD_PROF"]
|
|
51
52
|
|
|
52
53
|
unless MODES.include?(mode)
|
|
53
54
|
raise "Unknown RSpecDissect mode: #{mode};" \
|
|
54
|
-
"available modes: #{MODES.join(
|
|
55
|
+
"available modes: #{MODES.join(", ")}"
|
|
55
56
|
end
|
|
56
57
|
|
|
57
58
|
RSpecStamp.config.tags = @stamp if stamp?
|
|
@@ -86,10 +87,8 @@ module TestProf
|
|
|
86
87
|
def init
|
|
87
88
|
RSpec::Core::Example.prepend(ExampleInstrumentation)
|
|
88
89
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
RSpec::Core::MemoizedHelpers::NonThreadSafeMemoized.prepend(MemoizedInstrumentation)
|
|
92
|
-
end
|
|
90
|
+
RSpec::Core::MemoizedHelpers::ThreadsafeMemoized.prepend(MemoizedInstrumentation)
|
|
91
|
+
RSpec::Core::MemoizedHelpers::NonThreadSafeMemoized.prepend(MemoizedInstrumentation)
|
|
93
92
|
|
|
94
93
|
@data = {}
|
|
95
94
|
|
|
@@ -99,10 +98,6 @@ module TestProf
|
|
|
99
98
|
|
|
100
99
|
reset!
|
|
101
100
|
|
|
102
|
-
if config.let? && !memoization_available?
|
|
103
|
-
log :warn, "RSpecDissect: `let` profiling is not supported (requires RSpec >= 3.3.0)\n"
|
|
104
|
-
end
|
|
105
|
-
|
|
106
101
|
log :info, "RSpecDissect enabled"
|
|
107
102
|
end
|
|
108
103
|
|
|
@@ -119,7 +114,7 @@ module TestProf
|
|
|
119
114
|
|
|
120
115
|
def reset!
|
|
121
116
|
METRICS.each do |type|
|
|
122
|
-
@data[type.to_s] = {
|
|
117
|
+
@data[type.to_s] = {time: 0.0, meta: []}
|
|
123
118
|
end
|
|
124
119
|
end
|
|
125
120
|
|
|
@@ -145,8 +140,8 @@ end
|
|
|
145
140
|
|
|
146
141
|
require "test_prof/rspec_dissect/collectors/let"
|
|
147
142
|
require "test_prof/rspec_dissect/collectors/before"
|
|
148
|
-
require "test_prof/rspec_dissect/rspec" if
|
|
143
|
+
require "test_prof/rspec_dissect/rspec" if TestProf.rspec?
|
|
149
144
|
|
|
150
|
-
TestProf.activate(
|
|
145
|
+
TestProf.activate("RD_PROF") do
|
|
151
146
|
TestProf::RSpecDissect.init
|
|
152
147
|
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "test_prof"
|
|
3
4
|
require "test_prof/logging"
|
|
4
5
|
require "test_prof/rspec_stamp/parser"
|
|
5
6
|
|
|
@@ -15,8 +16,8 @@ module TestProf
|
|
|
15
16
|
|
|
16
17
|
def initialize
|
|
17
18
|
@ignore_files = [%r{spec/support}]
|
|
18
|
-
@dry_run = ENV[
|
|
19
|
-
self.tags = ENV[
|
|
19
|
+
@dry_run = ENV["RSTAMP_DRY_RUN"] == "1"
|
|
20
|
+
self.tags = ENV["RSTAMP"]
|
|
20
21
|
end
|
|
21
22
|
|
|
22
23
|
def dry_run?
|
|
@@ -25,10 +26,10 @@ module TestProf
|
|
|
25
26
|
|
|
26
27
|
def tags=(val)
|
|
27
28
|
@tags = if val.is_a?(String)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
parse_tags(val)
|
|
30
|
+
else
|
|
31
|
+
val
|
|
32
|
+
end
|
|
32
33
|
end
|
|
33
34
|
|
|
34
35
|
private
|
|
@@ -37,10 +38,10 @@ module TestProf
|
|
|
37
38
|
str.split(/\s*,\s*/).each_with_object([]) do |tag, acc|
|
|
38
39
|
k, v = tag.split(":")
|
|
39
40
|
acc << if v.nil?
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
k.to_sym
|
|
42
|
+
else
|
|
43
|
+
Hash[k.to_sym, v.to_sym]
|
|
44
|
+
end
|
|
44
45
|
end
|
|
45
46
|
end
|
|
46
47
|
end
|
|
@@ -128,7 +129,7 @@ module TestProf
|
|
|
128
129
|
parsed = Parser.parse(code)
|
|
129
130
|
return false unless parsed
|
|
130
131
|
|
|
131
|
-
desc = parsed.desc_const || quote(parsed.desc ||
|
|
132
|
+
desc = parsed.desc_const || quote(parsed.desc || "works")
|
|
132
133
|
|
|
133
134
|
tags.each do |t|
|
|
134
135
|
if t.is_a?(Hash)
|
|
@@ -155,9 +156,9 @@ module TestProf
|
|
|
155
156
|
end
|
|
156
157
|
end
|
|
157
158
|
|
|
158
|
-
replacement = "\\1#{parsed.fname}#{need_parens ?
|
|
159
|
-
"#{[desc, tags_str, htags_str].compact.join(
|
|
160
|
-
"#{need_parens ?
|
|
159
|
+
replacement = "\\1#{parsed.fname}#{need_parens ? "(" : " "}"\
|
|
160
|
+
"#{[desc, tags_str, htags_str].compact.join(", ")}"\
|
|
161
|
+
"#{need_parens ? ") " : " "}\\3"
|
|
161
162
|
|
|
162
163
|
if config.dry_run?
|
|
163
164
|
log :info, "Patched: #{example.sub(EXAMPLE_RXP, replacement)}"
|
|
@@ -181,4 +182,4 @@ module TestProf
|
|
|
181
182
|
end
|
|
182
183
|
end
|
|
183
184
|
|
|
184
|
-
require "test_prof/rspec_stamp/rspec" if
|
|
185
|
+
require "test_prof/rspec_stamp/rspec" if TestProf.rspec?
|
|
@@ -6,8 +6,7 @@ module TestProf
|
|
|
6
6
|
class Listener # :nodoc:
|
|
7
7
|
NOTIFICATIONS = %i[
|
|
8
8
|
example_started
|
|
9
|
-
|
|
10
|
-
example_passed
|
|
9
|
+
example_finished
|
|
11
10
|
].freeze
|
|
12
11
|
|
|
13
12
|
def example_started(notification)
|
|
@@ -18,14 +17,11 @@ module TestProf
|
|
|
18
17
|
|
|
19
18
|
def example_finished(notification)
|
|
20
19
|
return unless profile?(notification.example)
|
|
21
|
-
notification.example.metadata[:rprof_report]
|
|
20
|
+
notification.example.metadata[:rprof_report]&.dump(
|
|
22
21
|
notification.example.full_description.parameterize
|
|
23
22
|
)
|
|
24
23
|
end
|
|
25
24
|
|
|
26
|
-
alias example_passed example_finished
|
|
27
|
-
alias example_failed example_finished
|
|
28
|
-
|
|
29
25
|
private
|
|
30
26
|
|
|
31
27
|
def profile?(example)
|