test-prof 1.2.2 → 1.3.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 +15 -2
- data/README.md +1 -1
- data/lib/minitest/test_prof_plugin.rb +10 -0
- data/lib/test_prof/any_fixture/dump/sqlite.rb +1 -1
- data/lib/test_prof/any_fixture.rb +1 -1
- data/lib/test_prof/before_all/adapters/active_record.rb +3 -1
- data/lib/test_prof/before_all.rb +1 -1
- data/lib/test_prof/core.rb +167 -0
- data/lib/test_prof/factory_all_stub.rb +1 -1
- data/lib/test_prof/factory_default.rb +1 -1
- data/lib/test_prof/memory_prof/minitest.rb +56 -0
- data/lib/test_prof/memory_prof/printer/number_to_human.rb +44 -0
- data/lib/test_prof/memory_prof/printer.rb +93 -0
- data/lib/test_prof/memory_prof/rspec.rb +76 -0
- data/lib/test_prof/memory_prof/tracker/linked_list.rb +119 -0
- data/lib/test_prof/memory_prof/tracker/rss_tool.rb +87 -0
- data/lib/test_prof/memory_prof/tracker.rb +84 -0
- data/lib/test_prof/memory_prof.rb +78 -0
- data/lib/test_prof/recipes/logging.rb +1 -1
- data/lib/test_prof/recipes/minitest/sample.rb +2 -2
- data/lib/test_prof/recipes/rspec/let_it_be.rb +1 -1
- data/lib/test_prof/ruby_prof.rb +19 -3
- data/lib/test_prof/stack_prof/rspec.rb +2 -1
- data/lib/test_prof/stack_prof.rb +3 -3
- data/lib/test_prof/utils/sized_ordered_set.rb +4 -0
- data/lib/test_prof/vernier/rspec.rb +59 -0
- data/lib/test_prof/vernier.rb +152 -0
- data/lib/test_prof/version.rb +1 -1
- data/lib/test_prof.rb +3 -165
- metadata +14 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0678bc968a267ebeece00e12338f6408683140428ecdd041ece64c70e6bb91c0'
|
4
|
+
data.tar.gz: 3ab5bc88b7b5dea557847f05a16d7fc3e4c6c9212115cd16984a56b7dd7b1737
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b32e7e689cef27e72ce5f7e65ca0463bae7b83dfcaf77eba17aa0cc9bae1b74d6223b6b141e805debb7640b74b75be34bf238a8f41cb3efaf0386929935d814
|
7
|
+
data.tar.gz: 34200774bc30c39acc48109fbc5031fd8f48abb5f7175799a1e1bbfd7650a11a441c9ba63638bf186d78ef5cd15b7b33e64782c781a7f28bd43e43cb6d1e5588
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,18 @@
|
|
2
2
|
|
3
3
|
## master (unreleased)
|
4
4
|
|
5
|
+
## 1.3.0 (2023-11-21)
|
6
|
+
|
7
|
+
- Add Vernier integration. ([@palkan][])
|
8
|
+
|
9
|
+
- StackProf uses JSON format by default. ([@palkan][])
|
10
|
+
|
11
|
+
- MemoryProf ia added. ([@Vankiru][])
|
12
|
+
|
13
|
+
## 1.2.3 (2023-09-11)
|
14
|
+
|
15
|
+
- Minor fixes and dependencies upgrades.
|
16
|
+
|
5
17
|
## 1.2.2 (2023-06-27)
|
6
18
|
|
7
19
|
- Ignore inaccessible connection pools in `before_all`. ([@bf4][])
|
@@ -156,7 +168,7 @@ And for every test run see the overall factories usage:
|
|
156
168
|
|
157
169
|
## 1.0.0.rc2 (2021-01-06)
|
158
170
|
|
159
|
-
- Make Rails fixtures
|
171
|
+
- Make Rails fixtures accessible in `before_all`. ([@palkan][])
|
160
172
|
|
161
173
|
You can load and access fixtures when explicitly enabling them via `before_all(setup_fixtures: true, &block)`.
|
162
174
|
|
@@ -217,7 +229,7 @@ end
|
|
217
229
|
|
218
230
|
See more in [#181](https://github.com/test-prof/test-prof/issues/181).
|
219
231
|
|
220
|
-
- Adds the ability to define stackprof
|
232
|
+
- Adds the ability to define stackprof interval sampling by using `TEST_STACK_PROF_INTERVAL` env variable ([@LynxEyes][])
|
221
233
|
|
222
234
|
Now you can use `$ TEST_STACK_PROF=1 TEST_STACK_PROF_INTERVAL=10000 rspec` to define a custom interval (in microseconds).
|
223
235
|
|
@@ -363,3 +375,4 @@ See [changelog](https://github.com/test-prof/test-prof/blob/v0.8.0/CHANGELOG.md)
|
|
363
375
|
[@cbarton]: https://github.com/cbarton
|
364
376
|
[@peret]: https://github.com/peret
|
365
377
|
[@bf4]: https://github.com/bf4
|
378
|
+
[@Vankiru]: https://github.com/Vankiru
|
data/README.md
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "test_prof/event_prof/minitest"
|
4
4
|
require "test_prof/factory_doctor/minitest"
|
5
|
+
require "test_prof/memory_prof/minitest"
|
5
6
|
|
6
7
|
module Minitest # :nodoc:
|
7
8
|
module TestProf # :nodoc:
|
@@ -13,6 +14,8 @@ module Minitest # :nodoc:
|
|
13
14
|
opts[:per_example] = true if ENV["EVENT_PROF_EXAMPLES"]
|
14
15
|
opts[:fdoc] = true if ENV["FDOC"]
|
15
16
|
opts[:sample] = true if ENV["SAMPLE"] || ENV["SAMPLE_GROUPS"]
|
17
|
+
opts[:mem_prof_mode] = ENV["TEST_MEM_PROF"] if ENV["TEST_MEM_PROF"]
|
18
|
+
opts[:mem_prof_top_count] = ENV["TEST_MEM_PROF_COUNT"] if ENV["TEST_MEM_PROF_COUNT"]
|
16
19
|
end
|
17
20
|
end
|
18
21
|
end
|
@@ -33,6 +36,12 @@ module Minitest # :nodoc:
|
|
33
36
|
opts.on "--factory-doctor", TrueClass, "Enable Factory Doctor for your examples" do |flag|
|
34
37
|
options[:fdoc] = flag
|
35
38
|
end
|
39
|
+
opts.on "--mem-prof=MODE", "Enable MemoryProf for your examples" do |flag|
|
40
|
+
options[:mem_prof_mode] = flag
|
41
|
+
end
|
42
|
+
opts.on "--mem-prof-top-count=N", "Limits MemoryProf results with N groups/examples" do |flag|
|
43
|
+
options[:mem_prof_top_count] = flag
|
44
|
+
end
|
36
45
|
end
|
37
46
|
|
38
47
|
def self.plugin_test_prof_init(options)
|
@@ -40,6 +49,7 @@ module Minitest # :nodoc:
|
|
40
49
|
|
41
50
|
reporter << TestProf::EventProfReporter.new(options[:io], options) if options[:event]
|
42
51
|
reporter << TestProf::FactoryDoctorReporter.new(options[:io], options) if options[:fdoc]
|
52
|
+
reporter << TestProf::MemoryProfReporter.new(options[:io], options) if options[:mem_prof_mode]
|
43
53
|
|
44
54
|
::TestProf::MinitestSample.call if options[:sample]
|
45
55
|
end
|
@@ -5,10 +5,12 @@ module TestProf
|
|
5
5
|
module Adapters
|
6
6
|
# ActiveRecord adapter for `before_all`
|
7
7
|
module ActiveRecord
|
8
|
+
POOL_ARGS = ((::ActiveRecord::VERSION::MAJOR > 6) ? [:writing] : []).freeze
|
9
|
+
|
8
10
|
class << self
|
9
11
|
def all_connections
|
10
12
|
@all_connections ||= if ::ActiveRecord::Base.respond_to? :connects_to
|
11
|
-
::ActiveRecord::Base.connection_handler.connection_pool_list.filter_map { |pool|
|
13
|
+
::ActiveRecord::Base.connection_handler.connection_pool_list(*POOL_ARGS).filter_map { |pool|
|
12
14
|
begin
|
13
15
|
pool.connection
|
14
16
|
rescue *pool_connection_errors => error
|
data/lib/test_prof/before_all.rb
CHANGED
@@ -0,0 +1,167 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "fileutils"
|
4
|
+
require "logger"
|
5
|
+
|
6
|
+
require "test_prof/logging"
|
7
|
+
require "test_prof/utils"
|
8
|
+
|
9
|
+
# Ruby applications tests profiling tools.
|
10
|
+
#
|
11
|
+
# Contains tools to analyze factories usage, integrate with Ruby profilers,
|
12
|
+
# profile your examples using ActiveSupport notifications (if any) and
|
13
|
+
# statically analyze your code with custom RuboCop cops.
|
14
|
+
#
|
15
|
+
# Example usage:
|
16
|
+
#
|
17
|
+
# require 'test_prof'
|
18
|
+
#
|
19
|
+
# # Activate a tool by providing environment variable, e.g.
|
20
|
+
# TEST_RUBY_PROF=1 rspec ...
|
21
|
+
#
|
22
|
+
# # or manually in your code
|
23
|
+
# TestProf::RubyProf.run
|
24
|
+
#
|
25
|
+
# See other modules for more examples.
|
26
|
+
module TestProf
|
27
|
+
class << self
|
28
|
+
include Logging
|
29
|
+
|
30
|
+
def config
|
31
|
+
@config ||= Configuration.new
|
32
|
+
end
|
33
|
+
|
34
|
+
def configure
|
35
|
+
yield config
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns true if we're inside RSpec
|
39
|
+
def rspec?
|
40
|
+
defined?(RSpec::Core)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns true if we're inside Minitest
|
44
|
+
def minitest?
|
45
|
+
defined?(Minitest)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns true if Spring is used and not disabled
|
49
|
+
def spring?
|
50
|
+
# See https://github.com/rails/spring/blob/577cf01f232bb6dbd0ade7df2df2ac209697e741/lib/spring/binstub.rb
|
51
|
+
disabled = ENV["DISABLE_SPRING"]
|
52
|
+
defined?(::Spring::Application) && (disabled.nil? || disabled.empty? || disabled == "0")
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns the current process time
|
56
|
+
def now
|
57
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Require gem and shows a custom
|
61
|
+
# message if it fails to load
|
62
|
+
def require(gem_name, msg = nil)
|
63
|
+
Kernel.require gem_name
|
64
|
+
block_given? ? yield : true
|
65
|
+
rescue LoadError
|
66
|
+
log(:error, msg) if msg
|
67
|
+
false
|
68
|
+
end
|
69
|
+
|
70
|
+
# Run block only if provided env var is present and
|
71
|
+
# equal to the provided value (if any).
|
72
|
+
# Contains workaround for applications using Spring.
|
73
|
+
def activate(env_var, val = nil)
|
74
|
+
if spring?
|
75
|
+
notify_spring_detected
|
76
|
+
::Spring.after_fork do
|
77
|
+
activate!(env_var, val) do
|
78
|
+
notify_spring_activate env_var
|
79
|
+
yield
|
80
|
+
end
|
81
|
+
end
|
82
|
+
else
|
83
|
+
activate!(env_var, val) { yield }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Return absolute path to asset
|
88
|
+
def asset_path(filename)
|
89
|
+
::File.expand_path(filename, ::File.join(::File.dirname(__FILE__), "..", "..", "assets"))
|
90
|
+
end
|
91
|
+
|
92
|
+
# Return a path to store artifact
|
93
|
+
def artifact_path(filename)
|
94
|
+
create_artifact_dir
|
95
|
+
|
96
|
+
with_timestamps(
|
97
|
+
::File.join(
|
98
|
+
config.output_dir,
|
99
|
+
with_report_suffix(
|
100
|
+
filename
|
101
|
+
)
|
102
|
+
)
|
103
|
+
)
|
104
|
+
end
|
105
|
+
|
106
|
+
def create_artifact_dir
|
107
|
+
FileUtils.mkdir_p(config.output_dir)[0]
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def activate!(env_var, val)
|
113
|
+
yield if ENV[env_var] && (val.nil? || val === ENV[env_var])
|
114
|
+
end
|
115
|
+
|
116
|
+
def with_timestamps(path)
|
117
|
+
return path unless config.timestamps?
|
118
|
+
timestamps = "-#{now.to_i}"
|
119
|
+
"#{path.sub(/\.\w+$/, "")}#{timestamps}#{::File.extname(path)}"
|
120
|
+
end
|
121
|
+
|
122
|
+
def with_report_suffix(path)
|
123
|
+
return path if config.report_suffix.nil?
|
124
|
+
|
125
|
+
"#{path.sub(/\.\w+$/, "")}-#{config.report_suffix}#{::File.extname(path)}"
|
126
|
+
end
|
127
|
+
|
128
|
+
def notify_spring_detected
|
129
|
+
return if instance_variable_defined?(:@spring_notified)
|
130
|
+
log :info, "Spring detected"
|
131
|
+
@spring_notified = true
|
132
|
+
end
|
133
|
+
|
134
|
+
def notify_spring_activate(env_var)
|
135
|
+
log :info, "Activating #{env_var} with `Spring.after_fork`"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# TestProf configuration
|
140
|
+
class Configuration
|
141
|
+
attr_accessor :output, # IO to write logs
|
142
|
+
:color, # Whether to colorize output or not
|
143
|
+
:output_dir, # Directory to store artifacts
|
144
|
+
:timestamps, # Whether to use timestamped names for artifacts,
|
145
|
+
:report_suffix # Custom suffix for reports/artifacts
|
146
|
+
|
147
|
+
def initialize
|
148
|
+
@output = $stdout
|
149
|
+
@color = true
|
150
|
+
@output_dir = "tmp/test_prof"
|
151
|
+
@timestamps = false
|
152
|
+
@report_suffix = ENV["TEST_PROF_REPORT"]
|
153
|
+
end
|
154
|
+
|
155
|
+
def color?
|
156
|
+
color == true && output.is_a?(IO) && output.tty?
|
157
|
+
end
|
158
|
+
|
159
|
+
def timestamps?
|
160
|
+
timestamps == true
|
161
|
+
end
|
162
|
+
|
163
|
+
def logger
|
164
|
+
@logger ||= Logger.new(output, formatter: Logging::Formatter.new)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "minitest/base_reporter"
|
4
|
+
|
5
|
+
module Minitest
|
6
|
+
module TestProf
|
7
|
+
class MemoryProfReporter < BaseReporter # :nodoc:
|
8
|
+
attr_reader :tracker, :printer, :current_example
|
9
|
+
|
10
|
+
def initialize(io = $stdout, options = {})
|
11
|
+
super
|
12
|
+
|
13
|
+
configure_profiler(options)
|
14
|
+
|
15
|
+
@tracker = ::TestProf::MemoryProf.tracker
|
16
|
+
@printer = ::TestProf::MemoryProf.printer(tracker)
|
17
|
+
|
18
|
+
@current_example = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def prerecord(group, example)
|
22
|
+
set_current_example(group, example)
|
23
|
+
tracker.example_started(current_example)
|
24
|
+
end
|
25
|
+
|
26
|
+
def record(example)
|
27
|
+
tracker.example_finished(current_example)
|
28
|
+
end
|
29
|
+
|
30
|
+
def start
|
31
|
+
tracker.start
|
32
|
+
end
|
33
|
+
|
34
|
+
def report
|
35
|
+
tracker.finish
|
36
|
+
printer.print
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def set_current_example(group, example)
|
42
|
+
@current_example = {
|
43
|
+
name: example.gsub(/^test_(?:\d+_)?/, ""),
|
44
|
+
location: location_with_line_number(group, example)
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def configure_profiler(options)
|
49
|
+
::TestProf::MemoryProf.configure do |config|
|
50
|
+
config.mode = options[:mem_prof_mode]
|
51
|
+
config.top_count = options[:mem_prof_top_count] if options[:mem_prof_top_count]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TestProf
|
4
|
+
module MemoryProf
|
5
|
+
class Printer
|
6
|
+
module NumberToHuman
|
7
|
+
BASE = 1024
|
8
|
+
UNITS = %w[B KB MB GB TB PB EB ZB]
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def convert(number)
|
12
|
+
exponent = exponent(number)
|
13
|
+
human_size = number.to_f / (BASE**exponent)
|
14
|
+
|
15
|
+
"#{round(human_size)}#{UNITS[exponent]}"
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def exponent(number)
|
21
|
+
return 0 unless number.positive?
|
22
|
+
|
23
|
+
max = UNITS.size - 1
|
24
|
+
|
25
|
+
exponent = (Math.log(number) / Math.log(BASE)).to_i
|
26
|
+
(exponent > max) ? max : exponent
|
27
|
+
end
|
28
|
+
|
29
|
+
def round(number)
|
30
|
+
if integer?(number)
|
31
|
+
number.round
|
32
|
+
else
|
33
|
+
number.round(2)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def integer?(number)
|
38
|
+
number.round == number
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "test_prof/memory_prof/printer/number_to_human"
|
4
|
+
require "test_prof/ext/string_truncate"
|
5
|
+
|
6
|
+
module TestProf
|
7
|
+
module MemoryProf
|
8
|
+
class Printer
|
9
|
+
include Logging
|
10
|
+
using StringTruncate
|
11
|
+
|
12
|
+
def initialize(tracker)
|
13
|
+
@tracker = tracker
|
14
|
+
end
|
15
|
+
|
16
|
+
def print
|
17
|
+
messages = [
|
18
|
+
"MemoryProf results\n\n",
|
19
|
+
print_total,
|
20
|
+
print_block("groups", tracker.groups),
|
21
|
+
print_block("examples", tracker.examples)
|
22
|
+
]
|
23
|
+
|
24
|
+
log :info, messages.join
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :tracker
|
30
|
+
|
31
|
+
def print_block(name, items)
|
32
|
+
return if items.empty?
|
33
|
+
|
34
|
+
<<~GROUP
|
35
|
+
Top #{tracker.top_count} #{name} (by #{mode}):
|
36
|
+
|
37
|
+
#{print_items(items)}
|
38
|
+
GROUP
|
39
|
+
end
|
40
|
+
|
41
|
+
def print_items(items)
|
42
|
+
messages =
|
43
|
+
items.map do |item|
|
44
|
+
<<~ITEM
|
45
|
+
#{item[:name].truncate(30)} (#{item[:location]}) – +#{memory_amount(item)} (#{memory_percentage(item)}%)
|
46
|
+
ITEM
|
47
|
+
end
|
48
|
+
|
49
|
+
messages.join
|
50
|
+
end
|
51
|
+
|
52
|
+
def memory_percentage(item)
|
53
|
+
(100.0 * item[:memory] / tracker.total_memory).round(2)
|
54
|
+
end
|
55
|
+
|
56
|
+
def number_to_human(value)
|
57
|
+
NumberToHuman.convert(value)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class AllocPrinter < Printer
|
62
|
+
private
|
63
|
+
|
64
|
+
def mode
|
65
|
+
"allocations"
|
66
|
+
end
|
67
|
+
|
68
|
+
def print_total
|
69
|
+
"Total allocations: #{tracker.total_memory}\n\n"
|
70
|
+
end
|
71
|
+
|
72
|
+
def memory_amount(item)
|
73
|
+
item[:memory]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class RssPrinter < Printer
|
78
|
+
private
|
79
|
+
|
80
|
+
def mode
|
81
|
+
"RSS"
|
82
|
+
end
|
83
|
+
|
84
|
+
def print_total
|
85
|
+
"Final RSS: #{number_to_human(tracker.total_memory)}\n\n"
|
86
|
+
end
|
87
|
+
|
88
|
+
def memory_amount(item)
|
89
|
+
number_to_human(item[:memory])
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TestProf
|
4
|
+
module MemoryProf
|
5
|
+
class RSpecListener
|
6
|
+
NOTIFICATIONS = %i[
|
7
|
+
example_started
|
8
|
+
example_finished
|
9
|
+
example_group_started
|
10
|
+
example_group_finished
|
11
|
+
].freeze
|
12
|
+
|
13
|
+
attr_reader :tracker, :printer
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@tracker = MemoryProf.tracker
|
17
|
+
@printer = MemoryProf.printer(tracker)
|
18
|
+
|
19
|
+
@tracker.start
|
20
|
+
end
|
21
|
+
|
22
|
+
def example_started(notification)
|
23
|
+
tracker.example_started(example(notification))
|
24
|
+
end
|
25
|
+
|
26
|
+
def example_finished(notification)
|
27
|
+
tracker.example_finished(example(notification))
|
28
|
+
end
|
29
|
+
|
30
|
+
def example_group_started(notification)
|
31
|
+
tracker.group_started(group(notification))
|
32
|
+
end
|
33
|
+
|
34
|
+
def example_group_finished(notification)
|
35
|
+
tracker.group_finished(group(notification))
|
36
|
+
end
|
37
|
+
|
38
|
+
def report
|
39
|
+
tracker.finish
|
40
|
+
printer.print
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def example(notification)
|
46
|
+
{
|
47
|
+
name: notification.example.description,
|
48
|
+
location: notification.example.metadata[:location]
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
def group(notification)
|
53
|
+
{
|
54
|
+
name: notification.group.description,
|
55
|
+
location: notification.group.metadata[:location]
|
56
|
+
}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
TestProf.activate("TEST_MEM_PROF") do
|
63
|
+
RSpec.configure do |config|
|
64
|
+
listener = nil
|
65
|
+
|
66
|
+
config.before(:suite) do
|
67
|
+
listener = TestProf::MemoryProf::RSpecListener.new
|
68
|
+
|
69
|
+
config.reporter.register_listener(
|
70
|
+
listener, *TestProf::MemoryProf::RSpecListener::NOTIFICATIONS
|
71
|
+
)
|
72
|
+
end
|
73
|
+
|
74
|
+
config.after(:suite) { listener&.report }
|
75
|
+
end
|
76
|
+
end
|