minitest 5.14.4 → 5.25.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.
@@ -0,0 +1,94 @@
1
+ module Minitest
2
+ ##
3
+ # Compresses backtraces.
4
+
5
+ module Compress
6
+
7
+ ##
8
+ # Takes a backtrace (array of strings) and compresses repeating
9
+ # cycles in it to make it more readable.
10
+
11
+ def compress orig
12
+ ary = orig
13
+
14
+ eswo = ->(a, n, off) { # each_slice_with_offset
15
+ if off.zero? then
16
+ a.each_slice n
17
+ else
18
+ # [ ...off... [...n...] [...n...] ... ]
19
+ front, back = a.take(off), a.drop(off)
20
+ [front].chain back.each_slice n
21
+ end
22
+ }
23
+
24
+ 3.times do # maybe don't use loop do here?
25
+ index = ary # [ a b c b c b c d ]
26
+ .size
27
+ .times # 0...size
28
+ .group_by { |i| ary[i] } # { a: [0] b: [1 3 5], c: [2 4 6], d: [7] }
29
+
30
+ order = index
31
+ .reject { |k, v| v.size == 1 } # { b: [1 3 5], c: [2 4 6] }
32
+ .sort_by { |k, a1| ### sort by max dist + min offset
33
+ d = a1.each_cons(2).sum { |a2, b| b-a2 }
34
+ [-d, a1.first]
35
+ } # b: [1 3 5] c: [2 4 6]
36
+
37
+ ranges = order
38
+ .map { |k, a1| # [[1..2 3..4] [2..3 4..5]]
39
+ a1
40
+ .each_cons(2)
41
+ .map { |a2, b| a2..b-1 }
42
+ }
43
+
44
+ big_ranges = ranges
45
+ .flat_map { |a| # [1..2 3..4 2..3 4..5]
46
+ a.sort_by { |r| [-r.size, r.first] }.first 5
47
+ }
48
+ .first(100)
49
+
50
+ culprits = big_ranges
51
+ .map { |r|
52
+ eswo[ary, r.size, r.begin] # [o1 s1 s1 s2 s2]
53
+ .chunk_while { |a, b| a == b } # [[o1] [s1 s1] [s2 s2]]
54
+ .map { |a| [a.size, a.first] } # [[1 o1] [2 s1] [2 s2]]
55
+ }
56
+ .select { |chunks|
57
+ chunks.any? { |a| a.first > 1 } # compressed anything?
58
+ }
59
+
60
+ min = culprits
61
+ .min_by { |a| a.flatten.size } # most compressed
62
+
63
+ break unless min
64
+
65
+ ary = min.flat_map { |(n, lines)|
66
+ if n > 1 then
67
+ [[n, compress(lines)]] # [o1 [2 s1] [2 s2]]
68
+ else
69
+ lines
70
+ end
71
+ }
72
+ end
73
+
74
+ format = ->(lines) {
75
+ lines.flat_map { |line|
76
+ case line
77
+ when Array then
78
+ n, lines = line
79
+ lines = format[lines]
80
+ [
81
+ " +->> #{n} cycles of #{lines.size} lines:",
82
+ *lines.map { |s| " | #{s}" },
83
+ " +-<<",
84
+ ]
85
+ else
86
+ line
87
+ end
88
+ }
89
+ }
90
+
91
+ format[ary]
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,11 @@
1
+ module Minitest
2
+
3
+ module ErrorOnWarning # :nodoc:
4
+ def warn message, category: nil
5
+ message = "[#{category}] #{message}" if category
6
+ raise UnexpectedWarning, message
7
+ end
8
+ end
9
+
10
+ ::Warning.singleton_class.prepend ErrorOnWarning
11
+ end
@@ -124,6 +124,15 @@ module Minitest::Expectations
124
124
 
125
125
  infect_an_assertion :assert_output, :must_output, :block
126
126
 
127
+ ##
128
+ # See Minitest::Assertions#assert_pattern
129
+ #
130
+ # _ { ... }.must_pattern_match [...]
131
+ #
132
+ # :method: must_pattern_match
133
+
134
+ infect_an_assertion :assert_pattern, :must_pattern_match, :block
135
+
127
136
  ##
