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
@@ -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-2013 Kouhei Sutou <kou@clear-code.com>
6
+ # * Copyright (c) 2008-2017 Kouhei Sutou <kou@clear-code.com>
7
7
  # License:: Ruby license.
8
8
 
9
9
  begin
@@ -47,6 +47,8 @@ module Test
47
47
  @progress_row_max ||= guess_progress_row_max
48
48
  @show_detail_immediately = @options[:show_detail_immediately]
49
49
  @show_detail_immediately = true if @show_detail_immediately.nil?
50
+ @reverse_output = @options[:reverse_output]
51
+ @reverse_output = @output.tty? if @reverse_output.nil?
50
52
  @already_outputted = false
51
53
  @indent = 0
52
54
  @top_level = true
@@ -110,8 +112,10 @@ module Test
110
112
  end
111
113
 
112
114
  def finished(elapsed_time)
113
- nl if output?(NORMAL) and !output?(VERBOSE)
114
- output_faults unless @show_detail_immediately
115
+ unless @show_detail_immediately
116
+ nl if output?(NORMAL) and !output?(VERBOSE)
117
+ output_faults
118
+ end
115
119
  nl(PROGRESS_ONLY)
116
120
  change_output_level(IMPORTANT_FAULTS_ONLY) do
117
121
  output_statistics(elapsed_time)
@@ -178,22 +182,31 @@ module Test
178
182
 
179
183
  def output_fault_in_detail(fault)
180
184
  if fault.is_a?(Failure) and
181
- fault.inspected_expected and fault.inspected_actual
182
- output_single("#{fault.label}: ")
183
- output(fault.test_name, fault_color(fault))
184
- output_fault_backtrace(fault)
185
- output_failure_message(fault)
185
+ fault.inspected_expected and
186
+ fault.inspected_actual
187
+ if @reverse_output
188
+ output_fault_backtrace(fault)
189
+ output_failure_message(fault)
190
+ output_single("#{fault.label}: ")
191
+ output(fault.test_name, fault_color(fault))
192
+ else
193
+ output_single("#{fault.label}: ")
194
+ output(fault.test_name, fault_color(fault))
195
+ output_fault_backtrace(fault)
196
+ output_failure_message(fault)
197
+ end
186
198
  else
187
- if fault.is_a?(Error)
199
+ if @reverse_output
200
+ output_fault_backtrace(fault)
188
201
  output_single("#{fault.label}: ")
189
202
  output_single(fault.test_name, fault_color(fault))
190
203
  output_fault_message(fault)
191
204
  else
192
- output_single(fault.label, fault_color(fault))
205
+ output_single("#{fault.label}: ")
206
+ output_single(fault.test_name, fault_color(fault))
193
207
  output_fault_message(fault)
194
- output(fault.test_name)
208
+ output_fault_backtrace(fault)
195
209
  end
196
- output_fault_backtrace(fault)
197
210
  end
198
211
  end
199
212
 
@@ -212,26 +225,47 @@ module Test
212
225
  end
213
226
 
214
227
  def output_fault_backtrace(fault)
215
- snippet_is_shown = false
216
228
  detector = FaultLocationDetector.new(fault, @code_snippet_fetcher)
217
229
  backtrace = fault.location
218
230
  # workaround for test-spec. :<
219
231
  # see also GitHub:#22
220
232
  backtrace ||= []
233
+
234
+ code_snippet_backtrace_index = nil
235
+ code_snippet_lines = nil
221
236
  backtrace.each_with_index do |entry, i|
222
- output(entry)
223
- next if snippet_is_shown
224
237
  next unless detector.target?(entry)
225
238
  file, line_number, = detector.split_backtrace_entry(entry)
226
- snippet_is_shown = output_code_snippet(file, line_number,
227
- fault_color(fault))
239
+ lines = fetch_code_snippet(file, line_number)
240
+ unless lines.empty?
241
+ code_snippet_backtrace_index = i
242
+ code_snippet_lines = lines
243
+ break
244
+ end
245
+ end
246
+
247
+ if @reverse_output
248
+ backtrace.each_with_index.reverse_each do |entry, i|
249
+ if i == code_snippet_backtrace_index
250
+ output_code_snippet(code_snippet_lines, fault_color(fault))
251
+ end
252
+ output(entry)
253
+ end
254
+ else
255
+ backtrace.each_with_index do |entry, i|
256
+ output(entry)
257
+ if i == code_snippet_backtrace_index
258
+ output_code_snippet(code_snippet_lines, fault_color(fault))
259
+ end
260
+ end
228
261
  end
229
262
  end
230
263
 
231
- def output_code_snippet(file, line_number, target_line_color=nil)
232
- lines = @code_snippet_fetcher.fetch(file, line_number)
233
- return false if lines.empty?
264
+ def fetch_code_snippet(file, line_number)
265
+ @code_snippet_fetcher.fetch(file, line_number)
266
+ end
234
267
 
268
+ def output_code_snippet(lines, target_line_color=nil)
235
269
  max_n = lines.collect {|n, line, attributes| n}.max
236
270
  digits = (Math.log10(max_n) + 1).truncate
237
271
  lines.each do |n, line, attributes|
@@ -245,7 +279,6 @@ module Test
245
279
  output(" %2s %*d: %s" % [current_line_mark, digits, n, line],
246
280
  line_color)
247
281
  end
248
- true
249
282
  end
250
283
 
251
284
  def output_failure_message(failure)
@@ -303,9 +336,17 @@ module Test
303
336
  end
304
337
 
305
338
  def output_fault_in_short(fault)
306
- output_single(fault.message, fault_color(fault))
307
- output(" [#{fault.test_name}]")
308
- output(fault.location.first)
339
+ if @reverse_output
340
+ output(fault.location.first)
341
+ output_single("#{fault.label}: ")
342
+ output_single(fault.message, fault_color(fault))
343
+ output(" [#{fault.test_name}]")
344
+ else
345
+ output_single("#{fault.label}: ")
346
+ output_single(fault.message, fault_color(fault))
347
+ output(" [#{fault.test_name}]")
348
+ output(fault.location.first)
349
+ end
309
350
  end
310
351
 
311
352
  def format_fault(fault)
@@ -330,24 +371,34 @@ module Test
330
371
  end
331
372
 
332
373
  def output_summary_marker
333
- term_width = guess_term_width
334
- if term_width.zero?
335
- marker_width = 6
374
+ if @progress_row_max > 0
375
+ output("-" * @progress_row_max, summary_marker_color)
336
376
  else
337
- marker_width = term_width
377
+ nl
338
378
  end
339
- output("-" * marker_width, summary_marker_color)
340
379
  end
341
380
 
342
381
  def test_started(test)
343
382
  return unless output?(VERBOSE)
344
383
 
345
- name = test.name.sub(/\(.+?\)\z/, '')
346
- right_space = 8 * 2
384
+ tab_width = 8
385
+ name = test.local_name
386
+ separator = ":"
387
+ left_used = indent.size + name.size + separator.size
388
+ right_space = tab_width * 2
347
389
  left_space = @progress_row_max - right_space
348
- left_space = left_space - indent.size - name.size
349
- tab_stop = "\t" * ([left_space - 1, 0].max / 8)
350
- output_single("#{indent}#{name}:#{tab_stop}", nil, VERBOSE)
390
+ if (left_used % tab_width).zero?
391
+ left_space -= left_used
392
+ n_tabs = 0
393
+ else
394
+ left_space -= ((left_used / tab_width) + 1) * tab_width
395
+ n_tabs = 1
396
+ end
397
+ n_tabs += [left_space, 0].max / tab_width
398
+ tab_stop = "\t" * n_tabs
399
+ output_single("#{indent}#{name}#{separator}#{tab_stop}",
400
+ nil,
401
+ VERBOSE)
351
402
  @test_start = Time.now
352
403
  end
353
404
 
@@ -473,8 +524,12 @@ module Test
473
524
  fault_class.name.split(/::/).last.downcase
474
525
  end
475
526
 
