minitest 5.16.2 → 6.0.5

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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/History.rdoc +373 -1
  4. data/Manifest.txt +16 -4
  5. data/README.rdoc +48 -118
  6. data/Rakefile +17 -2
  7. data/bin/minitest +5 -0
  8. data/design_rationale.rb +21 -19
  9. data/lib/hoe/minitest.rb +4 -2
  10. data/lib/minitest/assertions.rb +142 -124
  11. data/lib/minitest/autorun.rb +3 -11
  12. data/lib/minitest/benchmark.rb +9 -12
  13. data/lib/minitest/bisect.rb +304 -0
  14. data/lib/minitest/complete.rb +56 -0
  15. data/lib/minitest/compress.rb +94 -0
  16. data/lib/minitest/error_on_warning.rb +11 -0
  17. data/lib/minitest/expectations.rb +18 -0
  18. data/lib/minitest/find_minimal_combination.rb +127 -0
  19. data/lib/minitest/hell.rb +1 -1
  20. data/lib/minitest/manual_plugins.rb +4 -0
  21. data/lib/minitest/parallel.rb +10 -8
  22. data/lib/minitest/path_expander.rb +432 -0
  23. data/lib/minitest/pride.rb +2 -2
  24. data/lib/minitest/pride_plugin.rb +17 -24
  25. data/lib/minitest/server.rb +49 -0
  26. data/lib/minitest/server_plugin.rb +88 -0
  27. data/lib/minitest/spec.rb +27 -46
  28. data/lib/minitest/sprint.rb +105 -0
  29. data/lib/minitest/sprint_plugin.rb +39 -0
  30. data/lib/minitest/test.rb +32 -52
  31. data/lib/minitest/test_task.rb +68 -42
  32. data/lib/minitest.rb +361 -215
  33. data/test/minitest/metametameta.rb +33 -19
  34. data/test/minitest/test_bisect.rb +249 -0
  35. data/test/minitest/test_find_minimal_combination.rb +138 -0
  36. data/test/minitest/test_minitest_assertions.rb +311 -173
  37. data/test/minitest/test_minitest_benchmark.rb +15 -1
  38. data/test/minitest/test_minitest_reporter.rb +148 -23
  39. data/test/minitest/test_minitest_spec.rb +157 -132
  40. data/test/minitest/test_minitest_test.rb +270 -204
  41. data/test/minitest/test_minitest_test_task.rb +18 -7
  42. data/test/minitest/test_path_expander.rb +229 -0
  43. data/test/minitest/test_server.rb +146 -0
  44. data.tar.gz.sig +2 -2
  45. metadata +97 -37
  46. metadata.gz.sig +0 -0
  47. data/.autotest +0 -34
  48. data/lib/minitest/mock.rb +0 -323
  49. data/lib/minitest/unit.rb +0 -42
  50. data/test/minitest/test_minitest_mock.rb +0 -1139
data/lib/minitest/spec.rb CHANGED
@@ -1,22 +1,15 @@
1
- require "minitest/test"
1
+ require_relative "test"
2
2
 
3
3
  class Module # :nodoc:
4
4
  def infect_an_assertion meth, new_name, dont_flip = false # :nodoc:
5
5
  block = dont_flip == :block
6
6
  dont_flip = false if block
7
- target_obj = block ? '_{obj.method}' : '_(obj)'
8
7
 
9
- # warn "%-22p -> %p %p" % [meth, new_name, dont_flip]
10
- self.class_eval <<-EOM, __FILE__, __LINE__ + 1
11
- def #{new_name} *args
12
- where = Minitest.filter_backtrace(caller).first
13
- where = where.split(/:in /, 2).first # clean up noise
14
- Kernel.warn "DEPRECATED: global use of #{new_name} from #\{where}. Use #{target_obj}.#{new_name} instead. This will fail in Minitest 6."
15
- Minitest::Expectation.new(self, Minitest::Spec.current).#{new_name}(*args)
16
- end
17
- EOM
8
+ # https://eregon.me/blog/2021/02/13/correct-delegation-in-ruby-2-27-3.html
9
+ # Drop this when we can drop ruby 2.6 (aka after rails 6.1 EOL, ~2024-06)
10
+ kw_extra = "ruby2_keywords %p" % [new_name] if respond_to? :ruby2_keywords, true
18
11
 