128
137
  # See Minitest::Assertions#assert_raises
129
138
  #
@@ -283,6 +292,15 @@ module Minitest::Expectations
283
292
 
284
293
  infect_an_assertion :refute_operator, :wont_be, :reverse
285
294
 
295
+ ##
296
+ # See Minitest::Assertions#refute_pattern
297
+ #
298
+ # _ { ... }.wont_pattern_match [...]
299
+ #
300
+ # :method: wont_pattern_match
301
+
302
+ infect_an_assertion :refute_pattern, :wont_pattern_match, :block
303
+
286
304
  ##
287
305
  # See Minitest::Assertions#refute_respond_to
288
306
  #
@@ -0,0 +1,16 @@
1
+ require "minitest"
2
+
3
+ ARGV << "--no-plugins"
4
+
5
+ module Minitest
6
+ ##
7
+ # Manually load plugins by name.
8
+
9
+ def self.load *names
10
+ names.each do |name|
11
+ require "minitest/#{name}_plugin"
12
+
13
+ self.extensions << name.to_s
14
+ end
15
+ end
16
+ end
data/lib/minitest/mock.rb CHANGED
@@ -8,9 +8,9 @@ module Minitest # :nodoc:
8
8
  # All mock objects are an instance of Mock
9
9
 
10
10
  class Mock
11
- alias :__respond_to? :respond_to?
11
+ alias __respond_to? respond_to?
12
12
 
