test-prof 1.2.2 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|