19
- Minitest::Expectation.class_eval <<-EOM, __FILE__, __LINE__ + 1
12
+ self.class_eval <<-EOM, __FILE__, __LINE__ + 1
20
13
  def #{new_name} *args
21
14
  raise "Calling ##{new_name} outside of test." unless ctx
22
15
  case
@@ -28,11 +21,16 @@ class Module # :nodoc:
28
21
  ctx.#{meth}(args.first, target, *args[1..-1])
29
22
  end
30
23
  end
24
+ #{kw_extra}
31
25
  EOM
32
26
  end
33
27
  end
34
28
 
35
- Minitest::Expectation = Struct.new :target, :ctx # :nodoc:
29
+ # :stopdoc:
30
+ module Minitest # fucking hell rdoc...
31
+ Expectation = Struct.new :target, :ctx
32
+ end
33
+ # :startdoc:
36
34
 
37
35
  ##
38
36
  # Kernel extensions for minitest
@@ -75,14 +73,15 @@ module Kernel
75
73
 
76
74
  def describe desc, *additional_desc, &block # :doc:
77
75
  stack = Minitest::Spec.describe_stack
78
- name = [stack.last, desc, *additional_desc].compact.join("::")
79
- sclas = stack.last || if Class === self && kind_of?(Minitest::Spec::DSL) then
80
- self
81
- else
82
- Minitest::Spec.spec_type desc, *additional_desc
83
- end
76
+ is_spec_class = Class === self && kind_of?(Minitest::Spec::DSL)
77
+ name = [stack.last, desc, *additional_desc]
78
+ name.prepend self if stack.empty? && is_spec_class
79
+ sclas =
80
+ stack.last \
81
+ || (is_spec_class && self) \
82
+ || Minitest::Spec.spec_type(desc, *additional_desc)
84
83
 
85
- cls = sclas.create name, desc
84
+ cls = sclas.create name.compact.join("::"), desc
86
85
 
87
86
  stack.push cls
88
87
  cls.class_eval(&block)
@@ -99,15 +98,6 @@ end
99
98
 
100
99
  class Minitest::Spec < Minitest::Test
101
100
 
102
- def self.current # :nodoc:
103
- Thread.current[:current_spec]
104
- end
105
-
106
- def initialize name # :nodoc:
107
- super
108
- Thread.current[:current_spec] = self
109
- end
110
-
111
101
  ##
112
102
  # Oh look! A Minitest::Spec::DSL module! Eat your heart out DHH.
113
103
 
@@ -243,7 +233,7 @@ class Minitest::Spec < Minitest::Test
243
233
  pre, post = "let '#{name}' cannot ", ". Please use another name."
244
234
  methods = Minitest::Spec.instance_methods.map(&:to_s) - %w[subject]
245
235
  raise ArgumentError, "#{pre}begin with 'test'#{post}" if
246
- name =~ /\Atest/
236
+ name.start_with? "test"
247
237
  raise ArgumentError, "#{pre}override a method in Minitest::Spec#{post}" if
248
238
  methods.include? name
249
239
 
@@ -262,7 +252,7 @@ class Minitest::Spec < Minitest::Test
262
252
  end
263
253
 
264
254
  def create name, desc # :nodoc:
265
- cls = Class.new(self) do
255
+ cls = Class.new self do
266
256
  @name = name
267
257
  @desc = desc
268
258
 
@@ -278,12 +268,11 @@ class Minitest::Spec < Minitest::Test
278
268
  defined?(@name) ? @name : super
279
269
  end
280
270
 
281
- def to_s # :nodoc:
282
- name # Can't alias due to 1.8.7, not sure why
283
- end
271
+ alias to_s name
272
+ alias inspect name
284
273
 
285
274
  attr_reader :desc # :nodoc:
286
- alias :specify :it
275
+ alias specify it
287
276
 
288
277
  ##
289
278
  # Rdoc... why are you so dumb?
@@ -303,9 +292,6 @@ class Minitest::Spec < Minitest::Test
303
292
  # straight-expectation methods (on Object) because it stores its
304
293
  # test context, bypassing our hacky use of thread-local variables.
305
294
  #
306
- # NOTE: At some point, the methods on Object will be deprecated
307
- # and then removed.
308
- #
309
295
  # It is also aliased to #value and #expect for your aesthetic
310
296
  # pleasure:
311
297
  #
@@ -319,11 +305,6 @@ class Minitest::Spec < Minitest::Test
319
305
 
320
306
  alias value _
321
307
  alias expect _
322
-
323
- def before_setup # :nodoc:
324
- super
325
- Thread.current[:current_spec] = self
326
- end
327
308
  end
328
309
 
329
310
  def self.extended obj # :nodoc:
@@ -336,8 +317,8 @@ class Minitest::Spec < Minitest::Test
336
317
  TYPES = DSL::TYPES # :nodoc:
337
318
  end
338
319
 
339
- require "minitest/expectations"
320
+ require_relative "expectations"
340
321
 
341
- class Object # :nodoc:
342
- include Minitest::Expectations unless ENV["MT_NO_EXPECTATIONS"]
322
+ class Minitest::Expectation
323
+ include Minitest::Expectations
343
324
  end
@@ -0,0 +1,105 @@
1
+ $LOAD_PATH.unshift "test", "lib"
2
+
3
+ require "simplecov" if ENV["MT_COV"] || ARGV.delete("--simplecov")
4
+ require_relative "autorun"
5
+ require_relative "path_expander"
6
+
7
+ module Minitest
8
+
9
+ ##
10
+ # Runs (Get it? It's fast!) your tests and makes it easier to rerun
11
+ # individual failures.
12
+
13
+ class Sprint
14
+ # extracted version = "1.5.0"
15
+
16
+ ##
17
+ # Process and run minitest cmdline.
18
+
19
+ def self.run args = ARGV
20
+ if args.delete("--bisect") or args.delete("-b") then
21
+ require_relative "bisect"
22
+
23
+ return Minitest::Bisect.run ARGV
24
+ end
25
+
26
+ Minitest::PathExpander.new(args).process { |f|
27
+ require "./#{f}" if File.file? f
28
+ }
29
+ end
30
+
31
+ ##
32
+ # An extra minitest reporter to output how to rerun failures in
33
+ # various styles.
34
+
35
+ class SprintReporter < AbstractReporter
36
+ ##
37
+ # The style to report, either lines or regexp. Defaults to lines.
38
+ attr_accessor :style
39
+ attr_accessor :results # :nodoc:
40
+
41
+ def initialize style = :regexp # :nodoc:
42
+ self.results = []
43
+ self.style = style
44
+ end
45
+
46
+ def record result # :nodoc:
47
+ results << result unless result.passed? or result.skipped?
48
+ end
49
+
50
+ def report # :nodoc:
51
+ return if results.empty?
52
+
53
+ puts
54
+ puts "Happy Happy Sprint List:"
55
+ puts
56
+ print_list
57
+ puts
58
+ end
59
+
60
+ def print_list # :nodoc:
61
+ case style
62
+ when :regexp
63
+ results.each do |result|
64
+ puts " minitest -n #{result.class_name}##{result.name}"
65
+ end
66
+ when :lines
67
+ files = Hash.new { |h,k| h[k] = [] }
68
+ results.each do |result|
69
+ path, line = result.source_location
70
+ path = path.delete_prefix "#{Dir.pwd}/"
71
+ files[path] << line
72
+ end
73
+
74
+ files.sort.each do |path, lines|
75
+ puts " minitest %s:%s" % [path, lines.sort.join(",")]
76
+ end
77
+ else
78
+ raise "unsupported style: %p" % [style]
79
+ end
80
+ end
81
+ end
82
+
83
+ ##
84
+ # An extra minitest reporter to output how to rerun failures using
85
+ # rake.
86
+
87
+ class RakeReporter < SprintReporter
88
+ ##
89
+ # The name of the rake task to rerun. Defaults to nil.
90
+
91
+ attr_accessor :name
92
+
93
+ def initialize name = nil # :nodoc:
94
+ super()
95
+ self.name = name
96
+ end
97
+
98
+ def print_list # :nodoc:
99
+ results.each do |result|
100
+ puts [" rake", name, "N=#{result.class_name}##{result.name}"].compact.join(" ")
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,39 @@
1
+ require_relative "../minitest"
2
+
3
+ # :stopdoc:
4
+ class OptionParser # unofficial embedded gem "makeoptparseworkwell"
5
+ def hidden(...) = define(...).tap { |sw| def sw.summarize(*) = nil }
6
+ def deprecate(from, to) = hidden(from) { abort "#{from} is deprecated. Use #{to}." }
7
+ def topdict(name) = name.length > 1 ? top.long : top.short
8
+ def alias(from, to) = (dict = topdict(from) and dict[to] = dict[from])
9
+ end unless OptionParser.method_defined? :hidden
10
+ # :startdoc:
11
+
12
+ module Minitest # :nodoc:
13
+ def self.plugin_sprint_options opts, options # :nodoc:
14
+ opts.on "--rake [TASK]", "Report how to re-run failures with rake." do |task|
15
+ options[:sprint] = :rake
16
+ options[:rake_task] = task
17
+ end
18
+
19
+ opts.deprecate "--binstub", "--rerun"
20
+
21
+ sprint_styles = %w[rake lines names binstub]
22
+
23
+ opts.on "-r", "--rerun [STYLE]", sprint_styles, "Report how to re-run failures using STYLE (names, lines)." do |style|
24
+ options[:sprint] = (style || :lines).to_sym
25
+ end
26
+ end
27
+
28
+ def self.plugin_sprint_init options
29
+ require_relative "sprint"
30
+ case options[:sprint]
31
+ when :rake then
32
+ self.reporter << Minitest::Sprint::RakeReporter.new(options[:rake_task])
33
+ when :binstub, :names then
34
+ self.reporter << Minitest::Sprint::SprintReporter.new
35
+ when :lines then
36
+ self.reporter << Minitest::Sprint::SprintReporter.new(:lines)
37
+ end
38
+ end
39
+ end
data/lib/minitest/test.rb CHANGED
@@ -1,4 +1,4 @@
1
- require "minitest" unless defined? Minitest::Runnable
1
+ require_relative "../minitest" unless defined? Minitest::Runnable
2
2
 
3
3
  module Minitest
4
4
  ##
@@ -8,16 +8,16 @@ module Minitest
8
8
  # See Minitest::Assertions
9
9
 
10
10
  class Test < Runnable
11
- require "minitest/assertions"
12
- include Minitest::Assertions
11
+ require_relative "assertions"
13
12
  include Minitest::Reportable
14
-
15
- def class_name # :nodoc:
16
- self.class.name # for Minitest::Reportable
17
- end
13
+ include Minitest::Assertions
18
14
 
19
15
  PASSTHROUGH_EXCEPTIONS = [NoMemoryError, SignalException, SystemExit] # :nodoc:
20
16
 
17
+ SETUP_METHODS = %w[ before_setup setup after_setup ] # :nodoc:
18
+
19
+ TEARDOWN_METHODS = %w[ before_teardown teardown after_teardown ] # :nodoc:
20
+
21
21
  # :stopdoc:
22
22
  class << self; attr_accessor :io_lock; end
23
23
  self.io_lock = Mutex.new
@@ -30,8 +30,8 @@ module Minitest
30
30
 
31
31
  def self.i_suck_and_my_tests_are_order_dependent!
32
32
  class << self
33
- undef_method :test_order if method_defined? :test_order
34
- define_method :test_order do :alpha end
33
+ undef_method :run_order if method_defined? :run_order
34
+ define_method :run_order do :alpha end
35
35
  end
36
36
  end
37
37
 
@@ -48,60 +48,52 @@ module Minitest
48
48
  end
49
49
 
50
50
  ##
51
- # Call this at the top of your tests when you want to run your
52
- # tests in parallel. In doing so, you're admitting that you rule
53
- # and your tests are awesome.
51
+ # Call this at the top of your tests (inside the +Minitest::Test+
52
+ # subclass or +describe+ block) when you want to run your tests in
53
+ # parallel. In doing so, you're admitting that you rule and your
54
+ # tests are awesome.
54
55
 
55
56
  def self.parallelize_me!
57
+ return unless Minitest.parallel_executor
56
58
  include Minitest::Parallel::Test
57
59
  extend Minitest::Parallel::Test::ClassMethods
58
60
  end
59
61
 
60
62
  ##
61
63
  # Returns all instance methods starting with "test_". Based on
62
- # #test_order, the methods are either sorted, randomized
64
+ # #run_order, the methods are either sorted, randomized
63
65
  # (default), or run in parallel.
