test-unit-minitest 0.9.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.
@@ -0,0 +1,403 @@
1
+ require 'minitest/unit'
2
+ require 'pp'
3
+
4
+ module Test
5
+ module Unit
6
+ module Assertions
7
+ include MiniTest::Assertions
8
+
9
+ def mu_pp(obj) #:nodoc:
10
+ obj.pretty_inspect.chomp
11
+ end
12
+
13
+ MINI_DIR = File.join(File.dirname(File.dirname(File.expand_path(__FILE__))), "minitest") #:nodoc:
14
+
15
+ # :call-seq:
16
+ # assert(test, [failure_message])
17
+ #
18
+ #Tests if +test+ is true.
19
+ #
20
+ #+msg+ may be a String or a Proc. If +msg+ is a String, it will be used
21
+ #as the failure message. Otherwise, the result of calling +msg+ will be
22
+ #used as the message if the assertion fails.
23
+ #
24
+ #If no +msg+ is given, a default message will be used.
25
+ #
26
+ # assert(false, "This was expected to be true")
27
+ def assert(test, *msgs)
28
+ case msg = msgs.first
29
+ when String, Proc
30
+ when nil
31
+ msgs.shift
32
+ else
33
+ bt = caller.reject { |s| s.start_with?(MINI_DIR) }
34
+ raise ArgumentError, "assertion message must be String or Proc, but #{msg.class} was given.", bt
35
+ end unless msgs.empty?
36
+ super
37
+ end
38
+
39
+ # :call-seq:
40
+ # assert_block( failure_message = nil )
41
+ #
42
+ #Tests the result of the given block. If the block does not return true,
43
+ #the assertion will fail. The optional +failure_message+ argument is the same as in
44
+ #Assertions#assert.
45
+ #
46
+ # assert_block do
47
+ # [1, 2, 3].any? { |num| num < 1 }
48
+ # end
49
+ def assert_block(*msgs)
50
+ assert yield, *msgs
51
+ end
52
+
53
+ # :call-seq:
54
+ # assert_raise( *args, &block )
55
+ #
56
+ #Tests if the given block raises an exception. Acceptable exception
57
+ #types may be given as optional arguments. If the last argument is a
58
+ #String, it will be used as the error message.
59
+ #
60
+ # assert_raise do #Fails, no Exceptions are raised
61
+ # end
62
+ #
63
+ # assert_raise NameError do
64
+ # puts x #Raises NameError, so assertion succeeds
65
+ # end
66
+ def assert_raise(*args, &b)
67
+ assert_raises(*args, &b)
68
+ end
69
+
70
+ # :call-seq:
71
+ # assert_raise_with_message(exception, expected, msg = nil, &block)
72
+ #
73
+ #Tests if the given block raises an exception with the expected
74
+ #message.
75
+ #
76
+ # assert_raise_with_message(RuntimeError, "foo") do
77
+ # nil #Fails, no Exceptions are raised
78
+ # end
79
+ #
80
+ # assert_raise_with_message(RuntimeError, "foo") do
81
+ # raise ArgumentError, "foo" #Fails, different Exception is raised
82
+ # end
83
+ #
84
+ # assert_raise_with_message(RuntimeError, "foo") do
85
+ # raise "bar" #Fails, RuntimeError is raised but the message differs
86
+ # end
87
+ #
88
+ # assert_raise_with_message(RuntimeError, "foo") do
89
+ # raise "foo" #Raises RuntimeError with the message, so assertion succeeds
90
+ # end
91
+ def assert_raise_with_message(exception, expected, msg = nil, &block)
92
+ case expected
93
+ when String
94
+ assert = :assert_equal
95
+ when Regexp
96
+ assert = :assert_match
97
+ else
98
+ raise TypeError, "Expected #{expected.inspect} to be a kind of String or Regexp, not #{expected.class}"
99
+ end
100
+
101
+ ex = assert_raise(exception, *msg) {yield}
102
+ msg = message(msg, "") {"Expected Exception(#{exception}) was raised, but the message doesn't match"}
103
+
104
+ if assert == :assert_equal
105
+ assert_equal(expected, ex.message, msg)
106
+ else
107
+ msg = message(msg) { "Expected #{mu_pp expected} to match #{mu_pp ex.message}" }
108
+ assert expected =~ ex.message, msg
109
+ block.binding.eval("proc{|_|$~=_}").call($~)
110
+ end
111
+ ex
112
+ end
113
+
114
+ # :call-seq:
115
+ # assert_nothing_raised( *args, &block )
116
+ #
117
+ #If any exceptions are given as arguments, the assertion will
118
+ #fail if one of those exceptions are raised. Otherwise, the test fails
119
+ #if any exceptions are raised.
120
+ #
121
+ #The final argument may be a failure message.
122
+ #
123
+ # assert_nothing_raised RuntimeError do
124
+ # raise Exception #Assertion passes, Exception is not a RuntimeError
125
+ # end
126
+ #
127
+ # assert_nothing_raised do
128
+ # raise Exception #Assertion fails
129
+ # end
130
+ def assert_nothing_raised(*args)
131
+ self._assertions += 1
132
+ if Module === args.last
133
+ msg = nil
134
+ else
135
+ msg = args.pop
136
+ end
137
+ begin
138
+ line = __LINE__; yield
139
+ rescue MiniTest::Skip
140
+ raise
141
+ rescue Exception => e
142
+ bt = e.backtrace
143
+ as = e.instance_of?(MiniTest::Assertion)
144
+ if as
145
+ ans = /\A#{Regexp.quote(__FILE__)}:#{line}:in /o
146
+ bt.reject! {|ln| ans =~ ln}
147
+ end
148
+ if ((args.empty? && !as) ||
149
+ args.any? {|a| a.instance_of?(Module) ? e.is_a?(a) : e.class == a })
150
+ msg = message(msg) { "Exception raised:\n<#{mu_pp(e)}>" }
151
+ raise MiniTest::Assertion, msg.call, bt
152
+ else
153
+ raise
154
+ end
155
+ end
156
+ nil
157
+ end
158
+
159
+ # :call-seq:
160
+ # assert_nothing_thrown( failure_message = nil, &block )
161
+ #
162
+ #Fails if the given block uses a call to Kernel#throw, and
163
+ #returns the result of the block otherwise.
164
+ #
165
+ #An optional failure message may be provided as the final argument.
166
+ #
167
+ # assert_nothing_thrown "Something was thrown!" do
168
+ # throw :problem?
169
+ # end
170
+ def assert_nothing_thrown(msg=nil)
171
+ begin
172
+ ret = yield
173
+ rescue ArgumentError => error
174
+ raise error if /\Auncaught throw (.+)\z/m !~ error.message
175
+ msg = message(msg) { "<#{$1}> was thrown when nothing was expected" }
176
+ flunk(msg)
177
+ end
178
+ assert(true, "Expected nothing to be thrown")
179
+ ret
180
+ end
181
+
182
+ # :call-seq:
183
+ # assert_throw( tag, failure_message = nil, &block )
184
+ #
185
+ #Fails unless the given block throws +tag+, returns the caught
186
+ #value otherwise.
187
+ #
188
+ #An optional failure message may be provided as the final argument.
189
+ #
190
+ # tag = Object.new
191
+ # assert_throw(tag, "#{tag} was not thrown!") do
192
+ # throw tag
193
+ # end
194
+ def assert_throw(tag, msg = nil)
195
+ catch(tag) do
196
+ yield(tag)
197
+ assert(false, message(msg) {"Expected #{mu_pp(tag)} to have been thrown"})
198
+ end
199
+ end
200
+
201
+ # :call-seq:
202
+ # assert_equal( expected, actual, failure_message = nil )
203
+ #
204
+ #Tests if +expected+ is equal to +actual+.
205
+ #
206
+ #An optional failure message may be provided as the final argument.
207
+ def assert_equal(exp, act, msg = nil)
208
+ msg = message(msg) {
209
+ exp_str = mu_pp(exp)
210
+ act_str = mu_pp(act)
211
+ exp_comment = ''
212
+ act_comment = ''
213
+ if exp_str == act_str
214
+ if (exp.is_a?(String) && act.is_a?(String)) ||
215
+ (exp.is_a?(Regexp) && act.is_a?(Regexp))
216
+ exp_comment = " (#{exp.encoding})"
217
+ act_comment = " (#{act.encoding})"
218
+ elsif exp.is_a?(Float) && act.is_a?(Float)
219
+ exp_str = "%\#.#{Float::DIG+2}g" % exp
220
+ act_str = "%\#.#{Float::DIG+2}g" % act
221
+ elsif exp.is_a?(Time) && act.is_a?(Time)
222
+ if exp.subsec * 1000_000_000 == exp.nsec
223
+ exp_comment = " (#{exp.nsec}[ns])"
224
+ else
225
+ exp_comment = " (subsec=#{exp.subsec})"
226
+ end
227
+ if act.subsec * 1000_000_000 == act.nsec
228
+ act_comment = " (#{act.nsec}[ns])"
229
+ else
230
+ act_comment = " (subsec=#{act.subsec})"
231
+ end
232
+ elsif exp.class != act.class
233
+ # a subclass of Range, for example.
234
+ exp_comment = " (#{exp.class})"
235
+ act_comment = " (#{act.class})"
236
+ end
237
+ elsif !Encoding.compatible?(exp_str, act_str)
238
+ if exp.is_a?(String) && act.is_a?(String)
239
+ exp_str = exp.dump
240
+ act_str = act.dump
241
+ exp_comment = " (#{exp.encoding})"
242
+ act_comment = " (#{act.encoding})"
243
+ else
244
+ exp_str = exp_str.dump
245
+ act_str = act_str.dump
246
+ end
247
+ end
248
+ "<#{exp_str}>#{exp_comment} expected but was\n<#{act_str}>#{act_comment}"
249
+ }
250
+ assert(exp == act, msg)
251
+ end
252
+
253
+ # :call-seq:
254
+ # assert_not_nil( expression, failure_message = nil )
255
+ #
256
+ #Tests if +expression+ is not nil.
257
+ #
258
+ #An optional failure message may be provided as the final argument.
259
+ def assert_not_nil(exp, msg=nil)
260
+ msg = message(msg) { "<#{mu_pp(exp)}> expected to not be nil" }
261
+ assert(!exp.nil?, msg)
262
+ end
263
+
264
+ # :call-seq:
265
+ # assert_not_equal( expected, actual, failure_message = nil )
266
+ #
267
+ #Tests if +expected+ is not equal to +actual+.
268
+ #
269
+ #An optional failure message may be provided as the final argument.
270
+ def assert_not_equal(exp, act, msg=nil)
271
+ msg = message(msg) { "<#{mu_pp(exp)}> expected to be != to\n<#{mu_pp(act)}>" }
272
+ assert(exp != act, msg)
273
+ end
274
+
275
+ # :call-seq:
276
+ # assert_no_match( regexp, string, failure_message = nil )
277
+ #
278
+ #Tests if the given Regexp does not match a given String.
279
+ #
280
+ #An optional failure message may be provided as the final argument.
281
+ def assert_no_match(regexp, string, msg=nil)
282
+ assert_instance_of(Regexp, regexp, "The first argument to assert_no_match should be a Regexp.")
283
+ self._assertions -= 1
284
+ msg = message(msg) { "<#{mu_pp(regexp)}> expected to not match\n<#{mu_pp(string)}>" }
285
+ assert(regexp !~ string, msg)
286
+ end
287
+
288
+ # :call-seq:
289
+ # assert_not_same( expected, actual, failure_message = nil )
290
+ #
291
+ #Tests if +expected+ is not the same object as +actual+.
292
+ #This test uses Object#equal? to test equality.
293
+ #
294
+ #An optional failure message may be provided as the final argument.
295
+ #
296
+ # assert_not_same("x", "x") #Succeeds
297
+ def assert_not_same(expected, actual, message="")
298
+ msg = message(msg) { build_message(message, <<EOT, expected, expected.__id__, actual, actual.__id__) }
299
+ <?>
300
+ with id <?> expected to not be equal\\? to
301
+ <?>
302
+ with id <?>.
303
+ EOT
304
+ assert(!actual.equal?(expected), msg)
305
+ end
306
+
307
+ # :call-seq:
308
+ # assert_respond_to( object, method, failure_message = nil )
309
+ #
310
+ #Tests if the given Object responds to +method+.
311
+ #
312
+ #An optional failure message may be provided as the final argument.
313
+ #
314
+ # assert_respond_to("hello", :reverse) #Succeeds
315
+ # assert_respond_to("hello", :does_not_exist) #Fails
316
+ def assert_respond_to obj, (meth, priv), msg = nil
317
+ if priv
318
+ msg = message(msg) {
319
+ "Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}#{" privately" if priv}"
320
+ }
321
+ return assert obj.respond_to?(meth, priv), msg
322
+ end
323
+ #get rid of overcounting
324
+ super if !caller[0].rindex(MINI_DIR, 0) || !obj.respond_to?(meth)
325
+ end
326
+
327
+ # :call-seq:
328
+ # assert_send( +send_array+, failure_message = nil )
329
+ #
330
+ # Passes if the method send returns a true value.
331
+ #
332
+ # +send_array+ is composed of:
333
+ # * A receiver
334
+ # * A method
335
+ # * Arguments to the method
336
+ #
337
+ # Example:
338
+ # assert_send(["Hello world", :include?, "Hello"]) # -> pass
339
+ # assert_send(["Hello world", :include?, "Goodbye"]) # -> fail
340
+ def assert_send send_ary, m = nil
341
+ recv, msg, *args = send_ary
342
+ m = message(m) {
343
+ if args.empty?
344
+ argsstr = ""
345
+ else
346
+ (argsstr = mu_pp(args)).sub!(/\A\[(.*)\]\z/m, '(\1)')
347
+ end
348
+ "Expected #{mu_pp(recv)}.#{msg}#{argsstr} to return true"
349
+ }
350
+ assert recv.__send__(msg, *args), m
351
+ end
352
+
353
+ # :call-seq:
354
+ # assert_not_send( +send_array+, failure_message = nil )
355
+ #
356
+ # Passes if the method send doesn't return a true value.
357
+ #
358
+ # +send_array+ is composed of:
359
+ # * A receiver
360
+ # * A method
361
+ # * Arguments to the method
362
+ #
363
+ # Example:
364
+ # assert_not_send([[1, 2], :member?, 1]) # -> fail
365
+ # assert_not_send([[1, 2], :member?, 4]) # -> pass
366
+ def assert_not_send send_ary, m = nil
367
+ recv, msg, *args = send_ary
368
+ m = message(m) {
369
+ if args.empty?
370
+ argsstr = ""
371
+ else
372
+ (argsstr = mu_pp(args)).sub!(/\A\[(.*)\]\z/m, '(\1)')
373
+ end
374
+ "Expected #{mu_pp(recv)}.#{msg}#{argsstr} to return false"
375
+ }
376
+ assert !recv.__send__(msg, *args), m
377
+ end
378
+
379
+ ms = instance_methods(true).map {|sym| sym.to_s }
380
+ ms.grep(/\Arefute_/) do |m|
381
+ mname = ('assert_not_' << m.to_s[/.*?_(.*)/, 1])
382
+ alias_method(mname, m) unless ms.include? mname
383
+ end
384
+ alias assert_include assert_includes
385
+ alias assert_not_include assert_not_includes
386
+
387
+ def build_message(head, template=nil, *arguments) #:nodoc:
388
+ template &&= template.chomp
389
+ template.gsub(/\G((?:[^\\]|\\.)*?)(\\)?\?/) { $1 + ($2 ? "?" : mu_pp(arguments.shift)) }
390
+ end
391
+
392
+ def message(msg = nil, *args, &default) # :nodoc:
393
+ if Proc === msg
394
+ super(nil, *args) do
395
+ [msg.call, (default.call if default)].compact.reject(&:empty?).join(".\n")
396
+ end
397
+ else
398
+ super
399
+ end
400
+ end
401
+ end
402
+ end
403
+ end
@@ -0,0 +1,189 @@
1
+ require 'test/unit'
2
+
3
+ module Test
4
+ module Unit
5
+ class Worker < Runner # :nodoc:
6
+ class << self
7
+ undef autorun
8
+ end
9
+
10
+ alias orig_run_suite mini_run_suite
11
+ undef _run_suite
12
+ undef _run_suites
13
+ undef run
14
+
15
+ def increment_io(orig) # :nodoc:
16
+ *rest, io = 32.times.inject([orig.dup]){|ios, | ios << ios.last.dup }
17
+ rest.each(&:close)
18
+ io
19
+ end
20
+
21
+ def _run_suites(suites, type) # :nodoc:
22
+ suites.map do |suite|
23
+ _run_suite(suite, type)
24
+ end
25
+ end
26
+
27
+ def _run_suite(suite, type) # :nodoc:
28
+ @partial_report = []
29
+ orig_testout = MiniTest::Unit.output
30
+ i,o = IO.pipe
31
+
32
+ MiniTest::Unit.output = o
33
+ orig_stdin, orig_stdout = $stdin, $stdout
34
+
35
+ th = Thread.new do
36
+ begin
37
+ while buf = (self.verbose ? i.gets : i.read(5))
38
+ _report "p", buf
39
+ end
40
+ rescue IOError
41
+ rescue Errno::EPIPE
42
+ end
43
+ end
44
+
45
+ e, f, s = @errors, @failures, @skips
46
+
47
+ begin
48
+ result = orig_run_suite(suite, type)
49
+ rescue Interrupt
50
+ @need_exit = true
51
+ result = [nil,nil]
52
+ end
53
+
54
+ MiniTest::Unit.output = orig_testout
55
+ $stdin = orig_stdin
56
+ $stdout = orig_stdout
57
+
58
+ o.close
59
+ begin
60
+ th.join
61
+ rescue IOError
62
+ raise unless ["stream closed","closed stream"].include? $!.message
63
+ end
64
+ i.close
65
+
66
+ result << @partial_report
67
+ @partial_report = nil
68
+ result << [@errors-e,@failures-f,@skips-s]
69
+ result << ($: - @old_loadpath)
70
+ result << suite.name
71
+
72
+ begin
73
+ _report "done", Marshal.dump(result)
74
+ rescue Errno::EPIPE; end
75
+ return result
76
+ ensure
77
+ MiniTest::Unit.output = orig_stdout
78
+ $stdin = orig_stdin
79
+ $stdout = orig_stdout
80
+ o.close if o && !o.closed?
81
+ i.close if i && !i.closed?
82
+ end
83
+
84
+ def run(args = []) # :nodoc:
85
+ process_args args
86
+ @@stop_auto_run = true
87
+ @opts = @options.dup
88
+ @need_exit = false
89
+
90
+ @old_loadpath = []
91
+ begin
92
+ begin
93
+ @stdout = increment_io(STDOUT)
94
+ @stdin = increment_io(STDIN)
95
+ rescue
96
+ exit 2
97
+ end
98
+ exit 2 unless @stdout && @stdin
99
+
100
+ @stdout.sync = true
101
+ _report "ready!"
102
+ while buf = @stdin.gets
103
+ case buf.chomp
104
+ when /^loadpath (.+?)$/
105
+ @old_loadpath = $:.dup
106
+ $:.push(*Marshal.load($1.unpack("m")[0].force_encoding("ASCII-8BIT"))).uniq!
107
+ when /^run (.+?) (.+?)$/
108
+ _report "okay"
109
+
110
+ @options = @opts.dup
111
+ suites = MiniTest::Unit::TestCase.test_suites
112
+
113
+ begin
114
+ require $1
115
+ rescue LoadError
116
+ _report "after", Marshal.dump([$1, ProxyError.new($!)])
117
+ _report "ready"
118
+ next
119
+ end
120
+ _run_suites MiniTest::Unit::TestCase.test_suites-suites, $2.to_sym
121
+
122
+ if @need_exit
123
+ begin
124
+ _report "bye"
125
+ rescue Errno::EPIPE; end
126
+ exit
127
+ else
128
+ _report "ready"
129
+ end
130
+ when /^quit$/
131
+ begin
132
+ _report "bye"
133
+ rescue Errno::EPIPE; end
134
+ exit
135
+ end
136
+ end
137
+ rescue Errno::EPIPE
138
+ rescue Exception => e
139
+ begin
140
+ trace = e.backtrace
141
+ err = ["#{trace.shift}: #{e.message} (#{e.class})"] + trace.map{|t| t.prepend("\t") }
142
+
143
+ _report "bye", Marshal.dump(err.join("\n"))
144
+ rescue Errno::EPIPE;end
145
+ exit
146
+ ensure
147
+ @stdin.close if @stdin
148
+ @stdout.close if @stdout
149
+ end
150
+ end
151
+
152
+ def _report(res, *args) # :nodoc:
153
+ res = "#{res} #{args.pack("m0")}" unless args.empty?
154
+ @stdout.puts(res)
155
+ end
156
+
157
+ def puke(klass, meth, e) # :nodoc:
158
+ if e.is_a?(MiniTest::Skip)
159
+ new_e = MiniTest::Skip.new(e.message)
160
+ new_e.set_backtrace(e.backtrace)
161
+ e = new_e
162
+ end
163
+ @partial_report << [klass.name, meth, e.is_a?(MiniTest::Assertion) ? e : ProxyError.new(e)]
164
+ super
165
+ end
166
+ end
167
+ end
168
+ end
169
+
170
+ if $0 == __FILE__
171
+ module Test
172
+ module Unit
173
+ class TestCase < MiniTest::Unit::TestCase # :nodoc: all
174
+ undef on_parallel_worker?
175
+ def on_parallel_worker?
176
+ true
177
+ end
178
+ end
179
+ end
180
+ end
181
+ require 'rubygems'
182
+ module Gem # :nodoc:
183
+ end
184
+ class Gem::TestCase < MiniTest::Unit::TestCase # :nodoc:
185
+ @@project_dir = File.expand_path('../../../..', __FILE__)
186
+ end
187
+
188
+ Test::Unit::Worker.new.run(ARGV)
189
+ end