test-prof 1.0.3 → 1.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c3ea5b7078b12209f32a60554f25acffccd184bdf852ebfe14cad161ded2c180
4
- data.tar.gz: 34e61ec6d58e5688b441ea09c1be524ae563f9ca82f334541c3f2c3197787cbd
3
+ metadata.gz: 2f55e42ee372a9ebe0f8981487931bf70ab3209e38163b32f84a7553bdfb4249
4
+ data.tar.gz: 3ca0352ca4671c11d18937d3ee1de361322c827671d199d079b1460667c32a1c
5
5
  SHA512:
6
- metadata.gz: d866bfe03650d81cb2dd5b698b5de5703a8fa505c7c8d0b0e4283b8130eb774ac43c5cca6a750fef6f8342acdec7e518613489e898fd354f133e1793df833e45
7
- data.tar.gz: cf92cef8973837d2e09ff3bcc4449fb0675ebfca3f10fc75a314f10d885ad92aaae2f6fac0cd99e7250eb57985208e6d6f53b88d101f177709a172b8fcae1815
6
+ metadata.gz: 00dcd7797667e28b54fe32e36392e44b80a1dd6fdcc04b8a0565084311c5420bbe017eecba2ae553b84b2cdd6bc92886f15a919da8e1ba7a293aa737bc2c81da
7
+ data.tar.gz: eed04e297d23872fae979d7da614d4cf2730c4414b7eb26ad14095e619eeabd872619cd3e51293a4949fc04f214807cb10425da4a7ebe343df8a8f9af766f413
data/CHANGELOG.md CHANGED
@@ -2,6 +2,48 @@
2
2
 
3
3
  ## master (unrealeased)
4
4
 
5
+ ## 1.0.7 (2021-08-30)
6
+
7
+ - Fix access to `let_it_be` variables in `after(:all)` hook. ([@cbarton][])
8
+
9
+ - Add support for using the before_all hook with Rails' parallelize feature (using processes). ([@peret][])
10
+
11
+ Make sure to include `TestProf::BeforeAll::Minitest` before you call `parallelize`.
12
+
13
+ ## 1.0.6 (2021-06-23)
14
+
15
+ - Fix Spring detection when `DISABLE_SPRING=1` is used. ([@palkan][])
16
+
17
+ - Make `before_all` in Minitest inheritable. ([@palkan][])
18
+
19
+ ## 1.0.5 (2021-05-13)
20
+
21
+ - Fix logging regression when no newline has been added. ([@palkan][])
22
+
23
+ ## 1.0.4 (2021-05-12)
24
+
25
+ - Add ability to use custom logger. ([@palkan][])
26
+
27
+ ```ruby
28
+ TestProf.configure do |config|
29
+ config.logger = Logger.new($stdout, level: Logger::WARN)
30
+ end
31
+ ```
32
+
33
+ - Add `nate_heckler` mode for FactoryProf. ([@palkan][])
34
+
35
+ Drop this into your `rails_helper.rb` or `test_helper.rb`:
36
+
37
+ ```ruby
38
+ require "test_prof/factory_prof/nate_heckler"
39
+ ```
40
+
41
+ And for every test run see the overall factories usage:
42
+
43
+ ```sh
44
+ [TEST PROF INFO] Time spent in factories: 04:31.222 (54% of total time)
45
+ ```
46
+
5
47
  ## 1.0.3 (2021-04-30)
6
48
 
7
49
  - Minor fixes.
