test-unit 3.2.0 → 3.3.6

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.
Files changed (41) hide show
  1. checksums.yaml +5 -5
  2. data/COPYING +4 -1
  3. data/README.md +11 -11
  4. data/Rakefile +10 -1
  5. data/doc/text/getting-started.md +246 -0
  6. data/doc/text/news.md +372 -1
  7. data/lib/test/unit.rb +171 -157
  8. data/lib/test/unit/assertions.rb +187 -149
  9. data/lib/test/unit/attribute.rb +71 -2
  10. data/lib/test/unit/autorunner.rb +65 -32
  11. data/lib/test/unit/code-snippet-fetcher.rb +7 -7
  12. data/lib/test/unit/collector/load.rb +8 -13
  13. data/lib/test/unit/data-sets.rb +116 -0
  14. data/lib/test/unit/data.rb +121 -12
  15. data/lib/test/unit/diff.rb +11 -11
  16. data/lib/test/unit/fixture.rb +3 -0
  17. data/lib/test/unit/notification.rb +9 -7
  18. data/lib/test/unit/omission.rb +34 -31
  19. data/lib/test/unit/pending.rb +12 -11
  20. data/lib/test/unit/priority.rb +7 -3
  21. data/lib/test/unit/runner/console.rb +25 -0
  22. data/lib/test/unit/test-suite-creator.rb +22 -8
  23. data/lib/test/unit/testcase.rb +270 -182
  24. data/lib/test/unit/ui/console/testrunner.rb +90 -35
  25. data/lib/test/unit/ui/emacs/testrunner.rb +5 -5
  26. data/lib/test/unit/util/observable.rb +2 -2
  27. data/lib/test/unit/util/output.rb +5 -4
  28. data/lib/test/unit/util/procwrapper.rb +4 -4
  29. data/lib/test/unit/version.rb +1 -1
  30. data/test/collector/test-descendant.rb +4 -0
  31. data/test/collector/test-load.rb +35 -2
  32. data/test/collector/test_dir.rb +5 -4
  33. data/test/collector/test_objectspace.rb +7 -5
  34. data/test/test-assertions.rb +128 -101
  35. data/test/test-code-snippet.rb +42 -0
  36. data/test/test-data.rb +195 -79
  37. data/test/test-priority.rb +19 -8
  38. data/test/test-test-case.rb +111 -3
  39. data/test/test-test-suite.rb +1 -0
  40. data/test/testunit-test-util.rb +2 -0
  41. metadata +38 -37
@@ -5,6 +5,8 @@
5
5
  # * Copyright (c) 2011 Kouhei Sutou <tt><kou@clear-code.com></tt>
6
6
  # License:: Ruby license.
7
7
 
8
+ require "test/unit/data-sets"
9
+
8
10
  module Test
9
11
  module Unit
10
12
  class TestSuiteCreator # :nodoc:
@@ -22,15 +24,11 @@ module Test
22
24
  def create
23
25
  suite = TestSuite.new(@test_case.name, @test_case)
24
26
  collect_test_names.each do |test_name|
25
- data_sets = @test_case.find_attribute(test_name, :data,
26
- :recursive => false)
27
+ data_sets = extract_data_sets(test_name)
27
28
  if data_sets
28
- data_sets.each do |data_set|
29
- data_set = data_set.call if data_set.respond_to?(:call)
30
- data_set.each do |label, data|
31
- append_test(suite, test_name) do |test|
32
- test.assign_test_data(label, data)
33
- end
29
+ data_sets.each do |label, data|
30
+ append_test(suite, test_name) do |test|
31
+ test.assign_test_data(label, data)
34
32
  end
35
33
  end
36
34
  else
@@ -42,6 +40,22 @@ module Test
42
40
  end
43
41
 
44
42
  private