527
+ def fault_class_color(fault_class)
528
+ color(fault_class_color_name(fault_class))
529
+ end
530
+
476
531
  def fault_color(fault)
477
- color(fault_class_color_name(fault.class))
532
+ fault_class_color(fault.class)
478
533
  end
479
534
 
480
535
  def fault_marker_color(fault)
@@ -30,16 +30,16 @@ module Test
30
30
  location_display = "\n" + failure.location.join("\n")
31
31
  end
32
32
  result = "#{failure.label}:\n"
33
- result << "#{failure.test_name}#{location_display}:\n"
34
- result << failure.message
33
+ result += "#{failure.test_name}#{location_display}:\n"
34
+ result += failure.message
35
35
  result
36
36
  end
37
37
 
38
38
  def format_fault_error(error)
39
39
  result = "#{error.label}:\n"
40
- result << "#{error.test_name}:\n"
41
- result << "#{error.message}\n"
42
- result << error.backtrace.join("\n")
40
+ result += "#{error.test_name}:\n"
41
+ result += "#{error.message}\n"
42
+ result += error.backtrace.join("\n")
43
43
  result
44
44
  end
45
45
  end
@@ -26,8 +26,8 @@ module Test
26
26
  # returned, making it very easy to use the proc
27
27
  # itself as the listener_key:
28
28
  #
29
- # listener = add_listener("Channel") { ... }
30
- # remove_listener("Channel", listener)
29
+ # listener = add_listener("Channel") { ... }
30
+ # remove_listener("Channel", listener)
31
31
  def add_listener(channel_name, listener_key=NOTHING, &listener) # :yields: value
32
32
  unless(block_given?)
33
33
  raise ArgumentError.new("No callback was passed as a listener")
@@ -7,10 +7,11 @@ module Test
7
7
  # error as string.
8
8
  #
9
9
  # Example:
10
- # capture_output do
11
- # puts("stdout")
12
- # warn("stderr")
13
- # end # -> ["stdout\n", "stderr\n"]
10
+ #
11
+ # capture_output do
12
+ # puts("stdout")
13
+ # warn("stderr")
14
+ # end # -> ["stdout\n", "stderr\n"]
14
15
  def capture_output
15
16
  require 'stringio'
16
17
 
@@ -31,10 +31,10 @@ module Test
31
31
 
32
32
  def ==(other)
33
33
  case(other)
34
- when ProcWrapper
35
- return @a_proc == other.to_proc
36
- else
37
- return super
34
+ when ProcWrapper
35
+ return @a_proc == other.to_proc
36
+ else
37
+ return super
38
38
  end
39
39
  end
40
40
  alias :eql? :==
@@ -1,5 +1,5 @@
1
1
  module Test
2
2
  module Unit
3
- VERSION = '3.2.0'
3
+ VERSION = "3.3.6"
4
4
  end
5
5
  end
@@ -31,6 +31,8 @@ class TestUnitCollectorDescendant < Test::Unit::TestCase
31
31
  super
32
32
 
33
33
  @test_case1 = Class.new(Test::Unit::TestCase) do
34
+ self.test_order = :alphabetic
35
+
34
36
  def self.name
35
37
  "test-case1"
36
38
  end
@@ -43,6 +45,8 @@ class TestUnitCollectorDescendant < Test::Unit::TestCase
43
45
  end
44
46
 
45
47
  @test_case2 = Class.new(Test::Unit::TestCase) do
48
+ self.test_order = :alphabetic
49
+
46
50
  def self.name
47
51
  "test-case2"
48
52
  end
@@ -20,7 +20,9 @@ class TestUnitCollectorLoad < Test::Unit::TestCase
20
20
 
21
21
  setup
22
22
  def setup_top_level_test_cases
23
- @test_case1 = @test_dir + "test_case1.rb"
23
+ @test_case1_base_name = "test_case1.rb"
24
+
25
+ @test_case1 = @test_dir + @test_case1_base_name
24
26
  @test_case2 = @test_dir + "test_case2.rb"
25
27
  @no_load_test_case3 = @test_dir + "case3.rb"