64
66
 
65
67
  def self.runnable_methods
66
68
  methods = methods_matching(/^test_/)
67
69
 
68
- case self.test_order
70
+ case self.run_order
69
71
  when :random, :parallel then
70
72
  srand Minitest.seed
71
73
  methods.sort.shuffle
72
74
  when :alpha, :sorted then
73
75
  methods.sort
74
76
  else
75
- raise "Unknown test_order: #{self.test_order.inspect}"
77
+ raise "Unknown_order: %p" % [self.run_order]
76
78
  end
77
79
  end
78
80
 
79
- ##
80
- # Defines the order to run tests (:random by default). Override
81
- # this or use a convenience method to change it for your tests.
82
-
83
- def self.test_order
84
- :random
85
- end
86
-
87
- TEARDOWN_METHODS = %w[ before_teardown teardown after_teardown ] # :nodoc:
88
-
89
81
  ##
90
82
  # Runs a single test with setup/teardown hooks.
91
83
 
92
84
  def run
93
- with_info_handler do
94
- time_it do
95
- capture_exceptions do
96
- before_setup; setup; after_setup
97
-
98
- self.send self.name
85
+ time_it do
86
+ capture_exceptions do
87
+ SETUP_METHODS.each do |hook|
88
+ self.send hook
99
89
  end
100
90
 
101
- TEARDOWN_METHODS.each do |hook|
102
- capture_exceptions do
103
- self.send hook
104
- end
91
+ self.send self.name
92
+ end
93
+
94
+ TEARDOWN_METHODS.each do |hook|
95
+ capture_exceptions do
96
+ self.send hook
105
97
  end
106
98
  end
107
99
  end
@@ -145,7 +137,7 @@ module Minitest
145
137
  # end
146
138
  # end
147
139
  #
148
- # class MiniTest::Test
140
+ # class Minitest::Test
149
141
  # include MyMinitestPlugin
150
142
  # end
151
143
 
@@ -204,22 +196,22 @@ module Minitest
204
196
  def sanitize_exception e # :nodoc:
205
197
  Marshal.dump e
206
198
  e # good: use as-is
207
- rescue TypeError
199
+ rescue
208
200
  neuter_exception e
209
201
  end
210
202
 
211
- def neuter_exception e
203
+ def neuter_exception e # :nodoc:
212
204
  bt = e.backtrace
213
205
  msg = e.message.dup
214
206
 
215
207
  new_exception e.class, msg, bt # e.class can be a problem...
216
- rescue TypeError
208
+ rescue
217
209
  msg.prepend "Neutered Exception #{e.class}: "
218
210
 
219
211
  new_exception RuntimeError, msg, bt, true # but if this raises, we die
220
212
  end
221
213
 
222
- def new_exception klass, msg, bt, kill = false
214
+ def new_exception klass, msg, bt, kill = false # :nodoc:
223
215
  ne = klass.new msg
224
216
  ne.set_backtrace bt
225
217
 
@@ -233,20 +225,8 @@ module Minitest
233
225
  ne
234
226
  end
235
227
 
236
- def with_info_handler &block # :nodoc:
237
- t0 = Minitest.clock_time
238
-
239
- handler = lambda do
240
- warn "\nCurrent: %s#%s %.2fs" % [self.class, self.name, Minitest.clock_time - t0]
241
- end
242
-
243
- self.class.on_signal ::Minitest.info_signal, handler, &block
244
- end
245
-
246
228
  include LifecycleHooks
247
229
  include Guard
248
230
  extend Guard
249
231
  end # Test
250
232
  end
251
-
252
- require "minitest/unit" unless defined?(MiniTest) # compatibility layer only
@@ -1,6 +1,12 @@
1
1
  require "shellwords"
2
2
  require "rbconfig"
3
- require "rake/tasklib"
3
+
4
+ begin
5
+ require "rake/tasklib"
6
+ rescue LoadError => e
7
+ warn e.message
8
+ return
9
+ end
4
10
 
5
11
  module Minitest # :nodoc:
6
12
 
@@ -29,13 +35,25 @@ module Minitest # :nodoc:
29
35
  # end
30
36
  #
31
37
  # Customize the name and only run unit tests.
38
+ #
39
+ # NOTE: To hook this task up to the default, make it a dependency:
40
+ #
41
+ # task default: :unit
32
42
 