43
+ def extract_data_sets(test_name)
44
+ data_sets = @test_case.find_attribute(test_name,
45
+ :data,
46
+ :recursive => false)
47
+ data_method_name = "data_#{test_name}"
48
+ test = @test_case.new(test_name)
49
+ if test.respond_to?(data_method_name)
50
+ data_method = test.method(data_method_name)
51
+ if data_method.arity <= 0
52
+ data_sets ||= DataSets.new
53
+ data_sets << data_method
54
+ end
55
+ end
56
+ data_sets
57
+ end
58
+
45
59
  def append_test(suite, test_name)
46
60
  test = @test_case.new(test_name)
47
61
  yield(test) if block_given?
@@ -37,49 +37,70 @@ module Test
37
37
  # You can run two hooks before/after a TestCase run.
38
38
  #
39
39
  # Example:
40
- # class TestMyClass < Test::Unit::TestCase
41
- # class << self
42
- # def startup
40
+ #
41
+ # class TestMyClass < Test::Unit::TestCase
42
+ # class << self
43
+ # def startup
44
+ # ...
45
+ # end
46
+ #
47
+ # def shutdown
48
+ # ...
49
+ # end
50
+ # end
51
+ #
52
+ # def setup
43
53
  # ...
44
54
  # end
45
55
  #
46
- # def shutdown
56
+ # def cleanup
47
57
  # ...
48
58
  # end
49
- # end
50
59
  #
51
- # def setup
52
- # ...
53
- # end
60
+ # def teardown
61
+ # ...
62
+ # end
54
63
  #
55
- # def cleanup
56
- # ...
57
- # end
64
+ # def test_my_method1
65
+ # ...
66
+ # end
58
67
  #
59
- # def teardown
60
- # ...
68
+ # def test_my_method2
69
+ # ...
70
+ # end
61
71
  # end
62
72
  #
63
- # def test_my_method1
64
- # ...
65
- # end
73
+ # Here is a call order:
66
74
  #
67
- # def test_my_method2
68
- # ...
69
- # end
70
- # end
75
+ # 1. startup
76
+ # 1. setup
77
+ # 1. test_my_method1
78
+ # 1. cleanup
79
+ # 1. teardown
80
+ # 1. setup
81
+ # 1. test_my_method2
82
+ # 1. cleanup
83
+ # 1. teardown
84
+ # 1. shutdown
71
85
  #
72
- # Here is a call order:
73
- # * startup
74
- # * setup
75
- # * test_my_method1
76
- # * cleanup
77
- # * teardown
78
- # * setup
79
- # * test_my_method2
80
- # * cleanup
81
- # * teardown
82
- # * shutdown
86
+ # You can set an attribute to each test.
87
+ #
88
+ # Example:
89
+ #
90
+ # class TestMyClass < Test::Unit::TestCase
91
+ # attribute :speed, :fast
92
+ # def test_my_fast_method
93
+ # # You can get the attribute via `self[]`
94
+ # self[:speed] # => :fast
95
+ # ...
96
+ # end
97
+ #
98
+ # attribute :speed, :slow
99
+ # def test_my_slow_method
100
+ # self[:speed] # => :slow
101
+ # ...
102
+ # end
103
+ # end
83
104
  class TestCase
84
105
  include Attribute
85
106
  include Fixture
@@ -109,6 +130,15 @@ module Test
109
130
  super
110
131
  end
111
132
 
133
+ def include(*modules, &block) # :nodoc:
134
+ super
135
+ modules.each do |mod|
136
+ mod.public_instance_methods(false).each do |method_name|
137
+ AutoRunnerLoader.check(self, method_name.to_s)
138
+ end
139
+ end
140
+ end
141
+
112
142
  @@added_method_names = {}
113
143
  def method_added(name) # :nodoc:
114
144
  super
@@ -129,11 +159,12 @@ module Test
129
159
  path, line, = caller[0].split(/:(\d+)/, 2)
130
160
  line = line.to_i if line
131
161
  end