@@ -150,7 +192,7 @@ end
150
192
  ```
151
193
 
152
194
  - Print warning when `ActiveRecordSharedConnection` is used in the version of Rails
153
- supporting `lock_threads` (5.1+). ([@palkan][])
195
+ supporting `lock_threads` (5.1+). ([@palkan][])
154
196
 
155
197
  ## 0.9.0 (2019-05-14)
156
198
 
@@ -208,20 +250,20 @@ See [changelog](https://github.com/test-prof/test-prof/blob/v0.8.0/CHANGELOG.md)
208
250
  [@palkan]: https://github.com/palkan
209
251
  [@marshall-lee]: https://github.com/marshall-lee
210
252
  [@danielwestendorf]: https://github.com/danielwestendorf
211
- [@Shkrt]: https://github.com/Shkrt
212
- [@IDolgirev]: https://github.com/IDolgirev
253
+ [@shkrt]: https://github.com/Shkrt
254
+ [@idolgirev]: https://github.com/IDolgirev
213
255
  [@desoleary]: https://github.com/desoleary
214
256
  [@rabotyaga]: https://github.com/rabotyaga
215
- [@Vasfed]: https://github.com/Vasfed
257
+ [@vasfed]: https://github.com/Vasfed
216
258
  [@szemek]: https://github.com/szemek
217
259
  [@mkldon]: https://github.com/mkldon
218
260
  [@dmagro]: https://github.com/dmagro
219
261
  [@danielwaterworth]: https://github.com/danielwaterworth
220
- [@Envek]: https://github.com/Envek
262
+ [@envek]: https://github.com/Envek
221
263
  [@tyleriguchi]: https://github.com/tyleriguchi
222
264
  [@lostie]: https://github.com/lostie
223
265
  [@pirj]: https://github.com/pirj
224
- [@LynxEyes]: https://github.com/LynxEyes
266
+ [@lynxeyes]: https://github.com/LynxEyes
225
267
  [@stefkin]: https://github.com/stefkin
226
268
  [@jaimerson]: https://github.com/jaimerson
227
269
  [@alexvko]: https://github.com/alexvko
@@ -102,7 +102,7 @@ module TestProf
102
102
  def quoted(val)
103
103
  if val.is_a?(Array)
104
104
  val.map { |v| quoted(v) }
105
- elsif val.is_a?(ActiveRecord::Relation::QueryAttribute)
105
+ elsif val.is_a?(ActiveModel::Attribute)
106
106
  quoted(val.value_for_database)
107
107
  else
108
108
  ActiveRecord::Base.connection.quote(val)
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_prof/factory_prof"
4
+
5
+ # A standalone Factory Prof printer which is meant to be always enabled
6
+
7
+ TestProf::FactoryProf.patch!
8
+
9
+ started_at = TestProf.now
10
+ at_exit do
11
+ TestProf::FactoryProf::Printers::NateHeckler.dump(
12
+ TestProf::FactoryProf.result, start_time: started_at
13
+ )
14
+ end
15
+
16
+ TestProf::FactoryProf.start
@@ -11,7 +11,7 @@ module TestProf::FactoryProf
11
11
  class << self
12
12
  include TestProf::Logging
13
13
 
14
- def dump(result)
14
+ def dump(result, **)
15
15
  return log(:info, "No factories detected") if result.raw_stats == {}
16
16
  report_data = {
17
17
  total_stacks: result.stacks.size,
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_prof/ext/float_duration"
4
+
5
+ module TestProf::FactoryProf
6
+ module Printers
7
+ # See https://twitter.com/nateberkopec/status/1389945187766456333
8
+ module NateHeckler # :nodoc: all
9
+ class << self
10
+ using TestProf::FloatDuration
11
+ include TestProf::Logging
12
+
13
+ def dump(result, start_time:)
14
+ return if result.raw_stats == {}
15
+
16
+ total_time = result.stats.sum { |stat| stat[:top_level_time] }
17
+ total_run_time = TestProf.now - start_time
18
+
19
+ percentage = ((total_time / total_run_time) * 100).round(2)
20
+
21
+ log :info, "Time spent in factories: #{total_time.duration} (#{percentage}% of total time)"
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,15 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "test_prof/ext/float_duration"
4
+
3
5
  module TestProf::FactoryProf
4
6
  module Printers
5
7
  module Simple # :nodoc: all
6
8
  class << self
9
+ using TestProf::FloatDuration
7
10
  include TestProf::Logging
8
11
 
9
- def dump(result)
12
+ def dump(result, start_time:)
10
13
  return log(:info, "No factories detected") if result.raw_stats == {}
11
14
  msgs = []
12
15
 
16
+ total_run_time = TestProf.now - start_time
13
17
  total_count = result.stats.sum { |stat| stat[:total_count] }
14
18
  total_top_level_count = result.stats.sum { |stat| stat[:top_level_count] }
15
19
  total_time = result.stats.sum { |stat| stat[:top_level_time] }
@@ -21,7 +25,7 @@ module TestProf::FactoryProf
21
25
 
22
26
  Total: #{total_count}
23
27
  Total top-level: #{total_top_level_count}
24
- Total time: #{format("%.4f", total_time)}s
28
+ Total time: #{total_time.duration} (out of #{total_run_time.duration})
25
29
  Total uniq factories: #{total_uniq_factories}
26
30
 
27
31
  total top-level total time time per call top-level time name
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "test_prof/factory_prof/printers/simple"
4
4
  require "test_prof/factory_prof/printers/flamegraph"
5
+ require "test_prof/factory_prof/printers/nate_heckler"
5
6
  require "test_prof/factory_prof/factory_builders/factory_bot"
6
7
  require "test_prof/factory_prof/factory_builders/fabrication"
7
8
 
@@ -14,10 +15,19 @@ module TestProf
14
15
 
15
16
  # FactoryProf configuration
16
17
  class Configuration
17
- attr_accessor :mode
18
+ attr_accessor :mode, :printer
18
19
 
19
20
  def initialize
20
21
  @mode = ENV["FPROF"] == "flamegraph" ? :flamegraph : :simple
22
+ @printer =
23
+ case ENV["FPROF"]
24
+ when "flamegraph"
25
+ Printers::Flamegraph
26
+ when "nate_heckler"
27
+ Printers::NateHeckler
28
+ else
29
+ Printers::Simple
30
+ end
21
31
  end
22
32
 
23
33
  # Whether we want to generate flamegraphs
@@ -74,7 +84,15 @@ module TestProf
74
84
 
75
85
  log :info, "FactoryProf enabled (#{config.mode} mode)"
76
86
 
87
+ patch!
88
+ end
89
+
90
+ def patch!
91
+ return if @patched
92
+
77
93
  FACTORY_BUILDERS.each(&:patch)
94
+
95
+ @patched = true
78
96
  end
79
97
 
80
98
  # Inits FactoryProf and setups at exit hook,
@@ -82,9 +100,11 @@ module TestProf
82
100
  def run
83
101
  init
84
102
 
85
- printer = config.flamegraph? ? Printers::Flamegraph : Printers::Simple
103
+ printer = config.printer
104
+
105
+ started_at = TestProf.now
86
106
 
87
- at_exit { printer.dump(result) }
107
+ at_exit { printer.dump(result, start_time: started_at) }
88
108
 
89
109
  start
90
110
  end
@@ -4,23 +4,29 @@ module TestProf
4
4
  # Helper for output printing
5
5
  module Logging
6
6
  COLORS = {
7
- info: "\e[34m", # blue
8
- warn: "\e[33m", # yellow
9
- error: "\e[31m" # red
7
+ INFO: "\e[34m", # blue
8
+ WARN: "\e[33m", # yellow
9
+ ERROR: "\e[31m" # red
10
10
  }.freeze
11
11
 
12
- def log(level, msg)
13
- TestProf.config.output.puts(build_log_msg(level, msg))
14
- end
12
+ class Formatter
13
+ def call(severity, _time, progname, msg)
14
+ colorize(severity.to_sym, "[#{progname} #{severity}] #{msg}\n")
15
+ end
15
16
 
16
- def build_log_msg(level, msg)
17
- colorize(level, "[TEST PROF #{level.to_s.upcase}] #{msg}")
18
- end
17
+ private
18
+
19
+ def colorize(level, msg)
20
+ return msg unless TestProf.config.color?
19
21
 
20
- def colorize(level, msg)
21
- return msg unless TestProf.config.color?
22
+ return msg unless COLORS.key?(level)
22
23
 
23
- "#{COLORS[level]}#{msg}\e[0m"
24
+ "#{COLORS[level]}#{msg}\e[0m"
25
+ end
26
+ end
27
+
28
+ def log(level, msg)
29
+ TestProf.config.logger.public_send(level, "TEST PROF") { msg }
24
30
  end
25
31
  end
26
32
  end
@@ -2,6 +2,22 @@
2
2
 
3
3
  require "test_prof/before_all"
4
4
 
5
+ Minitest.singleton_class.prepend(Module.new do
6
+ attr_reader :previous_klass
7
+ @previous_klass = nil
8
+
9
+ def run_one_method(klass, method_name)
10
+ return super unless klass.respond_to?(:parallelized) && klass.parallelized
11
+
12
+ if @previous_klass && @previous_klass != klass
13
+ @previous_klass.before_all_executor&.deactivate!
14
+ end
15
+ @previous_klass = klass
16
+
17
+ super
18
+ end
19
+ end)
20
+
5
21
  module TestProf
6
22
  module BeforeAll
7
23
  # Add before_all hook to Minitest: wrap all examples into a transaction and
@@ -9,13 +25,15 @@ module TestProf
9
25
  module Minitest # :nodoc: all
10
26
  class Executor
11
27
  attr_reader :active, :block, :captured_ivars, :teardown_block, :current_test_object,
12
- :setup_fixtures
28
+ :setup_fixtures, :parent
13
29
 
14
30
  alias_method :active?, :active
15
31
  alias_method :setup_fixtures?, :setup_fixtures
16
32
 
17
- def initialize(setup_fixtures: false, &block)
18
- @setup_fixtures = setup_fixtures
33
+ def initialize(setup_fixtures: false, parent: nil, &block)
34
+ @parent = parent
35
+ # Fixtures must be instantiated if any of the executors needs them
36
+ @setup_fixtures = setup_fixtures || parent&.setup_fixtures
19
37
  @block = block
20
38
  @captured_ivars = []
21
39
  end
@@ -28,7 +46,9 @@ module TestProf
28
46
  @current_test_object = test_object
29
47
 
30
48
  return restore_ivars(test_object) if active?
49
+
31
50
  @active = true
51
+
32
52
  BeforeAll.setup_fixtures(test_object) if setup_fixtures?
33
53
  BeforeAll.begin_transaction do
34
54
  capture!(test_object)
@@ -36,20 +56,20 @@ module TestProf
36
56
  end
37
57
 
38
58
  def deactivate!
59
+ return unless active
60
+
39
61
  @active = false
40
62
 
41
- current_test_object&.instance_eval(&teardown_block) if teardown_block
63
+ perform_teardown(current_test_object)
42
64
 
43
65
  @current_test_object = nil
44
66
  BeforeAll.rollback_transaction
45
67
  end
46
68
 
47
69
  def capture!(test_object)
48
- return unless block
49
-
50
70
  before_ivars = test_object.instance_variables
51
71
 
52
- test_object.instance_eval(&block)
72
+ perform_setup(test_object)
53
73
 
54
74
  (test_object.instance_variables - before_ivars).each do |ivar|
55
75
  captured_ivars << [ivar, test_object.instance_variable_get(ivar)]
@@ -64,19 +84,76 @@ module TestProf
64
84
  )
65
85
  end
66
86
  end
87
+
88
+ def perform_setup(test_object)
89
+ parent&.perform_setup(test_object)
90
+ test_object.instance_eval(&block) if block
91
+ end
92
+
93
+ def perform_teardown(test_object)
94
+ current_test_object&.instance_eval(&teardown_block) if teardown_block
95
+ parent&.perform_teardown(test_object)
96
+ end
67
97
  end
68
98
 
69
99
  class << self
70
100
  def included(base)
71
101
  base.extend ClassMethods
102
+
103
+ base.cattr_accessor :parallelized
104
+ if base.respond_to?(:parallelize_teardown)
105
+ base.parallelize_teardown do
106
+ last_klass = ::Minitest.previous_klass
107
+ if last_klass&.respond_to?(:parallelized) && last_klass&.parallelized
108
+ last_klass.before_all_executor&.deactivate!
109
+ end
110
+ end
111
+ end
112
+
113
+ if base.respond_to?(:parallelize)
114
+ base.singleton_class.prepend(Module.new do
115
+ def parallelize(workers: :number_of_processors, with: :processes)
116
+ # super.parallelize returns nil when no parallelization is set up
117
+ if super(workers: workers, with: with).nil?
118
+ return
119
+ end
120
+
121
+ case with
122
+ when :processes
123
+ self.parallelized = true
124
+ when :threads
125
+ warn "!!! before_all is not implemented for parallalization with threads and " \
126
+ "could work incorrectly"
127
+ else
128
+ warn "!!! tests are using an unknown parallelization strategy and before_all " \
129
+ "could work incorrectly"
130
+ end
131
+ end
132
+ end)
133
+ end
72
134
  end
73
135
  end
74
136
 
75
137
  module ClassMethods
76
- attr_accessor :before_all_executor
138
+ attr_writer :before_all_executor
139
+
140
+ def before_all_executor
141
+ return @before_all_executor if instance_variable_defined?(:@before_all_executor)
142
+
143
+ @before_all_executor = if superclass.respond_to?(:before_all_executor)
144
+ superclass.before_all_executor
145
+ end
146
+ end
77
147
 
78
148
  def before_all(setup_fixtures: BeforeAll.config.setup_fixtures, &block)
79
- self.before_all_executor = Executor.new(setup_fixtures: setup_fixtures, &block)
149
+ self.before_all_executor = Executor.new(
150
+ setup_fixtures: setup_fixtures,
151
+ parent: before_all_executor,
152
+ &block
153
+ )
154
+
155
+ # Do not add patches multiple times
156
+ return if before_all_executor.parent
80
157
 
81
158
  prepend(Module.new do
82
159
  def before_setup
@@ -89,13 +166,13 @@ module TestProf
89
166
  def run(*)
90
167
  super
91
168
  ensure
92
- before_all_executor&.deactivate!
169
+ before_all_executor&.deactivate! unless parallelized
93
170
  end
94
171
  end)
95
172
  end
96
173
 
97
174
  def after_all(&block)
98
- self.before_all_executor ||= Executor.new
175
+ self.before_all_executor = Executor.new(parent: before_all_executor)
99
176
  before_all_executor.teardown(&block)
100
177
  end
101
178
  end
@@ -107,7 +107,7 @@ module TestProf
107
107
  define_method(identifier) do
108
108
  # Trying to detect the context
109
109
  # Based on https://github.com/rspec/rspec-rails/commit/7cb796db064f58da7790a92e73ab906ef50b1f34
110
- if @__inspect_output.include?("before(:context)") || @__inspect_output.include?("before_all")
110
+ if /(before|after)\(:context\)/.match?(@__inspect_output) || @__inspect_output.include?("before_all")
111
111
  instance_variable_get(:"#{PREFIX}#{identifier}")
112
112
  else
113
113
  # Fallback to let definition
@@ -39,7 +39,7 @@ module TestProf
39
39
  acc << if v.nil?
40
40
  k.to_sym
41
41
  else
42
- Hash[k.to_sym, v.to_sym]
42
+ {k.to_sym => v.to_sym}
43
43
  end
44
44
  end
45
45
  end
@@ -12,7 +12,7 @@ module TestProf
12
12
 
13
13
  @data = Hash.new do |h, k|
14
14
  h[k] = {value: k, count: 0, time: 0.0}
15
- h[k].merge!(Hash[events.map { |event| [event, 0.0] }]) unless
15
+ h[k].merge!(events.map { |event| [event, 0.0] }.to_h) unless
16
16
  events.empty?
17
17
  h[k]
18
18
  end
@@ -53,11 +53,9 @@ module TestProf
53
53
  def fetch_events_data
54
54
  return {} unless @events_profiler
55
55
 
56
- Hash[
57
- @events_profiler.profilers.map do |profiler|
58
- [profiler.event, profiler.time]
59
- end
60
- ]
56
+ @events_profiler.profilers.map do |profiler|
57
+ [profiler.event, profiler.time]
58
+ end.to_h
61
59
  end
62
60
  end
63
61
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TestProf
4
- VERSION = "1.0.3"
4
+ VERSION = "1.0.7"
5
5
  end
data/lib/test_prof.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "fileutils"
4
+ require "logger"
5
+
4
6
  require "test_prof/version"
5
7
  require "test_prof/logging"
6
8
  require "test_prof/utils"
@@ -44,6 +46,13 @@ module TestProf
44
46
  defined?(Minitest)
45
47
  end
46
48
 
49
+ # Returns true if Spring is used and not disabled
50
+ def spring?
51
+ # See https://github.com/rails/spring/blob/577cf01f232bb6dbd0ade7df2df2ac209697e741/lib/spring/binstub.rb
52
+ disabled = ENV["DISABLE_SPRING"]
53
+ defined?(::Spring::Application) && (disabled.nil? || disabled.empty? || disabled == "0")
54
+ end
55
+
47
56
  # Returns the current process time
48
57
  def now
49
58
  Process.clock_gettime(Process::CLOCK_MONOTONIC)
@@ -63,7 +72,7 @@ module TestProf
63
72
  # equal to the provided value (if any).
64
73
  # Contains workaround for applications using Spring.
65
74
  def activate(env_var, val = nil)
66
- if defined?(::Spring::Application)
75
+ if spring?
67
76
  notify_spring_detected
68
77
  ::Spring.after_fork do
69
78
  activate!(env_var, val) do
@@ -130,7 +139,7 @@ module TestProf
130
139
 
131
140
  # TestProf configuration
132
141
  class Configuration
133
- attr_accessor :output, # IO to write output messages.
142
+ attr_accessor :output, # IO to write logs
134
143
  :color, # Whether to colorize output or not
135
144
  :output_dir, # Directory to store artifacts
136
145
  :timestamps, # Whether to use timestamped names for artifacts,
@@ -145,12 +154,16 @@ module TestProf
145
154
  end
146
155
 
147
156
  def color?
148
- color == true
157
+ color == true && output.is_a?(IO) && output.tty?
149
158
  end
150
159
 
151
160
  def timestamps?
152
161
  timestamps == true
153
162
  end
163
+
164
+ def logger
165
+ @logger ||= Logger.new(output, formatter: Logging::Formatter.new)
166
+ end
154
167
  end
155
168
  end
156
169
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: test-prof
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Dementyev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-30 00:00:00.000000000 Z
11
+ date: 2021-08-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -174,7 +174,9 @@ files:
174
174
  - lib/test_prof/factory_prof/factory_bot_patch.rb
175
175
  - lib/test_prof/factory_prof/factory_builders/fabrication.rb
176
176
  - lib/test_prof/factory_prof/factory_builders/factory_bot.rb
177
+ - lib/test_prof/factory_prof/nate_heckler.rb
177
178
  - lib/test_prof/factory_prof/printers/flamegraph.rb
179
+ - lib/test_prof/factory_prof/printers/nate_heckler.rb
178
180
  - lib/test_prof/factory_prof/printers/simple.rb
179
181
  - lib/test_prof/logging.rb
180
182
  - lib/test_prof/recipes/logging.rb
@@ -214,11 +216,12 @@ homepage: http://github.com/test-prof/test-prof
214
216
  licenses:
215
217
  - MIT
216
218
  metadata:
217
- bug_tracker_uri: http://github.com/test-prof/test-prof/issues
219
+ bug_tracker_uri: https://github.com/test-prof/test-prof/issues
218
220
  changelog_uri: https://github.com/test-prof/test-prof/blob/master/CHANGELOG.md
219
221
  documentation_uri: https://test-prof.evilmartians.io/
220
222
  homepage_uri: https://test-prof.evilmartians.io/
221
- source_code_uri: http://github.com/test-prof/test-prof
223
+ source_code_uri: https://github.com/test-prof/test-prof
224
+ funding_uri: https://github.com/sponsors/test-prof
222
225
  post_install_message:
223
226
  rdoc_options: []
224
227
  require_paths: