test-unit-minitest 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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