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.
- checksums.yaml +5 -5
- data/COPYING +4 -1
- data/README.md +11 -11
- data/Rakefile +10 -1
- data/doc/text/getting-started.md +246 -0
- data/doc/text/news.md +372 -1
- data/lib/test/unit.rb +171 -157
- data/lib/test/unit/assertions.rb +187 -149
- data/lib/test/unit/attribute.rb +71 -2
- data/lib/test/unit/autorunner.rb +65 -32
- data/lib/test/unit/code-snippet-fetcher.rb +7 -7
- data/lib/test/unit/collector/load.rb +8 -13
- data/lib/test/unit/data-sets.rb +116 -0
- data/lib/test/unit/data.rb +121 -12
- data/lib/test/unit/diff.rb +11 -11
- data/lib/test/unit/fixture.rb +3 -0
- data/lib/test/unit/notification.rb +9 -7
- data/lib/test/unit/omission.rb +34 -31
- data/lib/test/unit/pending.rb +12 -11
- data/lib/test/unit/priority.rb +7 -3
- data/lib/test/unit/runner/console.rb +25 -0
- data/lib/test/unit/test-suite-creator.rb +22 -8
- data/lib/test/unit/testcase.rb +270 -182
- data/lib/test/unit/ui/console/testrunner.rb +90 -35
- data/lib/test/unit/ui/emacs/testrunner.rb +5 -5
- data/lib/test/unit/util/observable.rb +2 -2
- data/lib/test/unit/util/output.rb +5 -4
- data/lib/test/unit/util/procwrapper.rb +4 -4
- data/lib/test/unit/version.rb +1 -1
- data/test/collector/test-descendant.rb +4 -0
- data/test/collector/test-load.rb +35 -2
- data/test/collector/test_dir.rb +5 -4
- data/test/collector/test_objectspace.rb +7 -5
- data/test/test-assertions.rb +128 -101
- data/test/test-code-snippet.rb +42 -0
- data/test/test-data.rb +195 -79
- data/test/test-priority.rb +19 -8
- data/test/test-test-case.rb +111 -3
- data/test/test-test-suite.rb +1 -0
- data/test/testunit-test-util.rb +2 -0
- 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-
|
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
|
-
|
114
|
-
|
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
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
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
|
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
|
205
|
+
output_single("#{fault.label}: ")
|
206
|
+
output_single(fault.test_name, fault_color(fault))
|
193
207
|
output_fault_message(fault)
|
194
|
-
|
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
|
-
|
227
|
-
|
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
|
232
|
-
|
233
|
-
|
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
|
-
|
307
|
-
|
308
|
-
|
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
|
-
|
334
|
-
|
335
|
-
marker_width = 6
|
374
|
+
if @progress_row_max > 0
|
375
|
+
output("-" * @progress_row_max, summary_marker_color)
|
336
376
|
else
|
337
|
-
|
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
|
-
|
346
|
-
|
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
|
-
|
349
|
-
|
350
|
-
|
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
|
-
|
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
|
34
|
-
result
|
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
|
41
|
-
result
|
42
|
-
result
|
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
|
-
#
|
30
|
-
#
|
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
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
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
|
|
data/lib/test/unit/version.rb
CHANGED
@@ -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
|
data/test/collector/test-load.rb
CHANGED
@@ -20,7 +20,9 @@ class TestUnitCollectorLoad < Test::Unit::TestCase
|
|
20
20
|
|
21
21
|
setup
|
22
22
|
def setup_top_level_test_cases
|
23
|
-
@
|
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"}]]
|
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"}]],
|
data/test/collector/test_dir.rb
CHANGED
@@ -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'))
|