132
- method_locations << {
162
+ location = {
133
163
  :method_name => stringified_name,
134
164
  :path => File.expand_path(path),
135
165
  :line => line,
136
166
  }
167
+ add_method_location(location)
137
168
  added_method_names[stringified_name] = true
138
169
  AutoRunnerLoader.check(self, stringified_name)
139
170
  end
@@ -155,27 +186,29 @@ module Test
155
186
  # scope.
156
187
  #
157
188
  # Here is an example test case:
158
- # class TestMyClass < Test::Unit::TestCase
159
- # class << self
160
- # def startup
161
- # ...
189
+ #
190
+ # class TestMyClass < Test::Unit::TestCase
191
+ # class << self
192
+ # def startup
193
+ # ...
194
+ # end
162
195
  # end
163
- # end
164
196
  #
165
- # def setup
166
- # ...
167
- # end
197
+ # def setup
198
+ # ...
199
+ # end
168
200
  #
169
- # def test_my_class1
170
- # ...
171
- # end
201
+ # def test_my_class1
202
+ # ...
203
+ # end
172
204
  #
173
- # def test_my_class2
174
- # ...
205
+ # def test_my_class2
206
+ # ...
207
+ # end
175
208
  # end
176
- # end
177
209
  #
178
210
  # Here is a call order:
211
+ #
179
212
  # * startup
180
213
  # * setup
181
214
  # * test_my_class1 (or test_my_class2)
@@ -191,27 +224,29 @@ module Test
191
224
  # down fixture information used in test case scope.
192
225
  #
193
226
  # Here is an example test case:
194
- # class TestMyClass < Test::Unit::TestCase
195
- # class << self
196
- # def shutdown
197
- # ...
227
+ #
228
+ # class TestMyClass < Test::Unit::TestCase
229
+ # class << self
230
+ # def shutdown
231
+ # ...
232
+ # end
198
233
  # end
199
- # end
200
234
  #
201
- # def teardown
202
- # ...
203
- # end
235
+ # def teardown
236
+ # ...
237
+ # end
204
238
  #
205
- # def test_my_class1
206
- # ...
207
- # end
239
+ # def test_my_class1
240
+ # ...
241
+ # end
208
242
  #
209
- # def test_my_class2
210
- # ...
243
+ # def test_my_class2
244
+ # ...
245
+ # end
211
246
  # end
212
- # end
213
247
  #
214
248
  # Here is a call order:
249
+ #
215
250
  # * test_my_class1 (or test_my_class2)
216
251
  # * teardown
217
252
  # * test_my_class2 (or test_my_class1)
@@ -226,20 +261,27 @@ module Test
226
261
  @@test_orders = {}
227
262
 
228
263
  # Returns the current test order. This returns
229
- # +:alphabetic+ by default.
264
+ # `:alphabetic` by default.
230
265
  def test_order
231
- @@test_orders[self] || AVAILABLE_ORDERS.first
266
+ ancestors.each do |ancestor|
267
+ order = @@test_orders[ancestor]
268
+ return order if order
269
+ end
270
+ AVAILABLE_ORDERS.first
232
271
  end
233
272
 
234
273
  # Sets the current test order.
235
274
  #
236
275
  # Here are the available _order_:
237
- # [:alphabetic]
238
- # Default. Tests are sorted in alphabetic order.
239
- # [:random]
240
- # Tests are sorted in random order.
241
- # [:defined]
242
- # Tests are sorted in defined order.
276
+ #
277
+ # :alphabetic
278
+ # : Default. Tests are sorted in alphabetic order.
279
+ #
280
+ # :random
281
+ # : Tests are sorted in random order.
282
+ #
283
+ # :defined
284
+ # : Tests are sorted in defined order.
243
285
  def test_order=(order)
244
286
  @@test_orders[self] = order
245
287
  end
@@ -250,22 +292,22 @@ module Test
250
292
  # In declarative syntax usage, the following two
251
293
  # test definitions are the almost same:
252
294
  #
253
- # description "register user"
254
- # def test_register_user
255
- # ...
256
- # end
295
+ # description "register user"
296
+ # def test_register_user
297
+ # ...
298
+ # end
257
299
  #
258
- # test "register user" do
259
- # ...
260
- # end
300
+ # test "register user" do
301
+ # ...
302
+ # end
261
303
  #
262
304
  # In test method mark usage, the "my_test_method" is
263
305
  # treated as a test method:
264
306
  #
265
- # test
266
- # def my_test_method
267
- # assert_equal("call me", ...)
268
- # end
307
+ # test
308
+ # def my_test_method
309
+ # assert_equal("call me", ...)
310
+ # end
269
311
  def test(*test_description_or_targets, &block)
270
312
  if block_given?
271
313
  test_description = test_description_or_targets.first
@@ -299,10 +341,10 @@ module Test
299
341
  # normal user" description with "test_register"
300
342
  # test.
301
343
  #
302
- # description "register a normal user"
303
- # def test_register
304
- # ...
305
- # end
344
+ # description "register a normal user"
345
+ # def test_register
346
+ # ...
347
+ # end
306
348
  def description(value, target=nil)
307
349
  targets = [target].compact
308
350
  attribute(:description, value, {}, *targets)
@@ -314,20 +356,22 @@ module Test
314
356
  # the same in meaning:
315
357
  #
316
358
  # Standard:
317
- # class TestParent < Test::UnitTestCase
318
- # class TestChild < self
319
- # def test_in_child
359
+ #
360
+ # class TestParent < Test::Unit::TestCase
361
+ # class TestChild < self
362
+ # def test_in_child
363
+ # end
320
364
  # end
321
365
  # end
322
- # end
323
366
  #
324
367
  # Syntax sugar:
325
- # class TestParent < Test::UnitTestCase
326
- # sub_test_case("TestChild") do
327
- # def test_in_child
368
+ #
369
+ # class TestParent < Test::Unit::TestCase
370
+ # sub_test_case("TestChild") do
371
+ # def test_in_child
372
+ # end
328
373
  # end
329
374
  # end
330
- # end
331
375
  #
332
376
  # The difference of them are the following:
333
377
  #
@@ -365,6 +409,11 @@ module Test
365
409
  # @option query [String] :method_name (nil)
366
410
  # the method name for a test.
367
411
  def test_defined?(query)
412
+ locations = find_locations(query)
413
+ not locations.empty?
414
+ end
415
+
416
+ def find_locations(query)
368
417
  query_path = query[:path]
369
418
  query_line = query[:line]
370
419
  query_method_name = query[:method_name]
@@ -377,49 +426,62 @@ module Test
377
426
  available_location = available_locations.find do |location|
378
427
  query_line >= location[:line]
379
428
  end
380
- return false if available_location.nil?
381
- return false if available_location[:test_case] != self
429
+ return [] if available_location.nil?
430
+ return [] if available_location[:test_case] != self
382
431
  available_locations = [available_location]
383
432
  end
384
433
  if query_method_name
385
434
  available_location = available_locations.find do |location|
386
- query_method_name == location[:method_name]
435
+ location[:test_case] == self and
436
+ query_method_name == location[:method_name]
387
437
  end
388
- return false if available_location.nil?
438
+ return [] if available_location.nil?
389
439
  available_locations = [available_location]
390
440
  end
391
441
 
392
- not available_locations.empty?
442
+ available_locations
393
443
  end
394
444
 
395
445
  private
396
446
  # @private
397
447
  @@method_locations = {}
448
+ # @private
449
+ @@method_location_mutex = Mutex.new
450
+
398
451
  # @private
399
452
  def method_locations
400
453
  @@method_locations[self] ||= []
401
454
  end
402
455
 
403
456
  # @private
404
- def target_method_locations(path)
405
- if path.nil?
406
- self_location = method_locations.first
407
- path = self_location[:path] if self_location
457
+ def add_method_location(location)
458
+ @@method_location_mutex.synchronize do
459
+ method_locations << location
408
460
  end
409
- return [] if path.nil?
410
-
411
- target_locations = []
412
- @@method_locations.each do |test_case, locations|
413
- locations.each do |location|
414
- absolete_path = File.expand_path(path)
415
- location_path = location[:path]
416
- location_basename = File.basename(location_path)
417
- if location_path == absolete_path or location_basename == path
418
- target_locations << location.merge(:test_case => test_case)
461
+ end
462
+
463
+ # @private
464
+ def target_method_locations(path)
465
+ @@method_location_mutex.synchronize do
466
+ if path.nil?
467
+ self_location = method_locations.first
468
+ path = self_location[:path] if self_location
469
+ end
470
+ return [] if path.nil?
471
+
472
+ target_locations = []
473
+ @@method_locations.each do |test_case, locations|
474
+ locations.each do |location|
475
+ absolete_path = File.expand_path(path)
476
+ location_path = location[:path]
477
+ location_basename = File.basename(location_path)
478
+ if location_path == absolete_path or location_basename == path
479
+ target_locations << location.merge(:test_case => test_case)
480
+ end
419
481
  end
420
482
  end
483
+ target_locations
421
484
  end
422
- target_locations
423
485
  end
424
486
  end
425
487
 
@@ -441,9 +503,7 @@ module Test
441
503
  def valid? # :nodoc:
442
504
  return false unless respond_to?(@method_name)
443
505
  test_method = method(@method_name)
444
- if @internal_data.have_test_data?
445
- return false unless test_method.arity == 1
446
- else
506
+ unless @internal_data.have_test_data?
447
507
  return false unless test_method.arity <= 0
448
508
  end
449
509
  owner = Util::MethodOwnerFinder.find(self, @method_name)
@@ -508,35 +568,37 @@ module Test
508
568
  #
509
569
  # You can add additional setup tasks by the following
510
570
  # code:
511
- # class TestMyClass < Test::Unit::TestCase
512
- # def setup
513
- # ...
514
- # end
515
571
  #
516
- # setup
517
- # def my_setup1
518
- # ...
519
- # end
572
+ # class TestMyClass < Test::Unit::TestCase
573
+ # def setup
574
+ # ...
575
+ # end
520
576
  #
521
- # setup do
522
- # ... # setup callback1
523
- # end
577
+ # setup
578
+ # def my_setup1
579
+ # ...
580
+ # end
524
581
  #
525
- # setup
526
- # def my_setup2
527
- # ...
528
- # end
582
+ # setup do
583
+ # ... # setup callback1
584
+ # end
529
585
  #
530
- # setup do
531
- # ... # setup callback2
532
- # end
586
+ # setup
587
+ # def my_setup2
588
+ # ...
589
+ # end
590
+ #
591
+ # setup do
592
+ # ... # setup callback2
593
+ # end
533
594
  #
534
- # def test_my_class
535
- # ...
595
+ # def test_my_class
596
+ # ...
597
+ # end
536
598
  # end
537
- # end
538
599
  #
539
600
  # Here is a call order:
601
+ #
540
602
  # * setup
541
603
  # * my_setup1
542
604
  # * setup callback1
@@ -553,35 +615,37 @@ module Test
553
615
  #
554
616
  # You can add additional cleanup tasks by the following
555
617
  # code:
556
- # class TestMyClass < Test::Unit::TestCase
557
- # def cleanup
558
- # ...
559
- # end
560
618
  #
561
- # cleanup
562
- # def my_cleanup1
563
- # ...
564
- # end
619
+ # class TestMyClass < Test::Unit::TestCase
620
+ # def cleanup
621
+ # ...
622
+ # end
565
623
  #
566
- # cleanup do
567
- # ... # cleanup callback1
568
- # end
624
+ # cleanup
625
+ # def my_cleanup1
626
+ # ...
627
+ # end
569
628
  #
570
- # cleanup
571
- # def my_cleanup2
572
- # ...
573
- # end
629
+ # cleanup do
630
+ # ... # cleanup callback1
631
+ # end
574
632
  #
575
- # cleanup do
576
- # ... # cleanup callback2
577
- # end
633
+ # cleanup
634
+ # def my_cleanup2
635
+ # ...
636
+ # end
637
+ #
638
+ # cleanup do
639
+ # ... # cleanup callback2
640
+ # end
578
641
  #
579
- # def test_my_class
580
- # ...
642
+ # def test_my_class
643
+ # ...
644
+ # end
581
645
  # end
582
- # end
583
646
  #
584
647
  # Here is a call order:
648
+ #
585
649
  # * test_my_class
586
650
  # * cleanup callback2
587
651
  # * my_cleanup2
@@ -596,35 +660,37 @@ module Test
596
660
  #
597
661
  # You can add additional teardown tasks by the following
598
662
  # code:
599
- # class TestMyClass < Test::Unit::TestCase
600
- # def teardown
601
- # ...
602
- # end
603
663
  #
604
- # teardown
605
- # def my_teardown1
606
- # ...
607
- # end
664
+ # class TestMyClass < Test::Unit::TestCase
665
+ # def teardown
666
+ # ...
667
+ # end
608
668
  #
609
- # teardown do
610
- # ... # teardown callback1
611
- # end
669
+ # teardown
670
+ # def my_teardown1
671
+ # ...
672
+ # end
612
673
  #
613
- # teardown
614
- # def my_teardown2
615
- # ...
616
- # end
674
+ # teardown do
675
+ # ... # teardown callback1
676
+ # end
617
677
  #
618
- # teardown do
619
- # ... # teardown callback2
620
- # end
678
+ # teardown
679
+ # def my_teardown2
680
+ # ...
681
+ # end
682
+ #
683
+ # teardown do
684
+ # ... # teardown callback2
685
+ # end
621
686
  #
622
- # def test_my_class
623
- # ...
687
+ # def test_my_class
688
+ # ...
689
+ # end
624
690
  # end
625
- # end
626
691
  #
627
692
  # Here is a call order:
693
+ #
628
694
  # * test_my_class
629
695
  # * teardown callback2
630
696
  # * my_teardown2
@@ -644,18 +710,33 @@ module Test
644
710
 
645
711
  # Returns a label of test data for the test. If the
646
712
  # test isn't associated with any test data, it returns
647
- # +nil+.
713
+ # `nil`.
648
714
  def data_label
649
715
  @internal_data.test_data_label
650
716
  end
651
717
 
718
+ # Returns test data for the test. If the test isn't associated
719
+ # with any test data, it returns `nil`.
720
+ def data
721
+ @internal_data.test_data
722
+ end
723
+
652
724
  # Returns a human-readable name for the specific test that
653
725
  # this instance of TestCase represents.
654
726
  def name
727
+ "#{local_name}(#{self.class.name})"
728
+ end
729
+
730
+ # Returns a human-readable name for the specific test that this
731
+ # instance of TestCase represents.
732
+ #
733
+ # `#local_name` doesn't include class name. `#name` includes
734
+ # class name.
735
+ def local_name
655
736
  if @internal_data.have_test_data?
656
- "#{@method_name}[#{data_label}](#{self.class.name})"
737
+ "#{@method_name}[#{data_label}]"
657
738
  else
658
- "#{@method_name}(#{self.class.name})"
739
+ @method_name.to_s
659
740
  end
660
741
  end
661
742
 
@@ -733,13 +814,20 @@ module Test
733
814
  end
734
815
 
735
816
  def run_test
817
+ signature = "#{self.class}\##{@method_name}"
736
818
  redefined_info = self[:redefined]
737
819
  if redefined_info
738
- notify("#{self.class}\##{@method_name} was redefined",
820
+ notify("<#{signature}> was redefined",
739
821
  :backtrace => redefined_info[:backtrace])
740
822
  end
741
823
  if @internal_data.have_test_data?
742
- __send__(@method_name, @internal_data.test_data)
824
+ test_method = method(@method_name)
825
+ arity = test_method.arity
826
+ if arity.zero?
827
+ __send__(@method_name)
828
+ else
829
+ __send__(@method_name, @internal_data.test_data)
830
+ end
743
831
  else
744
832
  __send__(@method_name)
745
833
  end