test-unit 3.2.0 → 3.3.6

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