benchmarker 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +6 -0
- data/benchmarker.gemspec +66 -0
- data/examples/bench_loop.rb +51 -0
- data/examples/bench_require.rb +34 -0
- data/setup.rb +1585 -0
- data/test/benchmarker_test.rb +694 -0
- data/test/oktest.rb +825 -0
- metadata +94 -0
data/test/oktest.rb
ADDED
@@ -0,0 +1,825 @@
|
|
1
|
+
###
|
2
|
+
### $Release: $
|
3
|
+
### $Copyright: copyright(c) 2010 kuwata-lab.com all rights reserved $
|
4
|
+
### $License: MIT License $
|
5
|
+
###
|
6
|
+
|
7
|
+
module Oktest
|
8
|
+
|
9
|
+
DIFF = ENV['DIFF'] || File.file?('/usr/bin/diff')
|
10
|
+
|
11
|
+
def self.DIFF=(command)
|
12
|
+
remove_const(:DIFF)
|
13
|
+
const_set(:DIFF, command)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.diff(actual, expected)
|
17
|
+
## actual and expected should be different
|
18
|
+
return nil if actual == expected
|
19
|
+
## both actual and expected should be String
|
20
|
+
return nil unless actual.is_a?(String) && expected.is_a?(String)
|
21
|
+
## either actual or expected should contain "\n"
|
22
|
+
return nil unless actual.index("\n") || expected.index("\n")
|
23
|
+
## diff command
|
24
|
+
command = Oktest::DIFF
|
25
|
+
return nil unless command
|
26
|
+
command = 'diff -u' if command == true
|
27
|
+
## diff
|
28
|
+
require 'tempfile' unless defined?(Tempfile)
|
29
|
+
output = nil
|
30
|
+
#Tempfile.open('actual') do |af| # af.path file is not removed. why?
|
31
|
+
# af.write(actual); af.flush()
|
32
|
+
# Tempfile.open('expected') do |ef|
|
33
|
+
# ef.write(expected); ef.flush()
|
34
|
+
# #output = `#{command} #{ef.path} #{af.path}`
|
35
|
+
# output = IO.popen(cmd="#{command} #{ef.path} #{af.path}") {|io| io.read }
|
36
|
+
# end
|
37
|
+
#end
|
38
|
+
af = ef = nil
|
39
|
+
begin
|
40
|
+
af = Tempfile.open('actual') ; af.write(actual) ; af.flush
|
41
|
+
ef = Tempfile.open('expected') ; ef.write(expected) ; ef.flush
|
42
|
+
#output = `#{command} #{ef.path} #{af.path}`
|
43
|
+
output = IO.popen("#{command} #{ef.path} #{af.path}") {|io| io.read() }
|
44
|
+
ensure
|
45
|
+
af.close if ef
|
46
|
+
ef.close if ef
|
47
|
+
end
|
48
|
+
return output.sub(/\A.*?\n.*?\n/, "--- expected\n+++ actual\n")
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
class AssertionFailed < Exception
|
53
|
+
attr_accessor :diff
|
54
|
+
end
|
55
|
+
|
56
|
+
ASSERTION_FAILED = AssertionFailed
|
57
|
+
|
58
|
+
|
59
|
+
class AssertionObject
|
60
|
+
|
61
|
+
attr_reader :actual, :negative
|
62
|
+
|
63
|
+
def initialize(this, actual, negative=false)
|
64
|
+
@this = this
|
65
|
+
@actual = actual
|
66
|
+
@negative = negative
|
67
|
+
end
|
68
|
+
|
69
|
+
def ==(expected)
|
70
|
+
begin
|
71
|
+
do_assert(@actual == expected, expected, '==', '!=')
|
72
|
+
rescue AssertionFailed => ex
|
73
|
+
ex.diff = Oktest.diff(@actual, expected) if @actual != expected
|
74
|
+
raise ex
|
75
|
+
rescue ASSERTION_FAILED => ex
|
76
|
+
diff = Oktest.diff(@actual, expected) if @actual != expected
|
77
|
+
ex.message << "\n" << diff.chomp() if diff && ! diff.empty?
|
78
|
+
raise ex
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
if Object.new.respond_to?(:'!=')
|
83
|
+
eval <<-'END'
|
84
|
+
def !=(expected)
|
85
|
+
do_assert(@actual == expected, expected, '!=', '==')
|
86
|
+
end
|
87
|
+
END
|
88
|
+
end
|
89
|
+
|
90
|
+
def >(expected)
|
91
|
+
do_assert(@actual > expected, expected, '>', '<=')
|
92
|
+
end
|
93
|
+
|
94
|
+
def <(expected)
|
95
|
+
do_assert(@actual < expected, expected, '<', '>=')
|
96
|
+
end
|
97
|
+
|
98
|
+
def >=(expected)
|
99
|
+
do_assert(@actual >= expected, expected, '>=', '<')
|
100
|
+
end
|
101
|
+
|
102
|
+
def <=(expected)
|
103
|
+
do_assert(@actual <= expected, expected, '<=', '>')
|
104
|
+
end
|
105
|
+
|
106
|
+
def ===(expected)
|
107
|
+
do_assert(@actual === expected, expected, '===', '!==')
|
108
|
+
end
|
109
|
+
|
110
|
+
def =~(expected)
|
111
|
+
do_assert(@actual =~ expected, expected, '=~', '!~')
|
112
|
+
end
|
113
|
+
|
114
|
+
def in_delta?(expected, delta)
|
115
|
+
flag = expected - delta <= @actual && @actual <= expected + delta
|
116
|
+
check2(flag) { "(#{(expected - delta).inspect} <= #{@actual.inspect} <= #{(expected + delta).inspect})" }
|
117
|
+
end
|
118
|
+
|
119
|
+
def file?
|
120
|
+
check2(File.file?(@actual)) { "File.file?(#{@actual.inspect})" }
|
121
|
+
end
|
122
|
+
|
123
|
+
def dir?
|
124
|
+
check2(File.directory?(@actual)) { "File.directory?(#{@actual.inspect})" }
|
125
|
+
end
|
126
|
+
|
127
|
+
def exist?
|
128
|
+
check2(File.exist?(@actual)) { "File.exist?(#{@actual.inspect})" }
|
129
|
+
end
|
130
|
+
|
131
|
+
def same?(expected)
|
132
|
+
check2(@actual.equal?(expected)) { "#{@actual.inspect}.equal?(#{expected.inspect})" }
|
133
|
+
end
|
134
|
+
|
135
|
+
def in?(expected)
|
136
|
+
check2(expected.include?(@actual)) { "#{expected.inspect}.include?(#{@actual.inspect})" }
|
137
|
+
end
|
138
|
+
|
139
|
+
def include?(expected)
|
140
|
+
check2(@actual.include?(expected)) { "#{@actual.inspect}.include?(#{expected.inspect})" }
|
141
|
+
end
|
142
|
+
|
143
|
+
def is_a?(expected)
|
144
|
+
check2(@actual.is_a?(expected)) { "#{@actual.inspect}.is_a?(#{expected})" }
|
145
|
+
end
|
146
|
+
alias kind_of? is_a?
|
147
|
+
|
148
|
+
def nil?
|
149
|
+
check2(@actual.nil?) { "#{@actual.inspect}.nil?" }
|
150
|
+
end
|
151
|
+
|
152
|
+
def empty?
|
153
|
+
check2(@actual.empty?) { "#{@actual.inspect}.empty?" }
|
154
|
+
end
|
155
|
+
|
156
|
+
def raise?(exception_class, message=nil)
|
157
|
+
if @negative
|
158
|
+
_should_not_raise(exception_class)
|
159
|
+
ex = nil
|
160
|
+
else
|
161
|
+
ex = _should_raise(exception_class, message)
|
162
|
+
end
|
163
|
+
return ex
|
164
|
+
end
|
165
|
+
|
166
|
+
private
|
167
|
+
|
168
|
+
def _should_raise(exception_class, message)
|
169
|
+
not_raised = false
|
170
|
+
begin
|
171
|
+
@actual.call
|
172
|
+
not_raised = true
|
173
|
+
rescue Exception => ex
|
174
|
+
@actual.instance_variable_set('@exception', ex)
|
175
|
+
def @actual.exception; @exception; end
|
176
|
+
ex.class <= exception_class or
|
177
|
+
raise new_assertion_failed("#{exception_class.name} expected but #{ex.class.name} raised.", 2)
|
178
|
+
if message
|
179
|
+
op = message.is_a?(Regexp) ? '=~' : '=='
|
180
|
+
ex.message.__send__(op, message) or
|
181
|
+
raise new_assertion_failed("#{ex.message.inspect} #{op} #{message.inspect}: failed.", 2)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
raise new_assertion_failed("#{exception_class.name} expected but not raised.", 2) if not_raised
|
185
|
+
return ex
|
186
|
+
end
|
187
|
+
|
188
|
+
def _should_not_raise(exception_class=Exception)
|
189
|
+
begin
|
190
|
+
@actual.call
|
191
|
+
rescue Exception => ex
|
192
|
+
@actual.instance_variable_set('@exception', ex)
|
193
|
+
def @actual.exception; @exception; end
|
194
|
+
if ex.class <= exception_class
|
195
|
+
raise new_assertion_failed("unexpected #{ex.class.name} raised.", 2)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def do_assert(flag, expected, op, negative_op)
|
201
|
+
flag, msg = check(flag, expected, op, negative_op)
|
202
|
+
return true if flag
|
203
|
+
raise new_assertion_failed(msg)
|
204
|
+
end
|
205
|
+
|
206
|
+
def new_assertion_failed(msg, depth=2)
|
207
|
+
ex = AssertionFailed.new(msg)
|
208
|
+
ex.set_backtrace(caller(depth+1)) # manipulate backtrace
|
209
|
+
return ex
|
210
|
+
end
|
211
|
+
|
212
|
+
def check(flag, expected, op, negative_op)
|
213
|
+
if @negative
|
214
|
+
flag = ! flag
|
215
|
+
op = negative_op
|
216
|
+
end
|
217
|
+
msg = flag ? nil : failed_message(expected, op)
|
218
|
+
return flag, msg
|
219
|
+
end
|
220
|
+
|
221
|
+
def failed_message(expected, op)
|
222
|
+
"#{@actual.inspect} #{op} #{expected.inspect}: failed."
|
223
|
+
end
|
224
|
+
|
225
|
+
def check2(flag)
|
226
|
+
flag = ! flag if @negative
|
227
|
+
return true if flag
|
228
|
+
expr = yield
|
229
|
+
expr = "! #{expr}" if @negative
|
230
|
+
raise new_assertion_failed("#{expr}: failed.")
|
231
|
+
end
|
232
|
+
|
233
|
+
end
|
234
|
+
|
235
|
+
|
236
|
+
module Helper
|
237
|
+
|
238
|
+
module_function
|
239
|
+
|
240
|
+
def ok
|
241
|
+
actual = yield
|
242
|
+
return Oktest::AssertionObject.new(self, actual, false)
|
243
|
+
end
|
244
|
+
|
245
|
+
def ok_(actual)
|
246
|
+
return Oktest::AssertionObject.new(self, actual, false)
|
247
|
+
end
|
248
|
+
|
249
|
+
def not_ok
|
250
|
+
actual = yield
|
251
|
+
return Oktest::AssertionObject.new(self, actual, true)
|
252
|
+
end
|
253
|
+
|
254
|
+
def not_ok_(actual)
|
255
|
+
return Oktest::AssertionObject.new(self, actual, true)
|
256
|
+
end
|
257
|
+
|
258
|
+
def dummy_io(stdin_str=nil)
|
259
|
+
require 'stringio' unless defined?(StringIO)
|
260
|
+
stdout, $stdout = $stdout, StringIO.new
|
261
|
+
stderr, $stderr = $stderr, StringIO.new
|
262
|
+
stdin, $stdin = $stdin, StringIO.new(stdin_str) if stdin_str
|
263
|
+
begin
|
264
|
+
yield
|
265
|
+
return [$stdout.string, $stderr.string]
|
266
|
+
ensure
|
267
|
+
$stdout = stdout
|
268
|
+
$stderr = stderr
|
269
|
+
$stdin = stdin if stdin_str
|
270
|
+
end
|
271
|
+
end
|
272
|
+
alias capture_io dummy_io # for backward compatibility
|
273
|
+
|
274
|
+
def dummy_file(pairs)
|
275
|
+
fnames = []
|
276
|
+
begin
|
277
|
+
pairs.each do |fname, content|
|
278
|
+
fnames << fname
|
279
|
+
File.open(fname, 'wb') {|f| f.write(content) }
|
280
|
+
yield
|
281
|
+
end
|
282
|
+
ensure
|
283
|
+
File.unlink(*fnames)
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
def dummy_dir(*paths)
|
288
|
+
require 'fileutils' unless defined?(FileUtils)
|
289
|
+
begin
|
290
|
+
paths.each {|path| FileUtils.mkdir_p(path) }
|
291
|
+
yield
|
292
|
+
ensure
|
293
|
+
paths.reverse.each {|path| FileUtils.rm_rf(path) }
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
## marker method to represent pre-condition
|
298
|
+
def pre_cond; yield; end
|
299
|
+
|
300
|
+
## marker method to represent post-condition
|
301
|
+
def post_cond; yield; end
|
302
|
+
|
303
|
+
## marker method to describe target of specification
|
304
|
+
def target(desc); yield; end
|
305
|
+
|
306
|
+
## marker method to describe specification
|
307
|
+
#def spec(desc); yield if block_given?; end
|
308
|
+
def spec(desc)
|
309
|
+
reporter = @_oktest_runner && @_oktest_runner.reporter
|
310
|
+
status = nil
|
311
|
+
begin
|
312
|
+
reporter.enter_spec(self, desc) if reporter
|
313
|
+
if block_given?
|
314
|
+
yield
|
315
|
+
status = :ok
|
316
|
+
else
|
317
|
+
status = :empty
|
318
|
+
end
|
319
|
+
rescue AssertionFailed => ex
|
320
|
+
status = :fail
|
321
|
+
raise ex
|
322
|
+
rescue => ex
|
323
|
+
status = :error
|
324
|
+
raise ex
|
325
|
+
ensure
|
326
|
+
reporter.exit_spec(self, status) if reporter
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
def tracer(*args)
|
331
|
+
return Oktest::Util::Tracer.new(*args)
|
332
|
+
end
|
333
|
+
|
334
|
+
end
|
335
|
+
|
336
|
+
|
337
|
+
module ClassMethodHelper
|
338
|
+
|
339
|
+
def method_added(name)
|
340
|
+
super
|
341
|
+
dict = (@_test_method_names_dict ||= {})
|
342
|
+
name = name.to_s
|
343
|
+
if name =~ /\Atest_?/
|
344
|
+
## if test method name is duplicated, raise error
|
345
|
+
dict[name].nil? or
|
346
|
+
raise NameError.new("#{self.name}##{name}(): already defined (please change test method name).")
|
347
|
+
dict[name] = dict.size()
|
348
|
+
## if ENV['TEST'] is set, remove unmatched method
|
349
|
+
if ENV['TEST']
|
350
|
+
remove_method(name) unless name.sub(/\Atest_?/, '').index(ENV['TEST'])
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
def method_undefined(method)
|
356
|
+
super
|
357
|
+
dict = @_test_method_names_dict
|
358
|
+
dict.delete(method.to_s) if dict
|
359
|
+
end
|
360
|
+
|
361
|
+
def test(desc, &block)
|
362
|
+
@_test_count ||= 0
|
363
|
+
@_test_count += 1
|
364
|
+
method_name = "test_%03d_%s" % [@_test_count, desc.to_s.gsub(/[^\w]/, '_')]
|
365
|
+
define_method(method_name, block)
|
366
|
+
end
|
367
|
+
|
368
|
+
end
|
369
|
+
|
370
|
+
|
371
|
+
module TestCase
|
372
|
+
include Helper
|
373
|
+
|
374
|
+
@_subclasses = []
|
375
|
+
|
376
|
+
def self._subclasses # :nodoc:
|
377
|
+
return @_subclasses
|
378
|
+
end
|
379
|
+
|
380
|
+
def self.included(klass)
|
381
|
+
@_subclasses << klass if klass.is_a?(Class)
|
382
|
+
klass.class_eval do
|
383
|
+
extend Oktest::ClassMethodHelper
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
end
|
388
|
+
|
389
|
+
|
390
|
+
class Reporter
|
391
|
+
|
392
|
+
def before_all(klass)
|
393
|
+
end
|
394
|
+
|
395
|
+
def after_all(klass)
|
396
|
+
end
|
397
|
+
|
398
|
+
def before(obj)
|
399
|
+
end
|
400
|
+
|
401
|
+
def after(obj)
|
402
|
+
end
|
403
|
+
|
404
|
+
def print_ok(obj)
|
405
|
+
end
|
406
|
+
|
407
|
+
def print_failed(obj, ex)
|
408
|
+
end
|
409
|
+
|
410
|
+
def print_error(obj, ex)
|
411
|
+
end
|
412
|
+
|
413
|
+
def enter_spec(obj, desc)
|
414
|
+
end
|
415
|
+
|
416
|
+
def exit_spec(obj, status)
|
417
|
+
end
|
418
|
+
|
419
|
+
end
|
420
|
+
|
421
|
+
|
422
|
+
class BaseReporter < Reporter
|
423
|
+
|
424
|
+
def initialize(out=nil)
|
425
|
+
@out = out || $stdout
|
426
|
+
@_flush = @out.respond_to?(:flush)
|
427
|
+
end
|
428
|
+
|
429
|
+
def before_all(klass)
|
430
|
+
@count_test = 0
|
431
|
+
@count_spec = 0
|
432
|
+
end
|
433
|
+
|
434
|
+
def before(obj)
|
435
|
+
@count_test += 1
|
436
|
+
@spec_status = nil
|
437
|
+
end
|
438
|
+
|
439
|
+
def after(obj)
|
440
|
+
end
|
441
|
+
|
442
|
+
def enter_spec(obj, desc)
|
443
|
+
@count_spec += 1
|
444
|
+
end
|
445
|
+
|
446
|
+
def exit_spec(obj, status)
|
447
|
+
@spec_status = status
|
448
|
+
case status
|
449
|
+
when :ok ; write('.')
|
450
|
+
when :empty ; write('_')
|
451
|
+
when :fail ; write('f')
|
452
|
+
when :error ; write('E')
|
453
|
+
when nil ; write('?')
|
454
|
+
else
|
455
|
+
raise "** internal error: status=#{status.inspect}"
|
456
|
+
end
|
457
|
+
end
|
458
|
+
|
459
|
+
private
|
460
|
+
|
461
|
+
def _test_ident(obj)
|
462
|
+
return obj.instance_variable_get('@_test_method')
|
463
|
+
end
|
464
|
+
|
465
|
+
def write(str)
|
466
|
+
@out << str
|
467
|
+
@out.flush if @_flush
|
468
|
+
end
|
469
|
+
|
470
|
+
def print_backtrace(ex, out=@out)
|
471
|
+
ex.backtrace.each do |str|
|
472
|
+
out << " #{str}\n"
|
473
|
+
if str =~ /\A(.*):(\d+):in `(.*?)'/
|
474
|
+
filepath, linenum, method = $1, $2.to_i, $3
|
475
|
+
#break if method =~ /\Atest_?/
|
476
|
+
line = get_line(filepath, linenum)
|
477
|
+
out << " #{line.strip}\n" if line
|
478
|
+
break if method =~ /\Atest_?/
|
479
|
+
end
|
480
|
+
end
|
481
|
+
end
|
482
|
+
|
483
|
+
def get_line(filepath, linenum)
|
484
|
+
return nil unless File.file?(filepath)
|
485
|
+
linenum = linenum.to_i
|
486
|
+
line = File.open(filepath) do |f|
|
487
|
+
i = 0
|
488
|
+
f.find { (i += 1) == linenum }
|
489
|
+
end
|
490
|
+
return line
|
491
|
+
end
|
492
|
+
|
493
|
+
end
|
494
|
+
|
495
|
+
|
496
|
+
class SimpleReporter < BaseReporter
|
497
|
+
|
498
|
+
def before_all(klass)
|
499
|
+
super
|
500
|
+
write("### %s: " % klass.name)
|
501
|
+
@buf = ""
|
502
|
+
end
|
503
|
+
|
504
|
+
def after_all(klass)
|
505
|
+
super
|
506
|
+
write(" (#{@count_test} tests, #{@count_spec} specs)\n")
|
507
|
+
@out << @buf.to_s
|
508
|
+
@buf = nil
|
509
|
+
end
|
510
|
+
|
511
|
+
def print_ok(obj)
|
512
|
+
write(".") unless @spec_status
|
513
|
+
end
|
514
|
+
|
515
|
+
def print_failed(obj, ex)
|
516
|
+
write("f") unless @spec_status
|
517
|
+
@buf << "Failed: #{_test_ident(obj)}()\n"
|
518
|
+
@buf << " #{ex.message}\n"
|
519
|
+
print_backtrace(ex, @buf)
|
520
|
+
#assert ex.is_a?(AssertionFailed)
|
521
|
+
@buf << ex.diff if ex.diff
|
522
|
+
end
|
523
|
+
|
524
|
+
def print_error(obj, ex)
|
525
|
+
write("E") unless @spec_status
|
526
|
+
@buf << "ERROR: #{_test_ident(obj)}()\n"
|
527
|
+
@buf << " #{ex.class.name}: #{ex.message}\n"
|
528
|
+
print_backtrace(ex, @buf)
|
529
|
+
end
|
530
|
+
|
531
|
+
end
|
532
|
+
|
533
|
+
|
534
|
+
class VerboseReporter < BaseReporter
|
535
|
+
|
536
|
+
def before_all(klass)
|
537
|
+
super
|
538
|
+
write("### %s\n" % klass.name)
|
539
|
+
end
|
540
|
+
|
541
|
+
def after_all(klass)
|
542
|
+
super
|
543
|
+
write(" (#{@count_test} tests, #{@count_spec} specs)\n")
|
544
|
+
end
|
545
|
+
|
546
|
+
def before(obj)
|
547
|
+
super
|
548
|
+
write("- #{_test_ident(obj)}: ")
|
549
|
+
end
|
550
|
+
|
551
|
+
def print_ok(obj)
|
552
|
+
write(" ok\n")
|
553
|
+
end
|
554
|
+
|
555
|
+
def print_failed(obj, ex)
|
556
|
+
write(" FAILED\n")
|
557
|
+
write(" #{ex.message}\n")
|
558
|
+
print_backtrace(ex, @out)
|
559
|
+
#assert ex.is_a?(AssertionFailed)
|
560
|
+
write(ex.diff) if ex.diff
|
561
|
+
end
|
562
|
+
|
563
|
+
def print_error(obj, ex)
|
564
|
+
write(" ERROR\n")
|
565
|
+
write(" #{ex.class.name}: #{ex.message}\n")
|
566
|
+
print_backtrace(ex, @out)
|
567
|
+
end
|
568
|
+
|
569
|
+
end
|
570
|
+
|
571
|
+
|
572
|
+
REPORTER = SimpleReporter
|
573
|
+
#REPORTER = VerboseReporter
|
574
|
+
|
575
|
+
def self.REPORTER=(reporter_class)
|
576
|
+
remove_const(:REPORTER)
|
577
|
+
const_set(:REPORTER, reporter_class)
|
578
|
+
end
|
579
|
+
|
580
|
+
|
581
|
+
class Runner
|
582
|
+
|
583
|
+
def initialize(reporter=nil)
|
584
|
+
@reporter = reporter || REPORTER.new
|
585
|
+
end
|
586
|
+
attr_accessor :reporter
|
587
|
+
|
588
|
+
def test_method_names_from(klass)
|
589
|
+
test_method_names = klass.instance_methods(true).collect {|sym| sym.to_s }.grep(/\Atest/).sort()
|
590
|
+
dict = klass.instance_variable_get('@_test_method_names_dict')
|
591
|
+
if dict
|
592
|
+
dict = dict.dup() # key: test method name (String), value: index (Integer)
|
593
|
+
i = 0
|
594
|
+
test_method_names.select {|name| ! dict.key?(name) }.reverse.each {|name| dict[name] = (i -= 1) }
|
595
|
+
test_method_names = dict.sort_by {|k, v| v }.collect {|k, v| k }
|
596
|
+
end
|
597
|
+
return test_method_names
|
598
|
+
end
|
599
|
+
|
600
|
+
def warning(msg)
|
601
|
+
warn "WARNING: #{msg}"
|
602
|
+
end
|
603
|
+
|
604
|
+
def run(klass)
|
605
|
+
reporter = @reporter
|
606
|
+
## gather test methods
|
607
|
+
test_method_names = test_method_names_from(klass)
|
608
|
+
## filer by $TEST environment variable
|
609
|
+
pattern = ENV['TEST']
|
610
|
+
test_method_names.delete_if {|x| x.index(pattern).nil? } if pattern
|
611
|
+
## sort by linenumber
|
612
|
+
# nothing
|
613
|
+
## invoke before_all()
|
614
|
+
reporter.before_all(klass)
|
615
|
+
if klass.respond_to?(:before_all)
|
616
|
+
klass.before_all()
|
617
|
+
elsif klass.method_defined?(:before_all)
|
618
|
+
warning "#{klass.name}#before_all() should be class method (but defined as instance method)"
|
619
|
+
end
|
620
|
+
## invoke test methods
|
621
|
+
count = 0
|
622
|
+
flag_before = klass.method_defined?(:before)
|
623
|
+
flag_setup = klass.method_defined?(:setup)
|
624
|
+
flag_after = klass.method_defined?(:after)
|
625
|
+
flag_teardown = klass.method_defined?(:teardown)
|
626
|
+
test_method_names.each do |method_name|
|
627
|
+
## create instance object for each test
|
628
|
+
begin
|
629
|
+
obj = klass.new
|
630
|
+
rescue ArgumentError
|
631
|
+
obj = klass.new(method_name)
|
632
|
+
end
|
633
|
+
obj.instance_variable_set('@_name', method_name.sub(/\Atest_?/, ''))
|
634
|
+
obj.instance_variable_set('@_test_method', method_name)
|
635
|
+
obj.instance_variable_set('@_oktest_runner', self)
|
636
|
+
## invoke before() or setup()
|
637
|
+
reporter.before(obj)
|
638
|
+
flag_before ? obj.before() : flag_setup ? obj.setup() : nil
|
639
|
+
## invoke test method
|
640
|
+
begin
|
641
|
+
obj.__send__(method_name)
|
642
|
+
reporter.print_ok(obj)
|
643
|
+
rescue Oktest::AssertionFailed => ex
|
644
|
+
count += 1
|
645
|
+
reporter.print_failed(obj, ex)
|
646
|
+
rescue Exception => ex
|
647
|
+
count += 1
|
648
|
+
reporter.print_error(obj, ex)
|
649
|
+
ensure
|
650
|
+
## invoke after() or teardown()
|
651
|
+
flag_after ? obj.after() : flag_teardown ? obj.teardown() : nil
|
652
|
+
reporter.after(obj)
|
653
|
+
end
|
654
|
+
end
|
655
|
+
## invoke after_all()
|
656
|
+
if klass.respond_to?(:after_all)
|
657
|
+
klass.after_all()
|
658
|
+
elsif klass.method_defined?(:after_all)
|
659
|
+
warning "#{klass.name}#after_all() should be class method (but defined as instance method)"
|
660
|
+
end
|
661
|
+
reporter.after_all(klass)
|
662
|
+
##
|
663
|
+
return count
|
664
|
+
end
|
665
|
+
end
|
666
|
+
|
667
|
+
|
668
|
+
def self.run(*classes)
|
669
|
+
opts = classes.last.is_a?(Hash) ? classes.pop() : {}
|
670
|
+
reporter_class = opts[:verbose] ? VerboseReporter : REPORTER
|
671
|
+
reporter = reporter_class.new(opts[:out])
|
672
|
+
runner = Runner.new(reporter)
|
673
|
+
classes.each {|cls| runner.run(cls) }
|
674
|
+
self.run_at_exit = false
|
675
|
+
end
|
676
|
+
|
677
|
+
def self.run_all(opts={})
|
678
|
+
classes = Oktest::TestCase._subclasses()
|
679
|
+
args = classes + [opts]
|
680
|
+
self.run(*args)
|
681
|
+
end
|
682
|
+
|
683
|
+
@_run_at_exit = true
|
684
|
+
|
685
|
+
def self.run_at_exit?
|
686
|
+
return @_run_at_exit
|
687
|
+
end
|
688
|
+
|
689
|
+
def self.run_at_exit=(flag)
|
690
|
+
@_run_at_exit = flag
|
691
|
+
end
|
692
|
+
|
693
|
+
|
694
|
+
module Util
|
695
|
+
|
696
|
+
|
697
|
+
class Call
|
698
|
+
|
699
|
+
def initialize(name, args, ret)
|
700
|
+
@name, @args, @ret = name, args, ret
|
701
|
+
end
|
702
|
+
|
703
|
+
attr_accessor :name, :args, :ret
|
704
|
+
|
705
|
+
def to_a
|
706
|
+
return [@name, @args, @ret]
|
707
|
+
end
|
708
|
+
|
709
|
+
end
|
710
|
+
|
711
|
+
|
712
|
+
class FakeObject
|
713
|
+
|
714
|
+
def initialize(*args)
|
715
|
+
if (hash = args[-1]).is_a?(Hash)
|
716
|
+
hash.each do |k, v|
|
717
|
+
v.is_a?(Proc) ? add_response(k, &v) : add_response(k, v)
|
718
|
+
end
|
719
|
+
end
|
720
|
+
@_calls = []
|
721
|
+
end
|
722
|
+
|
723
|
+
attr_reader :_calls
|
724
|
+
|
725
|
+
def add_response(name, return_value=nil, &block)
|
726
|
+
#if block
|
727
|
+
(class << self; self; end).class_eval do
|
728
|
+
define_method name do |*args|
|
729
|
+
@_calls << (call = Call.new(name, args, return_value))
|
730
|
+
call.ret = block.call(*args) if block
|
731
|
+
call.ret
|
732
|
+
end
|
733
|
+
end
|
734
|
+
#else
|
735
|
+
# (class << self; self; end).class_eval do
|
736
|
+
# define_method name do |*args, &blk|
|
737
|
+
# @calls << (call = Call.new(name, args, return_value))
|
738
|
+
# call.ret
|
739
|
+
# end
|
740
|
+
# end
|
741
|
+
#end
|
742
|
+
end
|
743
|
+
|
744
|
+
end
|
745
|
+
|
746
|
+
|
747
|
+
class Tracer
|
748
|
+
|
749
|
+
def initialize
|
750
|
+
@calls = []
|
751
|
+
end
|
752
|
+
|
753
|
+
attr_reader :calls
|
754
|
+
|
755
|
+
def [](index)
|
756
|
+
@calls[index]
|
757
|
+
end
|
758
|
+
|
759
|
+
def length
|
760
|
+
@calls.length
|
761
|
+
end
|
762
|
+
|
763
|
+
alias size length
|
764
|
+
|
765
|
+
def trace_method(obj, *method_names)
|
766
|
+
#tracer = self
|
767
|
+
#method_names.each do |method_name|
|
768
|
+
# (class << obj; self; end).class_eval do
|
769
|
+
# alias_method "__orig_#{method_name}", method_name
|
770
|
+
# define_method method_name do |*args|
|
771
|
+
# tracer.calls << (call = Call.new(method_name, args, nil))
|
772
|
+
# call.ret = obj.__send__("__orig_#{method_name}", *args)
|
773
|
+
# call.ret
|
774
|
+
# end
|
775
|
+
# end
|
776
|
+
#end
|
777
|
+
obj.instance_variable_set("@__calls", @calls)
|
778
|
+
method_names.each do |method_name|
|
779
|
+
(class << obj; self; end).class_eval <<-"END"
|
780
|
+
alias_method :__orig_#{method_name}, :#{method_name}
|
781
|
+
def #{method_name}(*args, &blk)
|
782
|
+
@__calls << (call = Call.new(:#{method_name}, args, nil))
|
783
|
+
#call.ret = self.__orig_#{method_name}(*args, &blk)
|
784
|
+
call.ret = self.__send__(:__orig_#{method_name}, *args, &blk)
|
785
|
+
call.ret
|
786
|
+
end
|
787
|
+
END
|
788
|
+
end
|
789
|
+
nil
|
790
|
+
end
|
791
|
+
|
792
|
+
def fake_method(obj, method_name, return_value=nil, &block)
|
793
|
+
tracer = self
|
794
|
+
(class << obj; self; end).class_eval do
|
795
|
+
define_method method_name do |*args|
|
796
|
+
tracer.calls << (call = Call.new(method_name, args, return_value))
|
797
|
+
call.ret = block.call(*args) if block
|
798
|
+
call.ret
|
799
|
+
end
|
800
|
+
end
|
801
|
+
nil
|
802
|
+
end
|
803
|
+
|
804
|
+
def fake_object(*args)
|
805
|
+
fake_obj = FakeObject.new(*args)
|
806
|
+
fake_obj.instance_variable_set('@_calls', @calls)
|
807
|
+
return fake_obj
|
808
|
+
end
|
809
|
+
|
810
|
+
end
|
811
|
+
|
812
|
+
|
813
|
+
end #Util
|
814
|
+
|
815
|
+
|
816
|
+
end
|
817
|
+
|
818
|
+
|
819
|
+
at_exit do
|
820
|
+
ex = $!
|
821
|
+
if (! ex || ex.is_a?(SystemExit)) && Oktest.run_at_exit? # && ! defined?(Test::Unit)
|
822
|
+
Oktest.run_all()
|
823
|
+
raise ex if ex
|
824
|
+
end
|
825
|
+
end
|