26
28
 
@@ -66,10 +68,25 @@ EOT
66
68
  @sub_test_dir = @test_dir + "sub"
67
69
  @sub_test_dir.mkpath
68
70
 
71
+ @sub_test_case1 = @sub_test_dir + @test_case1_base_name
69
72
  @sub_test_case4 = @sub_test_dir + "test_case4.rb"
70
73
  @no_load_sub_test_case5 = @sub_test_dir + "case5.rb"
71
74
  @sub_test_case6 = @sub_test_dir + "test_case6.rb"
72
75
 
76
+ @sub_test_case1.open("w") do |test_case|
77
+ test_case.puts(<<-TEST_CASE)
78
+ module #{@temporary_test_cases_module_name}
79
+ class SubTestCase1 < Test::Unit::TestCase
80
+ def test1_1
81
+ end
82
+
83
+ def test1_2
84
+ end
85
+ end
86
+ end
87
+ TEST_CASE
88
+ end
89
+
73
90
  @sub_test_case4.open("w") do |test_case|
74
91
  test_case.puts(<<-EOT)
75
92
  module #{@temporary_test_cases_module_name}
@@ -271,6 +288,9 @@ EOT
271
288
 
272
289
  def test_simple_collect
273
290
  assert_collect([:suite, {:name => @sub_test_dir.basename.to_s},
291
+ [:suite, {:name => _test_case_name("SubTestCase1")},
292
+ [:test, {:name => "test1_1"}],
293
+ [:test, {:name => "test1_2"}]],
274
294
  [:suite, {:name => _test_case_name("SubTestCase4")},
275
295
  [:test, {:name => "test4_1"}],
276
296
  [:test, {:name => "test4_2"}]],
@@ -302,6 +322,9 @@ EOT
302
322
  [:suite, {:name => _test_case_name("TestCase2")},
303
323
  [:test, {:name => "test2"}]],
304
324
  [:suite, {:name => @sub_test_dir.basename.to_s},
325
+ [:suite, {:name => _test_case_name("SubTestCase1")},
326
+ [:test, {:name => "test1_1"}],
327
+ [:test, {:name => "test1_2"}]],
305
328
  [:suite, {:name => _test_case_name("SubTestCase4")},
306
329
  [:test, {:name => "test4_1"}],
307
330
  [:test, {:name => "test4_2"}]],
@@ -356,6 +379,9 @@ EOT
356
379
  [:suite, {:name => _test_case_name("NoLoadSubTestCase5")},
357
380
  [:test, {:name => "test5_1"}],
358
381
  [:test, {:name => "test5_2"}]],
382
+ [:suite, {:name => _test_case_name("SubTestCase1")},
383
+ [:test, {:name => "test1_1"}],
384
+ [:test, {:name => "test1_2"}]],
359
385
  [:suite, {:name => _test_case_name("SubTestCase4")},
360
386
  [:test, {:name => "test4_1"}],
361
387
  [:test, {:name => "test4_2"}]],
@@ -370,7 +396,11 @@ EOT
370
396
  assert_collect([:suite, {:name => "."},
371
397
  [:suite, {:name => _test_case_name("TestCase1")},
372
398
  [:test, {:name => "test1_1"}],
373
- [:test, {:name => "test1_2"}]]]) do |collector|
399
+ [:test, {:name => "test1_2"}]],
400
+ [:suite, {:name => @sub_test_dir.basename.to_s},
401
+ [:suite, {:name => _test_case_name("SubTestCase1")},
402
+ [:test, {:name => "test1_1"}],
403
+ [:test, {:name => "test1_2"}]]]]) do |collector|
374
404
  collector.filter = Proc.new do |test|
375
405
  !/\Atest1/.match(test.method_name).nil?
376
406
  end
@@ -381,6 +411,9 @@ EOT
381
411
  test_dirs = [@sub_test_dir.to_s, @sub2_test_dir.to_s]