33
43
  class TestTask < Rake::TaskLib
34
44
  WINDOWS = RbConfig::CONFIG["host_os"] =~ /mswin|mingw/ # :nodoc:
35
45
 
36
46
  ##
37
- # Create several test-oriented tasks under +name+. Takes an
38
- # optional block to customize variables.
47
+ # Create several test-oriented tasks under +name+ (default:
48
+ # "test"). Takes an optional block to customize variables.
49
+ # Examples:
50
+ #
51
+ # Minitest::TestTask.create # named "test", all defaults
52
+ #
53
+ # Minitest::TestTask.create do |t|
54
+ # t.warning = false # my tests are noisy
55
+ # t.framework = %(require_relative "./test/helper.rb")
56
+ # end
39
57
 
40
58
  def self.create name = :test, &block
41
59
  task = new name
@@ -59,9 +77,18 @@ module Minitest # :nodoc:
59
77
 
60
78
  ##
61
79
  # The code to load the framework. Defaults to requiring
62
- # minitest/autorun...
80
+ # minitest/autorun.
81
+ #
82
+ # If you have a test helper file that requires minitest/autorun
83
+ # and anything else your project standardizes on, then you'll
84
+ # probably want to change this to:
85
+ #
86
+ # Minitest::TestTask.create do |t|
87
+ # t.framework = %(require_relative "./test/helper.rb")
88
+ # end
63
89
  #
64
- # Why do I have this as an option?
90
+ # or something similar. NOTE: if you do this, then helper must
91
+ # require "minitest/autorun" at the top to start the tests.
65
92
 
66
93
  attr_accessor :framework
67
94
 
@@ -90,6 +117,11 @@ module Minitest # :nodoc:
90
117
 
91
118
  ##
92
119
  # Optional: Additional ruby to run before the test framework is loaded.
120
+ # Example:
121
+ #
122
+ # Minitest::TestTask.create "test:cov" do |t|
123
+ # t.test_prelude = %(require "simplecov")
124
+ # end
93
125
 
94
126
  attr_accessor :test_prelude
95
127
 
@@ -110,7 +142,7 @@ module Minitest # :nodoc:
110
142
  self.test_globs = ["test/**/test_*.rb",
111
143
  "test/**/*_test.rb"]
112
144
  self.test_prelude = nil
113
- self.verbose = Rake.application.options.trace
145
+ self.verbose = Rake.application.options.trace || Rake.verbose == true
114
146
  self.warning = true
115
147
  end
116
148
 
@@ -136,20 +168,18 @@ module Minitest # :nodoc:
136
168
  ENV["TESTOPTS"]
137
169
  warn "FILTER is deprecated in Minitest::TestTask. Use A instead" if
138
170
  ENV["FILTER"]
139
- warn "N is deprecated in Minitest::TestTask. Use MT_CPU instead" if
140
- ENV["N"] && ENV["N"].to_i > 0
141
171
 
142
172
  lib_extras = (ENV["MT_LIB_EXTRAS"] || "").split File::PATH_SEPARATOR
143
- self.libs[0,0] = lib_extras
173
+ self.libs[0, 0] = lib_extras
144
174
 
145
- extra_args << "-n" << ENV["N"] if ENV["N"]
146
- extra_args << "-e" << ENV["X"] if ENV["X"]
175
+ extra_args << "-i" << ENV["N"] if ENV["N"]
176
+ extra_args << "-i" << ENV["I"] if ENV["I"]
177
+ extra_args << "-x" << ENV["X"] if ENV["X"]
178
+ extra_args << "-x" << ENV["E"] if ENV["E"]
147
179
  extra_args.concat Shellwords.split(ENV["TESTOPTS"]) if ENV["TESTOPTS"]
148
180
  extra_args.concat Shellwords.split(ENV["FILTER"]) if ENV["FILTER"]
149
181
  extra_args.concat Shellwords.split(ENV["A"]) if ENV["A"]
150
182
 
151
- ENV.delete "N" if ENV["N"]
152
-
153
183
  # TODO? RUBY_DEBUG = ENV["RUBY_DEBUG"]
154
184
  # TODO? ENV["RUBY_FLAGS"]
155
185
 
@@ -157,11 +187,14 @@ module Minitest # :nodoc:
157
187
  end
