test-unit 2.2.0 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +24 -1
- data/Manifest.txt +8 -0
- data/README.txt +1 -0
- data/Rakefile +1 -2
- data/html/github-logo.png +0 -0
- data/html/index.html +30 -19
- data/html/index.html.ja +29 -17
- data/html/test-unit.css +9 -2
- data/lib/test/unit/assertions.rb +77 -19
- data/lib/test/unit/attribute.rb +33 -29
- data/lib/test/unit/autorunner.rb +15 -1
- data/lib/test/unit/collector/xml.rb +250 -0
- data/lib/test/unit/data.rb +80 -0
- data/lib/test/unit/error.rb +4 -3
- data/lib/test/unit/fixture.rb +30 -1
- data/lib/test/unit/runner/xml.rb +15 -0
- data/lib/test/unit/testcase.rb +201 -85
- data/lib/test/unit/testresult.rb +6 -2
- data/lib/test/unit/testsuite.rb +17 -1
- data/lib/test/unit/testsuitecreator.rb +79 -0
- data/lib/test/unit/ui/console/testrunner.rb +23 -20
- data/lib/test/unit/ui/testrunnermediator.rb +11 -2
- data/lib/test/unit/ui/xml/testrunner.rb +224 -0
- data/lib/test/unit/version.rb +1 -1
- data/test/fixtures/plus.csv +3 -0
- data/test/test-data.rb +179 -0
- data/test/test-fixture.rb +163 -0
- data/test/test-testcase.rb +49 -29
- data/test/test_testsuite.rb +19 -11
- metadata +14 -6
@@ -0,0 +1,15 @@
|
|
1
|
+
module Test
|
2
|
+
module Unit
|
3
|
+
AutoRunner.register_runner(:xml) do |auto_runner|
|
4
|
+
require 'test/unit/ui/xml/testrunner'
|
5
|
+
Test::Unit::UI::XML::TestRunner
|
6
|
+
end
|
7
|
+
|
8
|
+
AutoRunner.setup_option do |auto_runner, opts|
|
9
|
+
opts.on("--output-file-descriptor=FD", Integer,
|
10
|
+
"Outputs to file descriptor FD") do |fd|
|
11
|
+
auto_runner.runner_options[:output_file_descriptor] = fd
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/test/unit/testcase.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
# Author:: Nathaniel Talbott.
|
4
4
|
# Copyright::
|
5
5
|
# * Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
|
6
|
-
# * Copyright (c) 2008-
|
6
|
+
# * Copyright (c) 2008-2011 Kouhei Sutou <tt><kou@clear-code.com></tt>
|
7
7
|
# License:: Ruby license.
|
8
8
|
|
9
9
|
require 'test/unit/attribute'
|
@@ -16,7 +16,9 @@ require 'test/unit/pending'
|
|
16
16
|
require 'test/unit/omission'
|
17
17
|
require 'test/unit/notification'
|
18
18
|
require 'test/unit/priority'
|
19
|
+
require 'test/unit/data'
|
19
20
|
require 'test/unit/testsuite'
|
21
|
+
require 'test/unit/testsuitecreator'
|
20
22
|
require 'test/unit/assertionfailederror'
|
21
23
|
require 'test/unit/util/backtracefilter'
|
22
24
|
require 'test/unit/util/output'
|
@@ -49,6 +51,10 @@ module Test
|
|
49
51
|
# ...
|
50
52
|
# end
|
51
53
|
#
|
54
|
+
# def cleanup
|
55
|
+
# ...
|
56
|
+
# end
|
57
|
+
#
|
52
58
|
# def teardown
|
53
59
|
# ...
|
54
60
|
# end
|
@@ -66,9 +72,11 @@ module Test
|
|
66
72
|
# * startup
|
67
73
|
# * setup
|
68
74
|
# * test_my_method1
|
75
|
+
# * cleanup
|
69
76
|
# * teardown
|
70
77
|
# * setup
|
71
78
|
# * test_my_method2
|
79
|
+
# * cleanup
|
72
80
|
# * teardown
|
73
81
|
# * shutdown
|
74
82
|
class TestCase
|
@@ -81,12 +89,15 @@ module Test
|
|
81
89
|
include TestCaseOmissionSupport
|
82
90
|
include TestCaseNotificationSupport
|
83
91
|
include Priority
|
92
|
+
include Data
|
84
93
|
include Assertions
|
85
94
|
include Util::BacktraceFilter
|
86
95
|
include Util::Output
|
87
96
|
|
88
97
|
STARTED = name + "::STARTED" # :nodoc:
|
89
98
|
FINISHED = name + "::FINISHED" # :nodoc:
|
99
|
+
STARTED_OBJECT = name + "::STARTED::OBJECT" # :nodoc:
|
100
|
+
FINISHED_OBJECT = name + "::FINISHED::OBJECT" # :nodoc:
|
90
101
|
|
91
102
|
DESCENDANTS = [] # :nodoc:
|
92
103
|
AVAILABLE_ORDERS = [:alphabetic, :random, :defined] # :nodoc:
|
@@ -99,30 +110,24 @@ module Test
|
|
99
110
|
@@added_methods = {}
|
100
111
|
def method_added(name) # :nodoc:
|
101
112
|
super
|
102
|
-
|
113
|
+
_added_methods = added_methods
|
103
114
|
stringified_name = name.to_s
|
104
|
-
if
|
115
|
+
if _added_methods.include?(stringified_name)
|
105
116
|
attribute(:redefined, true, {}, stringified_name)
|
106
117
|
end
|
107
|
-
|
118
|
+
_added_methods << stringified_name
|
119
|
+
end
|
120
|
+
|
121
|
+
def added_methods # :nodoc:
|
122
|
+
@@added_methods[self] ||= []
|
108
123
|
end
|
109
124
|
|
110
125
|
# Rolls up all of the test* methods in the fixture into
|
111
126
|
# one suite, creating a new instance of the fixture for
|
112
127
|
# each method.
|
113
128
|
def suite
|
114
|
-
|
115
|
-
|
116
|
-
catch(:invalid_test) do
|
117
|
-
suite << new(test)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
if suite.empty?
|
121
|
-
catch(:invalid_test) do
|
122
|
-
suite << new("default_test")
|
123
|
-
end
|
124
|
-
end
|
125
|
-
suite
|
129
|
+
suite_creator = TestSuiteCreator.new(self)
|
130
|
+
suite_creator.create
|
126
131
|
end
|
127
132
|
|
128
133
|
# Called before every test case runs. Can be used
|
@@ -219,9 +224,11 @@ module Test
|
|
219
224
|
@@test_orders[self] = order
|
220
225
|
end
|
221
226
|
|
222
|
-
# Defines a test in declarative syntax
|
227
|
+
# Defines a test in declarative syntax or marks
|
228
|
+
# following method as a test method.
|
223
229
|
#
|
224
|
-
#
|
230
|
+
# In declarative syntax usage, the following two
|
231
|
+
# test definitions are the almost same:
|
225
232
|
#
|
226
233
|
# description "register user"
|
227
234
|
# def test_register_user
|
@@ -231,11 +238,33 @@ module Test
|
|
231
238
|
# test "register user" do
|
232
239
|
# ...
|
233
240
|
# end
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
241
|
+
#
|
242
|
+
# In test method mark usage, the "my_test_method" is
|
243
|
+
# treated as a test method:
|
244
|
+
#
|
245
|
+
# test
|
246
|
+
# def my_test_method
|
247
|
+
# assert_equal("call me", ...)
|
248
|
+
# end
|
249
|
+
def test(*test_description_or_targets, &block)
|
250
|
+
if block_given?
|
251
|
+
test_description = test_description_or_targets.first
|
252
|
+
if test_description.nil?
|
253
|
+
raise ArgumentError, "test description is missing"
|
254
|
+
end
|
255
|
+
n_arguments = test_description_or_targets.size
|
256
|
+
if n_arguments > 1
|
257
|
+
message = "wrong number of arguments (#{n_arguments} for 1)"
|
258
|
+
raise ArgumentError, message
|
259
|
+
end
|
260
|
+
method_name = test_description
|
261
|
+
define_method(method_name, &block)
|
262
|
+
description(test_description, method_name)
|
263
|
+
attribute(:test, true, {}, method_name)
|
264
|
+
else
|
265
|
+
targets = test_description_or_targets
|
266
|
+
attribute(:test, true, {}, *targets)
|
267
|
+
end
|
239
268
|
end
|
240
269
|
|
241
270
|
# Describes a test.
|
@@ -251,44 +280,6 @@ module Test
|
|
251
280
|
def description(value, target=nil)
|
252
281
|
attribute(:description, value, {}, target || [])
|
253
282
|
end
|
254
|
-
|
255
|
-
# :stopdoc:
|
256
|
-
private
|
257
|
-
def collect_test_names
|
258
|
-
method_names = public_instance_methods(true).collect do |name|
|
259
|
-
name.to_s
|
260
|
-
end
|
261
|
-
test_names = method_names.find_all do |method_name|
|
262
|
-
method_name =~ /^test./
|
263
|
-
end
|
264
|
-
send("sort_test_names_in_#{test_order}_order", test_names)
|
265
|
-
end
|
266
|
-
|
267
|
-
def sort_test_names_in_alphabetic_order(test_names)
|
268
|
-
test_names.sort
|
269
|
-
end
|
270
|
-
|
271
|
-
def sort_test_names_in_random_order(test_names)
|
272
|
-
test_names.sort_by {rand(test_names.size)}
|
273
|
-
end
|
274
|
-
|
275
|
-
def sort_test_names_in_defined_order(test_names)
|
276
|
-
added_methods = @@added_methods[self]
|
277
|
-
test_names.sort do |test1, test2|
|
278
|
-
test1_defined_order = added_methods.index(test1)
|
279
|
-
test2_defined_order = added_methods.index(test2)
|
280
|
-
if test1_defined_order and test2_defined_order
|
281
|
-
test1_defined_order <=> test2_defined_order
|
282
|
-
elsif test1_defined_order
|
283
|
-
1
|
284
|
-
elsif test2_defined_order
|
285
|
-
-1
|
286
|
-
else
|
287
|
-
test1 <=> test2
|
288
|
-
end
|
289
|
-
end
|
290
|
-
end
|
291
|
-
# :startdoc:
|
292
283
|
end
|
293
284
|
|
294
285
|
attr_reader :method_name
|
@@ -296,16 +287,29 @@ module Test
|
|
296
287
|
# Creates a new instance of the fixture for running the
|
297
288
|
# test represented by test_method_name.
|
298
289
|
def initialize(test_method_name)
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
290
|
+
@method_name = test_method_name
|
291
|
+
@internal_data = InternalData.new
|
292
|
+
end
|
293
|
+
|
294
|
+
# Assigns test data to the test. It is used in internal.
|
295
|
+
def assign_test_data(label, data) # :nodoc:
|
296
|
+
@internal_data.assign_test_data(label, data)
|
297
|
+
end
|
298
|
+
|
299
|
+
# Returns the test is valid test. It is used in internal.
|
300
|
+
def valid? # :nodoc:
|
301
|
+
return false unless respond_to?(@method_name)
|
302
|
+
test_method = method(@method_name)
|
303
|
+
if @internal_data.have_test_data?
|
304
|
+
return false unless test_method.arity == 1
|
305
|
+
else
|
306
|
+
return false unless test_method.arity <= 0
|
307
|
+
end
|
308
|
+
owner = Util::MethodOwnerFinder.find(self, @method_name)
|
303
309
|
if owner.class != Module and self.class != owner
|
304
|
-
|
310
|
+
return false
|
305
311
|
end
|
306
|
-
|
307
|
-
@test_passed = true
|
308
|
-
@interrupted = false
|
312
|
+
true
|
309
313
|
end
|
310
314
|
|
311
315
|
# Runs the individual test method represented by this
|
@@ -314,12 +318,16 @@ module Test
|
|
314
318
|
def run(result)
|
315
319
|
begin
|
316
320
|
@_result = result
|
321
|
+
@internal_data.test_started
|
317
322
|
yield(STARTED, name)
|
323
|
+
yield(STARTED_OBJECT, self)
|
318
324
|
begin
|
319
325
|
run_setup
|
320
326
|
run_test
|
327
|
+
run_cleanup
|
328
|
+
add_pass
|
321
329
|
rescue Exception
|
322
|
-
@interrupted
|
330
|
+
@internal_data.interrupted
|
323
331
|
raise unless handle_exception($!)
|
324
332
|
ensure
|
325
333
|
begin
|
@@ -328,8 +336,10 @@ module Test
|
|
328
336
|
raise unless handle_exception($!)
|
329
337
|
end
|
330
338
|
end
|
339
|
+
@internal_data.test_finished
|
331
340
|
result.add_run
|
332
341
|
yield(FINISHED, name)
|
342
|
+
yield(FINISHED_OBJECT, self)
|
333
343
|
ensure
|
334
344
|
# @_result = nil # For test-spec's after_all :<
|
335
345
|
end
|
@@ -368,6 +378,41 @@ module Test
|
|
368
378
|
def setup
|
369
379
|
end
|
370
380
|
|
381
|
+
# Called after every test method runs but the test
|
382
|
+
# method isn't marked as 'passed'. Can be used to
|
383
|
+
# clean up and/or verify tested condition.
|
384
|
+
# e.g. Can be used to verify mock.
|
385
|
+
#
|
386
|
+
# You can add additional cleanup tasks by the following
|
387
|
+
# code:
|
388
|
+
# class TestMyClass < Test::Unit::TestCase
|
389
|
+
# def cleanup
|
390
|
+
# ...
|
391
|
+
# end
|
392
|
+
#
|
393
|
+
# cleanup
|
394
|
+
# def my_cleanup1
|
395
|
+
# ...
|
396
|
+
# end
|
397
|
+
#
|
398
|
+
# cleanup
|
399
|
+
# def my_cleanup2
|
400
|
+
# ...
|
401
|
+
# end
|
402
|
+
#
|
403
|
+
# def test_my_class
|
404
|
+
# ...
|
405
|
+
# end
|
406
|
+
# end
|
407
|
+
#
|
408
|
+
# Here is a call order:
|
409
|
+
# * test_my_class
|
410
|
+
# * my_cleanup2
|
411
|
+
# * my_cleanup1
|
412
|
+
# * cleanup
|
413
|
+
def cleanup
|
414
|
+
end
|
415
|
+
|
371
416
|
# Called after every test method runs. Can be used to tear
|
372
417
|
# down fixture information.
|
373
418
|
#
|
@@ -409,10 +454,21 @@ module Test
|
|
409
454
|
1
|
410
455
|
end
|
411
456
|
|
457
|
+
# Returns a label of test data for the test. If the
|
458
|
+
# test isn't associated with any test data, it returns
|
459
|
+
# +nil+.
|
460
|
+
def data_label
|
461
|
+
@internal_data.test_data_label
|
462
|
+
end
|
463
|
+
|
412
464
|
# Returns a human-readable name for the specific test that
|
413
465
|
# this instance of TestCase represents.
|
414
466
|
def name
|
415
|
-
|
467
|
+
if @internal_data.have_test_data?
|
468
|
+
"#{@method_name}[#{data_label}](#{self.class.name})"
|
469
|
+
else
|
470
|
+
"#{@method_name}(#{self.class.name})"
|
471
|
+
end
|
416
472
|
end
|
417
473
|
|
418
474
|
# Returns a description for the test. A description
|
@@ -431,13 +487,31 @@ module Test
|
|
431
487
|
|
432
488
|
# It's handy to be able to compare TestCase instances.
|
433
489
|
def ==(other)
|
434
|
-
return false unless
|
435
|
-
return false unless
|
490
|
+
return false unless other.kind_of?(self.class)
|
491
|
+
return false unless @method_name == other.method_name
|
436
492
|
self.class == other.class
|
437
493
|
end
|
438
494
|
|
495
|
+
# Returns a Time at the test was started.
|
496
|
+
def start_time
|
497
|
+
@internal_data.start_time
|
498
|
+
end
|
499
|
+
|
500
|
+
# Returns elapsed time for the test was ran.
|
501
|
+
def elapsed_time
|
502
|
+
@internal_data.elapsed_time
|
503
|
+
end
|
504
|
+
|
505
|
+
# Returns whether the test is interrupted.
|
439
506
|
def interrupted?
|
440
|
-
@interrupted
|
507
|
+
@internal_data.interrupted?
|
508
|
+
end
|
509
|
+
|
510
|
+
# Returns whether this individual test passed or
|
511
|
+
# not. Primarily for use in teardown so that artifacts
|
512
|
+
# can be left behind if the test fails.
|
513
|
+
def passed?
|
514
|
+
@internal_data.passed?
|
441
515
|
end
|
442
516
|
|
443
517
|
private
|
@@ -446,11 +520,14 @@ module Test
|
|
446
520
|
end
|
447
521
|
|
448
522
|
def run_test
|
449
|
-
if self
|
523
|
+
if self[:redefined]
|
450
524
|
notify("#{self.class}\##{@method_name} was redefined")
|
451
525
|
end
|
452
|
-
|
453
|
-
|
526
|
+
if @internal_data.have_test_data?
|
527
|
+
__send__(@method_name, @internal_data.test_data)
|
528
|
+
else
|
529
|
+
__send__(@method_name)
|
530
|
+
end
|
454
531
|
end
|
455
532
|
|
456
533
|
def handle_exception(exception)
|
@@ -460,15 +537,8 @@ module Test
|
|
460
537
|
false
|
461
538
|
end
|
462
539
|
|
463
|
-
# Returns whether this individual test passed or
|
464
|
-
# not. Primarily for use in teardown so that artifacts
|
465
|
-
# can be left behind if the test fails.
|
466
|
-
def passed?
|
467
|
-
@test_passed
|
468
|
-
end
|
469
|
-
|
470
540
|
def problem_occurred
|
471
|
-
@
|
541
|
+
@internal_data.problem_occurred
|
472
542
|
end
|
473
543
|
|
474
544
|
def add_assertion
|
@@ -478,6 +548,52 @@ module Test
|
|
478
548
|
def add_pass
|
479
549
|
current_result.add_pass
|
480
550
|
end
|
551
|
+
|
552
|
+
class InternalData
|
553
|
+
attr_reader :start_time, :elapsed_time
|
554
|
+
attr_reader :test_data_label, :test_data
|
555
|
+
def initialize
|
556
|
+
@start_time = nil
|
557
|
+
@elapsed_time = nil
|
558
|
+
@passed = true
|
559
|
+
@interrupted = false
|
560
|
+
@test_data_label = nil
|
561
|
+
@test_data = nil
|
562
|
+
end
|
563
|
+
|
564
|
+
def passed?
|
565
|
+
@passed
|
566
|
+
end
|
567
|
+
|
568
|
+
def interrupted?
|
569
|
+
@interrupted
|
570
|
+
end
|
571
|
+
|
572
|
+
def assign_test_data(label, data)
|
573
|
+
@test_data_label = label
|
574
|
+
@test_data = data
|
575
|
+
end
|
576
|
+
|
577
|
+
def have_test_data?
|
578
|
+
not @test_data_label.nil?
|
579
|
+
end
|
580
|
+
|
581
|
+
def test_started
|
582
|
+
@start_time = Time.now
|
583
|
+
end
|
584
|
+
|
585
|
+
def test_finished
|
586
|
+
@elapsed_time = Time.now - @start_time
|
587
|
+
end
|
588
|
+
|
589
|
+
def problem_occurred
|
590
|
+
@passed = false
|
591
|
+
end
|
592
|
+
|
593
|
+
def interrupted
|
594
|
+
@interrupted = true
|
595
|
+
end
|
596
|
+
end
|
481
597
|
end
|
482
598
|
end
|
483
599
|
end
|