382
412
  assert_collect([:suite, {:name => "[#{test_dirs.join(', ')}]"},
383
413
  [:suite, {:name => @sub_test_dir.basename.to_s},
414
+ [:suite, {:name => _test_case_name("SubTestCase1")},
415
+ [:test, {:name => "test1_1"}],
416
+ [:test, {:name => "test1_2"}]],
384
417
  [:suite, {:name => _test_case_name("SubTestCase4")},
385
418
  [:test, {:name => "test4_1"}],
386
419
  [:test, {:name => "test4_2"}]],
@@ -15,7 +15,7 @@ module Test
15
15
  @contents = {'.' => self, '..' => parent}
16
16
  instance_eval(&block) if(block)
17
17
  end
18
-
18
+
19
19
  def file(name, contents)
20
20
  @contents[name] = contents
21
21
  end
@@ -74,7 +74,7 @@ module Test
74
74
  end
75
75
 
76
76
  attr_reader :object_space
77
-
77
+
78
78
  def initialize(&block)
79
79
  @root = Directory.new('/', self, &block)
80
80
  @pwd = @root
@@ -295,7 +295,7 @@ module Test
295
295
  assert_raises(LoadError) do
296
296
  fs.require('bogus')
297
297
  end
298
-
298
+
299
299
  assert(fs.require('test_class1.rb'))
300
300
  assert(!fs.require('test_class1.rb'))
301
301
  c = []
@@ -345,6 +345,7 @@ module Test
345
345
  def create_test(name)
346
346
  t = Class.new(TestCase)
347
347
  t.class_eval <<-EOC
348
+ self.test_order = :alphabetic
348
349
  def self.name
349
350
  "T\#{#{name}}"
350
351
  end
@@ -373,7 +374,7 @@ module Test
373
374
  expected = TestSuite.new('test_1.rb')
374
375
  expected << @t1.suite
375
376
  assert_equal(expected, @c.collect('test_1.rb'))
376
-
377
+
377
378
  expected = TestSuite.new('t4.rb')
378
379
  expected << @t4.suite
379
380
  assert_equal(expected, @c.collect('t4.rb'))
@@ -11,6 +11,7 @@ module Test
11
11
  class TC_ObjectSpace < TestCase
12
12
  def setup
13
13
  @tc1 = Class.new(TestCase) do
14
+ self.test_order = :alphabetic
14
15
  def self.name
15
16
  "tc_1"
16
17
  end
@@ -21,6 +22,7 @@ module Test
21
22
  end
22
23
 
23
24
  @tc2 = Class.new(TestCase) do
25
+ self.test_order = :alphabetic
24
26
  def self.name
25
27
  "tc_2"
26
28
  end
@@ -32,7 +34,7 @@ module Test
32
34
  def test_4
33
35
  end
34
36
  end
35
-
37
+
36
38
  @object_space = {Class => [@tc1, @tc2, @no_tc], String => ['']}
37
39
  def @object_space.each_object(type)
38
40
  self[type].each{|item| yield(item) }
@@ -50,14 +52,14 @@ module Test
50
52
  def empty_suite
51
53
  TestSuite.new(ObjectSpace::NAME)
52
54
  end
53
-
55
+
54
56
  def test_basic_collection
55
57
  assert_equal(full_suite("name"), @c.collect("name"))
56
58
 
57
59
  @c.filter = []
58
60
  assert_equal(full_suite("name"), @c.collect("name"))
59
61
  end
60
-
62
+
61
63
  def test_filtered_collection
62
64
  @c.filter = proc{false}
63
65
  assert_equal(empty_suite, @c.collect)
@@ -76,10 +78,10 @@ module Test
76
78
 
77
79
  @c.filter = [proc{nil}, proc{false}]
78
80
  assert_equal(empty_suite, @c.collect)
79
-
81
+
80
82
  @c.filter = [proc{nil}, proc{true}]
81
83
  assert_equal(full_suite, @c.collect)
82
-
84
+
83
85
  expected = TestSuite.new(ObjectSpace::NAME)
84
86
  expected << (TestSuite.new(@tc1.name) << @tc1.new('test_1'))
85
87
  expected << (TestSuite.new(@tc2.name) << @tc2.new('test_0'))