158
188
 
159
189
  def define # :nodoc:
160
- default_tasks = []
161
-
162
- desc "Run the test suite. Use N, X, A, and TESTOPTS to add flags/args."
190
+ desc "Run the test suite. Use I, X, and A to add flags/args."
163
191
  task name do
164
- ruby make_test_cmd, verbose:verbose
192
+ ruby make_test_cmd, verbose: verbose
193
+ end
194
+
195
+ desc "Run the test suite, filtering for 'FU' in name (focused units?)."
196
+ task "#{name}:fu" do
197
+ ruby make_test_cmd(include:"/FU/"), verbose: verbose
165
198
  end
166
199
 
167
200
  desc "Print out the test command. Good for profiling and other tools."
@@ -175,14 +208,14 @@ module Minitest # :nodoc:
175
208
 
176
209
  # 3 seems to be the magic number... (tho not by that much)
177
210
  bad, good, n = {}, [], (ENV.delete("K") || 3).to_i
178
- file = ENV.delete("F")
211
+ file = ENV.delete "F"
179
212
  times = {}
180
213
 
181
214
  tt0 = Time.now
182
215
 
183
216
  n.threads_do tests.sort do |path|
184
217
  t0 = Time.now
185
- output = `#{Gem.ruby} #{make_test_cmd path} 2>&1`
218
+ output = `#{Gem.ruby} #{make_test_cmd path:path} 2>&1`
186
219
  t1 = Time.now - t0
187
220
 
188
221
  times[path] = t1
@@ -236,24 +269,21 @@ module Minitest # :nodoc:
236
269
 
237
270
  task "#{name}:deps" => "#{name}:isolated" # now just an alias
238
271
 
239
- desc "Show bottom 25 tests wrt time."
272
+ desc "Run the test suite and report the slowest 25 tests."
240
273
  task "#{name}:slow" do
241
- sh ["rake #{name} TESTOPTS=-v",
274
+ sh ["rake #{name} A=-v",
242
275
  "egrep '#test_.* s = .'",
243
276
  "sort -n -k2 -t=",
244
277
  "tail -25"].join " | "
245
278
  end
246
-
247
- default_tasks << name
248
-
249
- desc "Run the default task(s)."
250
- task :default => default_tasks
251
279
  end
252
280
 
253
281
  ##
254
282
  # Generate the test command-line.
255
283
 
256
- def make_test_cmd globs = test_globs
284
+ def make_test_cmd **option
285
+ globs = option[:path] || test_globs
286
+
257
287
  tests = []
258
288
  tests.concat Dir[*globs].sort.shuffle # TODO: SEED -> srand first?
259
289
  tests.map! { |f| %(require "#{f}") }
@@ -264,12 +294,14 @@ module Minitest # :nodoc:
264
294
  runner.concat tests
265
295
  runner = runner.join "; "
266
296
 
297
+ extra_args << "-i" << option[:include] if option[:include]
298
+
267
299
  args = []
268
- args << "-I#{libs.join(File::PATH_SEPARATOR)}" unless libs.empty?
300
+ args << "-I#{libs.join File::PATH_SEPARATOR}" unless libs.empty?
269
301
  args << "-w" if warning
270
- args << '-e'
302
+ args << "-e"
271
303
  args << "'#{runner}'"
272
- args << '--'
304
+ args << "--"
273
305
  args << extra_args.map(&:shellescape)
274
306
 
275
307
  args.join " "
@@ -277,24 +309,18 @@ module Minitest # :nodoc:
277
309
  end
278
310
  end
279
311
 
280
- class Work < Queue
281
- def initialize jobs = []
282
- super()
283
-
284
- jobs.each do |job|
285
- self << job
286
- end
287
-
312
+ class Work < Queue # :nodoc:
313
+ def initialize jobs # :nodoc:
314
+ super
288
315
  close
289
316
  end
290
317
  end
291
318
 
292
- class Integer
293
- def threads_do(jobs) # :nodoc:
294
- require "thread"
319
+ class Integer # :nodoc:
320
+ def threads_do jobs # :nodoc:
295
321
  q = Work.new jobs
296
322
 
297
- self.times.map {
323
+ Array.new(self) {
298
324
  Thread.new do
299
325
  while job = q.pop # go until quit value
300
326
  yield job