13
- overridden_methods = %w[
13
+ overridden_methods = %i[
14
14
  ===
15
15
  class
16
16
  inspect
@@ -23,18 +23,31 @@ module Minitest # :nodoc:
23
23
  to_s
24
24
  ]
25
25
 
26
+ overridden_methods << :singleton_method_added if defined?(::DEBUGGER__)
27
+
26
28
  instance_methods.each do |m|
27
- undef_method m unless overridden_methods.include?(m.to_s) || m =~ /^__/
29
+ undef_method m unless overridden_methods.include?(m) || m =~ /^__/
28
30
  end
29
31
 
30
32
  overridden_methods.map(&:to_sym).each do |method_id|
31
- define_method method_id do |*args, &b|
33
+ old_w, $-w = $-w, nil
34
+ define_method method_id do |*args, **kwargs, &b|
32
35
  if @expected_calls.key? method_id then
33
- method_missing(method_id, *args, &b)
36
+ if kwargs.empty? then # FIX: drop this after 2.7 dead
37
+ method_missing(method_id, *args, &b)
38
+ else
39
+ method_missing(method_id, *args, **kwargs, &b)
40
+ end
34
41
  else
35
- super(*args, &b)
42
+ if kwargs.empty? then # FIX: drop this after 2.7 dead
43
+ super(*args, &b)
44
+ else
45
+ super(*args, **kwargs, &b)
46
+ end
36
47
  end
37
48
  end
49
+ ensure
50
+ $-w = old_w
38
51
  end
39
52
 
40
53
  def initialize delegator = nil # :nodoc:
@@ -43,9 +56,11 @@ module Minitest # :nodoc:
43
56
  @actual_calls = Hash.new { |calls, name| calls[name] = [] }
44
57
  end
45
58
 
59
+ @@KW_WARNED = false # :nodoc:
60
+
46
61
  ##
47
- # Expect that method +name+ is called, optionally with +args+ or a
48
- # +blk+, and returns +retval+.
62
+ # Expect that method +name+ is called, optionally with +args+ (and
63
+ # +kwargs+ or a +blk+), and returns +retval+.
49
64
  #
50
65
  # @mock.expect(:meaning_of_life, 42)
51
66
  # @mock.meaning_of_life # => 42
@@ -78,15 +93,31 @@ module Minitest # :nodoc:
78
93
  # @mock.ordinal_increment # => raises MockExpectationError "No more expects available for :ordinal_increment"
79
94
  #
80
95
 
81
- def expect name, retval, args = [], &blk
96
+ def expect name, retval, args = [], **kwargs, &blk
82
97
  name = name.to_sym
83
98
 
84
- if block_given?
99
+ if blk then
85
100
  raise ArgumentError, "args ignored when block given" unless args.empty?
101
+ raise ArgumentError, "kwargs ignored when block given" unless kwargs.empty?
86
102
  @expected_calls[name] << { :retval => retval, :block => blk }
87
103
  else
88
104
  raise ArgumentError, "args must be an array" unless Array === args
89
- @expected_calls[name] << { :retval => retval, :args => args }
105
+
106
+ if ENV["MT_KWARGS_HAC\K"] && (Hash === args.last ||
107
+ Hash == args.last) then
108
+ if kwargs.empty? then
109
+ kwargs = args.pop
110
+ else
111
+ unless @@KW_WARNED then
112
+ from = caller(1..1).first
113
+ warn "Using MT_KWARGS_HAC\K yet passing kwargs. From #{from}"
114
+ @@KW_WARNED = true
115
+ end
116
+ end
117
+ end
118
+
119
+ @expected_calls[name] <<
120
+ { :retval => retval, :args => args, :kwargs => kwargs }
90
121
  end
91
122
  self
92
123
  end
@@ -94,7 +125,13 @@ module Minitest # :nodoc:
94
125
  def __call name, data # :nodoc:
95
126
  case data
96
127
  when Hash then
97
- "#{name}(#{data[:args].inspect[1..-2]}) => #{data[:retval].inspect}"
128
+ args = data[:args].inspect[1..-2]
129
+ kwargs = data[:kwargs]
130
+ if kwargs && !kwargs.empty? then
131
+ args << ", " unless args.empty?
132
+ args << kwargs.inspect[1..-2]
133
+ end
134
+ "#{name}(#{args}) => #{data[:retval].inspect}"
98
135
  else
99
136
  data.map { |d| __call name, d }.join ", "
100
137
  end
@@ -107,18 +144,22 @@ module Minitest # :nodoc:
107
144
 
108
145
  def verify
109
146
  @expected_calls.each do |name, expected|
110
- actual = @actual_calls.fetch(name, nil)
111
- raise MockExpectationError, "expected #{__call name, expected[0]}" unless actual
112
- raise MockExpectationError, "expected #{__call name, expected[actual.size]}, got [#{__call name, actual}]" if
147
+ actual = @actual_calls.fetch name, nil # defaults to []
148
+ raise MockExpectationError, "Expected #{__call name, expected[0]}" unless actual
149
+ raise MockExpectationError, "Expected #{__call name, expected[actual.size]}, got [#{__call name, actual}]" if
113
150
  actual.size < expected.size
114
151
  end
115
152
  true
116
153
  end
117
154
 
118
- def method_missing sym, *args, &block # :nodoc:
119
- unless @expected_calls.key?(sym) then
155
+ def method_missing sym, *args, **kwargs, &block # :nodoc:
156
+ unless @expected_calls.key? sym then
120
157
  if @delegator && @delegator.respond_to?(sym)
121
- return @delegator.public_send(sym, *args, &block)
158
+ if kwargs.empty? then # FIX: drop this after 2.7 dead
159
+ return @delegator.public_send(sym, *args, &block)
160
+ else
161
+ return @delegator.public_send(sym, *args, **kwargs, &block)
162
+ end
122
163
  else
123
164
  raise NoMethodError, "unmocked method %p, expected one of %p" %
124
165
  [sym, @expected_calls.keys.sort_by(&:to_s)]
@@ -129,41 +170,69 @@ module Minitest # :nodoc:
129
170
  expected_call = @expected_calls[sym][index]
130
171
 
131
172
  unless expected_call then
132
- raise MockExpectationError, "No more expects available for %p: %p" %
133
- [sym, args]
173
+ raise MockExpectationError, "No more expects available for %p: %p %p" %
174
+ [sym, args, kwargs]
134
175
  end
135
176
 
136
- expected_args, retval, val_block =
137
- expected_call.values_at(:args, :retval, :block)
177
+ expected_args, expected_kwargs, retval, val_block =
178
+ expected_call.values_at :args, :kwargs, :retval, :block
179
+
180
+ expected_kwargs = kwargs.to_h { |ak, av| [ak, Object] } if
181
+ Hash == expected_kwargs
138
182
 
139
183
  if val_block then
140
184
  # keep "verify" happy
141
185
  @actual_calls[sym] << expected_call
142
186
 
143
- raise MockExpectationError, "mocked method %p failed block w/ %p" %
144
- [sym, args] unless val_block.call(*args, &block)
187
+ raise MockExpectationError, "mocked method %p failed block w/ %p %p" %
188
+ [sym, args, kwargs] unless val_block.call(*args, **kwargs, &block)
145
189
 
146
190
  return retval
147
191
  end
148
192
 
149
193
  if expected_args.size != args.size then
150
- raise ArgumentError, "mocked method %p expects %d arguments, got %d" %
151
- [sym, expected_args.size, args.size]
194
+ raise ArgumentError, "mocked method %p expects %d arguments, got %p" %
195
+ [sym, expected_args.size, args]
196
+ end
197
+
198
+ if expected_kwargs.size != kwargs.size then
199
+ raise ArgumentError, "mocked method %p expects %d keyword arguments, got %p" %
200
+ [sym, expected_kwargs.size, kwargs]
152
201
  end
153
202
 
154
- zipped_args = expected_args.zip(args)
203
+ zipped_args = expected_args.zip args
155
204
  fully_matched = zipped_args.all? { |mod, a|
156
205
  mod === a or mod == a
157
206
  }
158
207
 
159
208
  unless fully_matched then
160
- raise MockExpectationError, "mocked method %p called with unexpected arguments %p" %
161
- [sym, args]
209
+ fmt = "mocked method %p called with unexpected arguments %p"
210
+ raise MockExpectationError, fmt % [sym, args]
211
+ end
212
+
213
+ unless expected_kwargs.keys.sort == kwargs.keys.sort then
214
+ fmt = "mocked method %p called with unexpected keywords %p vs %p"
215
+ raise MockExpectationError, fmt % [sym, expected_kwargs.keys, kwargs.keys]
216
+ end
217
+
218
+ zipped_kwargs = expected_kwargs.to_h { |ek, ev|
219
+ av = kwargs[ek]
220
+ [ek, [ev, av]]
221
+ }
222
+
223
+ fully_matched = zipped_kwargs.all? { |ek, (ev, av)|
224
+ ev === av or ev == av
225
+ }
226
+
227
+ unless fully_matched then
228
+ fmt = "mocked method %p called with unexpected keyword arguments %p vs %p"
229
+ raise MockExpectationError, fmt % [sym, expected_kwargs, kwargs]
162
230
  end
163
231
 
164
232
  @actual_calls[sym] << {
165
233
  :retval => retval,
166
- :args => zipped_args.map! { |mod, a| mod === a ? mod : a },
234
+ :args => zipped_args.map { |e, a| e === a ? e : a },
235
+ :kwargs => zipped_kwargs.to_h { |k, (e, a)| [k, e === a ? e : a] },
167
236
  }
168
237
 
169
238
  retval
@@ -172,20 +241,35 @@ module Minitest # :nodoc:
172
241
  def respond_to? sym, include_private = false # :nodoc:
173
242
  return true if @expected_calls.key? sym.to_sym
174
243
  return true if @delegator && @delegator.respond_to?(sym, include_private)
175
- __respond_to?(sym, include_private)
244
+ __respond_to? sym, include_private
176
245
  end
177
246
  end
178
247
  end
179
248
 
180
249
  module Minitest::Assertions
181
250
  ##
182
- # Assert that the mock verifies correctly.
251
+ # Assert that the mock verifies correctly and fail if not.
183
252
 
184
- def assert_mock mock
253
+ def assert_mock mock, msg = nil
185
254
  assert mock.verify
255
+ rescue MockExpectationError => e
256
+ msg = message(msg) { e.message }
257
+ flunk msg
186
258
  end
187
259
  end
188
260
 
261
+ module Minitest::Expectations
262
+ ##
263
+ # See Minitest::Assertions#assert_mock.
264
+ #
265
+ # _(collection).must_verify
266
+ #
267
+ # :method: must_verify
268
+
269
+ infect_an_assertion :assert_mock, :must_verify, :unary if
270
+ defined?(infect_an_assertion)
271
+ end
272
+
189
273
  ##
190
274
  # Object extensions for Minitest::Mock.
191
275
 
@@ -211,31 +295,50 @@ class Object
211
295
  # NOTE: keyword args in callables are NOT checked for correctness
212
296
  # against the existing method. Too many edge cases to be worth it.
213
297
 
214
- def stub name, val_or_callable, *block_args
298
+ def stub name, val_or_callable, *block_args, **block_kwargs, &block
215
299
  new_name = "__minitest_stub__#{name}"
216
300
 
217
301
  metaclass = class << self; self; end
218
302
 
219
303
  if respond_to? name and not methods.map(&:to_s).include? name.to_s then
220
- metaclass.send :define_method, name do |*args|
221
- super(*args)
304
+ metaclass.send :define_method, name do |*args, **kwargs|
305
+ super(*args, **kwargs)
222
306
  end
223
307
  end
224
308
 
225
309
  metaclass.send :alias_method, new_name, name
226
310
 
227
- metaclass.send :define_method, name do |*args, &blk|
228
- if val_or_callable.respond_to? :call then
229
- val_or_callable.call(*args, &blk)
230
- else
231
- blk.call(*block_args) if blk
232
- val_or_callable
311
+ if ENV["MT_KWARGS_HAC\K"] then
312
+ metaclass.send :define_method, name do |*args, &blk|
313
+ if val_or_callable.respond_to? :call then
314
+ val_or_callable.call(*args, &blk)
315
+ else
316
+ blk.call(*block_args, **block_kwargs) if blk
317
+ val_or_callable
318
+ end
319
+ end
320
+ else
321
+ metaclass.send :define_method, name do |*args, **kwargs, &blk|
322
+ if val_or_callable.respond_to? :call then
323
+ if kwargs.empty? then # FIX: drop this after 2.7 dead
324
+ val_or_callable.call(*args, &blk)
325
+ else
326
+ val_or_callable.call(*args, **kwargs, &blk)
327
+ end
328
+ else
329
+ if blk then
330
+ if block_kwargs.empty? then # FIX: drop this after 2.7 dead
331
+ blk.call(*block_args)
332
+ else
333
+ blk.call(*block_args, **block_kwargs)
334
+ end
335
+ end
336
+ val_or_callable
337
+ end
233
338
  end
234
339
  end
235
340
 
236
- metaclass.send(:ruby2_keywords, name) if metaclass.respond_to?(:ruby2_keywords, true)
237
-
238
- yield self
341
+ block[self]
239
342
  ensure
240
343
  metaclass.send :undef_method, name
241
344
  metaclass.send :alias_method, name, new_name
@@ -1,5 +1,5 @@
1
1
  module Minitest
2
- module Parallel #:nodoc:
2
+ module Parallel # :nodoc:
3
3
 
4
4
  ##
5
5
  # The engine used to run multiple tests in parallel.
@@ -16,7 +16,7 @@ module Minitest
16
16
 
17
17
  def initialize size
18
18
  @size = size
19
- @queue = Queue.new
19
+ @queue = Thread::Queue.new
20
20
  @pool = nil
21
21
  end
22
22
 
@@ -24,10 +24,10 @@ module Minitest
24
24
  # Start the executor
25
25
 
26
26
  def start
27
- @pool = size.times.map {
28
- Thread.new(@queue) do |queue|
27
+ @pool = Array.new(size) {
28
+ Thread.new @queue do |queue|
29
29
  Thread.current.abort_on_exception = true
30
- while (job = queue.pop)
30
+ while job = queue.pop do
31
31
  klass, method, reporter = job
32
32
  reporter.synchronize { reporter.prerecord klass, method }
33
33
  result = Minitest.run_one_method klass, method
@@ -8,13 +8,13 @@ module Minitest
8
8
  end
9
9
 
10
10
  def self.plugin_pride_init options # :nodoc:
11
- if PrideIO.pride? then
12
- klass = ENV["TERM"] =~ /^xterm|-256color$/ ? PrideLOL : PrideIO
13
- io = klass.new options[:io]
11
+ return unless PrideIO.pride?
14
12
 
15
- self.reporter.reporters.grep(Minitest::Reporter).each do |rep|
16
- rep.io = io if rep.io.tty?
17
- end
13
+ klass = ENV["TERM"] =~ /^xterm|-(?:256color|direct)$/ ? PrideLOL : PrideIO
14
+ io = klass.new options[:io]
15
+
16
+ self.reporter.reporters.grep(Minitest::Reporter).each do |rep|
17
+ rep.io = io if rep.io.tty?
18
18
  end
19
19
  end
20
20
 
@@ -48,7 +48,7 @@ module Minitest
48
48
  def initialize io # :nodoc:
49
49
  @io = io
50
50
  # stolen from /System/Library/Perl/5.10.0/Term/ANSIColor.pm
51
- # also reference http://en.wikipedia.org/wiki/ANSI_escape_code
51
+ # also reference https://en.wikipedia.org/wiki/ANSI_escape_code
52
52
  @colors ||= (31..36).to_a
53
53
  @size = @colors.size
54
54
  @index = 0
@@ -59,12 +59,10 @@ module Minitest
59
59
 
60
60
  def print o
61
61
  case o
62
- when "." then
62
+ when ".", "S" then
63
63
  io.print pride o
64
64
  when "E", "F" then
65
65
  io.print "#{ESC}41m#{ESC}37m#{o}#{NND}"
66
- when "S" then
67
- io.print pride o
68
66
  else
69
67
  io.print o
70
68
  end
@@ -72,11 +70,9 @@ module Minitest
72
70
 
73
71
  def puts *o # :nodoc:
74
72
  o.map! { |s|
75
- s.to_s.sub(/Finished/) {
73
+ s.to_s.sub("Finished") {
76
74
  @index = 0
77
- "Fabulous run".split(//).map { |c|
78
- pride(c)
79
- }.join
75
+ "Fabulous run".chars.map { |c| pride(c) }.join
80
76
  }
81
77
  }
82
78
 
@@ -113,19 +109,16 @@ module Minitest
113
109
  #
114
110
  # plot (3*sin(x)+3), (3*sin(x+2*pi/3)+3), (3*sin(x+4*pi/3)+3)
115
111
 
116
- # 6 has wide pretty gradients. 3 == lolcat, about half the width
117
- @colors = (0...(6 * 7)).map { |n|
118
- n *= 1.0 / 6
112
+ @colors = Array.new(6 * 7) { |n|
113
+ n *= 1.0 / 3
119
114
  r = (3 * Math.sin(n ) + 3).to_i
120
- g = (3 * Math.sin(n + 2 * PI_3) + 3).to_i
121
- b = (3 * Math.sin(n + 4 * PI_3) + 3).to_i
122
-
123
- # Then we take rgb and encode them in a single number using base 6.
124
- # For some mysterious reason, we add 16... to clear the bottom 4 bits?
125
- # Yes... they're ugly.
115
+ g = (3 * Math.sin(n + 4 * PI_3) + 3).to_i
116
+ b = (3 * Math.sin(n + 2 * PI_3) + 3).to_i
126
117
 
118
+ # Then we take rgb and encode them in a single number using
119
+ # base 6, shifted by 16 for the base 16 ansi colors.
127
120
  36 * r + 6 * g + b + 16
128
- }
121
+ }.rotate(4) # puts "red" first
129
122
 
130
123
  super
131
124
  end
data/lib/minitest/spec.rb CHANGED
@@ -4,15 +4,21 @@ 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
+
9
+ # https://eregon.me/blog/2021/02/13/correct-delegation-in-ruby-2-27-3.html
10
+ # Drop this when we can drop ruby 2.6 (aka after rails 6.1 EOL, ~2024-06)
11
+ kw_extra = "ruby2_keywords %p" % [new_name] if respond_to? :ruby2_keywords, true
7
12
 
8
13
  # warn "%-22p -> %p %p" % [meth, new_name, dont_flip]
9
14
  self.class_eval <<-EOM, __FILE__, __LINE__ + 1
10
15
  def #{new_name} *args
11
16
  where = Minitest.filter_backtrace(caller).first
12
17
  where = where.split(/:in /, 2).first # clean up noise
13
- warn "DEPRECATED: global use of #{new_name} from #\{where}. Use _(obj).#{new_name} instead. This will fail in Minitest 6."
18
+ Kernel.warn "DEPRECATED: global use of #{new_name} from #\{where}. Use #{target_obj}.#{new_name} instead. This will fail in Minitest 6."
14
19
  Minitest::Expectation.new(self, Minitest::Spec.current).#{new_name}(*args)
15
20
  end
21
+ #{kw_extra}
16
22
  EOM
17
23
 
18
24
  Minitest::Expectation.class_eval <<-EOM, __FILE__, __LINE__ + 1
@@ -27,6 +33,7 @@ class Module # :nodoc:
27
33
  ctx.#{meth}(args.first, target, *args[1..-1])
28
34
  end
29
35
  end
36
+ #{kw_extra}
30
37
  EOM
31
38
  end
32
39
  end
@@ -65,7 +72,7 @@ module Kernel
65
72
  #
66
73
  # For some suggestions on how to improve your specs, try:
67
74
  #
68
- # http://betterspecs.org
75
+ # https://betterspecs.org
69
76
  #
70
77
  # but do note that several items there are debatable or specific to
71
78
  # rspec.
@@ -74,14 +81,15 @@ module Kernel
74
81
 
75
82
  def describe desc, *additional_desc, &block # :doc:
76
83
  stack = Minitest::Spec.describe_stack
77
- name = [stack.last, desc, *additional_desc].compact.join("::")
78
- sclas = stack.last || if Class === self && kind_of?(Minitest::Spec::DSL) then
79
- self
80
- else
81
- Minitest::Spec.spec_type desc, *additional_desc
82
- end
84
+ is_spec_class = Class === self && kind_of?(Minitest::Spec::DSL)
85
+ name = [stack.last, desc, *additional_desc]
86
+ name.prepend self if stack.empty? && is_spec_class
87
+ sclas =
88
+ stack.last \
89
+ || (is_spec_class && self) \
90
+ || Minitest::Spec.spec_type(desc, *additional_desc)
83
91
 
84
- cls = sclas.create name, desc
92
+ cls = sclas.create name.compact.join("::"), desc
85
93
 
86
94
  stack.push cls
87
95
  cls.class_eval(&block)
@@ -242,7 +250,7 @@ class Minitest::Spec < Minitest::Test
242
250
  pre, post = "let '#{name}' cannot ", ". Please use another name."
243
251
  methods = Minitest::Spec.instance_methods.map(&:to_s) - %w[subject]
244
252
  raise ArgumentError, "#{pre}begin with 'test'#{post}" if
245
- name =~ /\Atest/
253
+ name.start_with? "test"
246
254
  raise ArgumentError, "#{pre}override a method in Minitest::Spec#{post}" if
247
255
  methods.include? name
248
256
 
@@ -261,7 +269,7 @@ class Minitest::Spec < Minitest::Test
261
269
  end
262
270
 
263
271
  def create name, desc # :nodoc:
264
- cls = Class.new(self) do
272
+ cls = Class.new self do
265
273
  @name = name
266
274
  @desc = desc
267
275
 
@@ -282,7 +290,7 @@ class Minitest::Spec < Minitest::Test
282
290
  end
283
291
 
284
292
  attr_reader :desc # :nodoc:
285
- alias :specify :it
293
+ alias specify it
286
294
 
287
295
  ##
288
296
  # Rdoc... why are you so dumb?