test-unit 2.0.3 → 2.0.4

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.
@@ -69,18 +69,20 @@ module Test
69
69
  end
70
70
  end
71
71
 
72
+ NOT_PASS_THROUGH_EXCEPTIONS = []
72
73
  PASS_THROUGH_EXCEPTIONS = [NoMemoryError, SignalException, Interrupt,
73
74
  SystemExit]
74
75
  private
75
76
  def handle_all_exception(exception)
76
77
  case exception
78
+ when *NOT_PASS_THROUGH_EXCEPTIONS
77
79
  when *PASS_THROUGH_EXCEPTIONS
78
- false
79
- else
80
- problem_occurred
81
- add_error(exception)
82
- true
80
+ return false
83
81
  end
82
+
83
+ problem_occurred
84
+ add_error(exception)
85
+ true
84
86
  end
85
87
 
86
88
  def add_error(exception)
@@ -11,16 +11,23 @@ module Test
11
11
  # when an assertion fails.
12
12
  class Failure
13
13
  attr_reader :test_name, :location, :message
14
-
14
+ attr_reader :expected, :actual, :user_message
15
+ attr_reader :inspected_expected, :inspected_actual
16
+
15
17
  SINGLE_CHARACTER = 'F'
16
18
  LABEL = "Failure"
17
19
 
18
20
  # Creates a new Failure with the given location and
19
21
  # message.
20
- def initialize(test_name, location, message)
22
+ def initialize(test_name, location, message, options={})
21
23
  @test_name = test_name
22
24
  @location = location
23
25
  @message = message
26
+ @expected = options[:expected]
27
+ @actual = options[:actual]
28
+ @inspected_expected = options[:inspected_expected]
29
+ @inspected_actual = options[:inspected_actual]
30
+ @user_message = options[:user_message]
24
31
  end
25
32
 
26
33
  # Returns a single character representation of a failure.
@@ -51,6 +58,15 @@ module Test
51
58
  def to_s
52
59
  long_display
53
60
  end
61
+
62
+ def diff
63
+ @diff ||= compute_diff
64
+ end
65
+
66
+ private
67
+ def compute_diff
68
+ Assertions::AssertionMessage.delayed_diff(@expected, @actual).inspect
69
+ end
54
70
  end
55
71
 
56
72
  module FailureHandler
@@ -64,12 +80,18 @@ module Test
64
80
  def handle_assertion_failed_error(exception)
65
81
  return false unless exception.is_a?(AssertionFailedError)
66
82
  problem_occurred
67
- add_failure(exception.message, exception.backtrace)
83
+ add_failure(exception.message, exception.backtrace,
84
+ :expected => exception.expected,
85
+ :actual => exception.actual,
86
+ :inspected_expected => exception.inspected_expected,
87
+ :inspected_actual => exception.inspected_actual,
88
+ :user_message => exception.user_message)
68
89
  true
69
90
  end
70
91
 
71
- def add_failure(message, backtrace)
72
- failure = Failure.new(name, filter_backtrace(backtrace), message)
92
+ def add_failure(message, backtrace, options={})
93
+ failure = Failure.new(name, filter_backtrace(backtrace), message,
94
+ options)
73
95
  current_result.add_failure(failure)
74
96
  end
75
97
  end
@@ -0,0 +1,8 @@
1
+ module Test
2
+ module Unit
3
+ AutoRunner.register_runner(:tap) do |auto_runner|
4
+ require 'test/unit/ui/tap/testrunner'
5
+ Test::Unit::UI::Tap::TestRunner
6
+ end
7
+ end
8
+ end
@@ -1,7 +1,9 @@
1
1
  #--
2
2
  #
3
3
  # Author:: Nathaniel Talbott.
4
- # Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
4
+ # Copyright::
5
+ # * Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
6
+ # * Copyright (c) 2008-2009 Kouhei Sutou <kou@clear-code.com>
5
7
  # License:: Ruby license.
6
8
 
7
9
  require 'test/unit/color-scheme'
@@ -36,6 +38,9 @@ module Test
36
38
  @progress_row_max = @options[:progress_row_max]
37
39
  @progress_row_max ||= guess_progress_row_max
38
40
  @already_outputted = false
41
+ @n_successes = 0
42
+ @indent = 0
43
+ @top_level = true
39
44
  @faults = []
40
45
  end
41
46
 
@@ -68,6 +73,8 @@ module Test
68
73
  @mediator.add_listener(TestRunnerMediator::FINISHED, &method(:finished))
69
74
  @mediator.add_listener(TestCase::STARTED, &method(:test_started))
70
75
  @mediator.add_listener(TestCase::FINISHED, &method(:test_finished))
76
+ @mediator.add_listener(TestSuite::STARTED, &method(:test_suite_started))
77
+ @mediator.add_listener(TestSuite::FINISHED, &method(:test_suite_finished))
71
78
  end
72
79
 
73
80
  def start_mediator
@@ -91,35 +98,140 @@ module Test
91
98
 
92
99
  def finished(elapsed_time)
93
100
  nl if output?(NORMAL) and !output?(VERBOSE)
94
- nl
95
- output("Finished in #{elapsed_time} seconds.")
96
101
  @faults.each_with_index do |fault, index|
97
102
  nl
98
103
  output_single("%3d) " % (index + 1))
104
+ output_fault(fault)
105
+ end
106
+ nl
107
+ output("Finished in #{elapsed_time} seconds.")
108
+ nl
109
+ output(@result, result_color)
110
+ n_tests = @result.run_count
111
+ if n_tests.zero?
112
+ pass_percentage = 0
113
+ else
114
+ pass_percentage = 100.0 * (@n_successes / n_tests.to_f)
115
+ end
116
+ output("%g%% passed" % pass_percentage, result_color)
117
+ end
118
+
119
+ def output_fault(fault)
120
+ if @use_color and fault.is_a?(Failure) and
121
+ fault.inspected_expected and fault.inspected_actual
122
+ output_single(fault.label, fault_color(fault))
123
+ output(":")
124
+ output_fault_backtrace(fault)
125
+ output_fault_message(fault)
126
+ else
99
127
  label, detail = format_fault(fault).split(/\r?\n/, 2)
100
128
  output(label, fault_color(fault))
101
129
  output(detail)
102
130
  end
103
- nl
104
- output(@result, result_color)
131
+ end
132
+
133
+ def output_fault_backtrace(fault)
134
+ backtrace = fault.location
135
+ if backtrace.size == 1
136
+ output(fault.test_name +
137
+ backtrace[0].sub(/\A(.+:\d+).*/, ' [\\1]') +
138
+ ":")
139
+ else
140
+ output(fault.test_name)
141
+ backtrace.each_with_index do |entry, i|
142
+ if i.zero?
143
+ prefix = "["
144
+ postfix = ""
145
+ elsif i == backtrace.size - 1
146
+ prefix = " "
147
+ postfix = "]:"
148
+ else
149
+ prefix = " "
150
+ postfix = ""
151
+ end
152
+ output(" #{prefix}#{entry}#{postfix}")
153
+ end
154
+ end
155
+ end
156
+
157
+ def output_fault_message(fault)
158
+ output(fault.user_message) if fault.user_message
159
+ output_single("<")
160
+ output_single(fault.inspected_expected, color("success"))
161
+ output("> expected but was")
162
+ output_single("<")
163
+ output_single(fault.inspected_actual, color("failure"))
164
+ output(">")
165
+ from, to = prepare_for_diff(fault.expected, fault.actual)
166
+ if from and to
167
+ differ = ColorizedReadableDiffer.new(from.split(/\r?\n/),
168
+ to.split(/\r?\n/),
169
+ self)
170
+ if differ.need_diff?
171
+ output("")
172
+ output("diff:")
173
+ differ.diff
174
+ end
175
+ end
105
176
  end
106
177
 
107
178
  def format_fault(fault)
108
179
  fault.long_display
109
180
  end
110
-
181
+
111
182
  def test_started(name)
112
- output_single(name + ": ", nil, VERBOSE)
183
+ return unless output?(VERBOSE)
184
+
185
+ name = name.sub(/\(.+?\)\z/, '')
186
+ right_space = 8 * 2
187
+ left_space = @progress_row_max - right_space
188
+ left_space = left_space - indent.size - name.size
189
+ tab_stop = "\t" * ((left_space - 1) / 8)
190
+ output_single("#{indent}#{name}:#{tab_stop}", nil, VERBOSE)
191
+ @test_start = Time.now
113
192
  end
114
-
193
+
115
194
  def test_finished(name)
116
195
  unless @already_outputted
196
+ @n_successes += 1
117
197
  output_progress(".", color("success"))
118
198
  end
119
- nl(VERBOSE)
120
199
  @already_outputted = false
200
+
201
+ return unless output?(VERBOSE)
202
+
203
+ output(": (%f)" % (Time.now - @test_start), nil, VERBOSE)
121
204
  end
122
-
205
+
206
+ def test_suite_started(name)
207
+ if @top_level
208
+ @top_level = false
209
+ return
210
+ end
211
+
212
+ output_single(indent, nil, VERBOSE)
213
+ if /\A[A-Z]/ =~ name
214
+ _color = color("case")
215
+ else
216
+ _color = color("suite")
217
+ end
218
+ output_single(name, _color, VERBOSE)
219
+ output(": ", nil, VERBOSE)
220
+ @indent += 2
221
+ end
222
+
223
+ def test_suite_finished(name)
224
+ @indent -= 2
225
+ end
226
+
227
+ def indent
228
+ if output?(VERBOSE)
229
+ " " * @indent
230
+ else
231
+ ""
232
+ end
233
+ end
234
+
123
235
  def nl(level=NORMAL)
124
236
  output("", nil, level)
125
237
  end
@@ -213,6 +325,135 @@ module Test
213
325
  0
214
326
  end
215
327
  end
328
+
329
+ class ColorizedReadableDiffer < Diff::ReadableDiffer
330
+ def initialize(from, to, runner)
331
+ @runner = runner
332
+ super(from, to)
333
+ end
334
+
335
+ def need_diff?(options={})
336
+ operations.each do |tag,|
337
+ return true if [:replace, :equal].include?(tag)
338
+ end
339
+ false
340
+ end
341
+
342
+ private
343
+ def output_single(something, color=nil)
344
+ @runner.send(:output_single, something, color)
345
+ end
346
+
347
+ def output(something, color=nil)
348
+ @runner.send(:output, something, color)
349
+ end
350
+
351
+ def color(name)
352
+ @runner.send(:color, name)
353
+ end
354
+
355
+ def cut_off_ratio
356
+ 0
357
+ end
358
+
359
+ def default_ratio
360
+ 0
361
+ end
362
+
363
+ def tag(mark, color_name, contents)
364
+ _color = color(color_name)
365
+ contents.each do |content|
366
+ output_single(mark, _color)
367
+ output_single(" ")
368
+ output(content)
369
+ end
370
+ end
371
+
372
+ def tag_deleted(contents)
373
+ tag("-", "diff-deleted-tag", contents)
374
+ end
375
+
376
+ def tag_inserted(contents)
377
+ tag("+", "diff-inserted-tag", contents)
378
+ end
379
+
380
+ def tag_equal(contents)
381
+ tag(" ", "normal", contents)
382
+ end
383
+
384
+ def tag_difference(contents)
385
+ tag("?", "diff-difference-tag", contents)
386
+ end
387
+
388
+ def diff_line(from_line, to_line)
389
+ to_operations = []
390
+ from_line, to_line, _operations = line_operations(from_line, to_line)
391
+
392
+ no_replace = true
393
+ _operations.each do |tag,|
394
+ if tag == :replace
395
+ no_replace = false
396
+ break
397
+ end
398
+ end
399
+
400
+ output_single("?", color("diff-difference-tag"))
401
+ output_single(" ")
402
+ _operations.each do |tag, from_start, from_end, to_start, to_end|
403
+ from_width = compute_width(from_line, from_start, from_end)
404
+ to_width = compute_width(to_line, to_start, to_end)
405
+ case tag
406
+ when :replace
407
+ output_single(from_line[from_start...from_end],
408
+ color("diff-deleted"))
409
+ if (from_width < to_width)
410
+ output_single(" " * (to_width - from_width))
411
+ end
412
+ to_operations << Proc.new do
413
+ output_single(to_line[to_start...to_end],
414
+ color("diff-inserted"))
415
+ if (to_width < from_width)
416
+ output_single(" " * (from_width - to_width))
417
+ end
418
+ end
419
+ when :delete
420
+ output_single(from_line[from_start...from_end],
421
+ color("diff-deleted"))
422
+ unless no_replace
423
+ to_operations << Proc.new {output_single(" " * from_width)}
424
+ end
425
+ when :insert
426
+ if no_replace
427
+ output_single(to_line[to_start...to_end],
428
+ color("diff-inserted"))
429
+ else
430
+ output_single(" " * to_width)
431
+ to_operations << Proc.new do
432
+ output_single(to_line[to_start...to_end],
433
+ color("diff-inserted"))
434
+ end
435
+ end
436
+ when :equal
437
+ output_single(from_line[from_start...from_end])
438
+ unless no_replace
439
+ to_operations << Proc.new {output_single(" " * to_width)}
440
+ end
441
+ else
442
+ raise "unknown tag: #{tag}"
443
+ end
444
+ end
445
+ output("")
446
+
447
+ unless to_operations.empty?
448
+ output_single("?", color("diff-difference-tag"))
449
+ output_single(" ")
450
+ to_operations.each do |operation|
451
+ operation.call
452
+ end
453
+ output("")
454
+ end
455
+ end
456
+ end
216
457
  end
217
458
  end
218
459
  end
@@ -22,6 +22,20 @@ module Test
22
22
  end
23
23
  end
24
24
 
25
+ def output_fault_backtrace(fault)
26
+ backtrace = fault.location
27
+ if backtrace.size == 1
28
+ output(fault.test_name +
29
+ backtrace[0].sub(/\A(.+:\d+).*/, ' [\\1]') +
30
+ ":")
31
+ else
32
+ output(fault.test_name)
33
+ backtrace.each do |entry|
34
+ output(entry)
35
+ end
36
+ end
37
+ end
38
+
25
39
  def format_fault_failure(failure)
26
40
  if failure.location.size == 1
27
41
  location = failure.location[0]
@@ -0,0 +1,92 @@
1
+ #--
2
+ #
3
+ # Author:: Kouhei Sutou.
4
+ # Copyright:: Copyright (c) 2009 Kouhei Sutou <kou@clear-code.com>.
5
+ # License:: Ruby license.
6
+
7
+ require 'test/unit/ui/testrunner'
8
+ require 'test/unit/ui/testrunnermediator'
9
+
10
+ module Test
11
+ module Unit
12
+ module UI
13
+ module Tap
14
+
15
+ # Runs a Test::Unit::TestSuite and outputs result
16
+ # as TAP format.
17
+ class TestRunner < UI::TestRunner
18
+ def initialize(suite, options={})
19
+ super
20
+ @output = @options[:output] || STDOUT
21
+ @n_tests = 0
22
+ @already_outputted = false
23
+ end
24
+
25
+ # Begins the test run.
26
+ def start
27
+ setup_mediator
28
+ result = start_mediator
29
+ def result.passed?
30
+ true # for prove commend :<
31
+ end
32
+ result
33
+ end
34
+
35
+ private
36
+ def setup_mediator
37
+ @mediator = TestRunnerMediator.new(@suite)
38
+ attach_to_mediator
39
+ end
40
+
41
+ def attach_to_mediator
42
+ @mediator.add_listener(TestResult::FAULT, &method(:add_fault))
43
+ @mediator.add_listener(TestRunnerMediator::STARTED, &method(:started))
44
+ @mediator.add_listener(TestRunnerMediator::FINISHED, &method(:finished))
45
+ @mediator.add_listener(TestCase::STARTED, &method(:test_started))
46
+ @mediator.add_listener(TestCase::FINISHED, &method(:test_finished))
47
+ end
48
+
49
+ def start_mediator
50
+ @mediator.run_suite
51
+ end
52
+
53
+ def add_fault(fault)
54
+ puts("not ok #{@n_tests} - #{fault.short_display}")
55
+ fault.long_display.each_line do |line|
56
+ puts("# #{line}")
57
+ end
58
+ @already_outputted = true
59
+ end
60
+
61
+ def started(result)
62
+ @result = result
63
+ puts("1..#{@suite.size}")
64
+ end
65
+
66
+ def finished(elapsed_time)
67
+ puts("# Finished in #{elapsed_time} seconds.")
68
+ @result.to_s.each_line do |line|
69
+ puts("# #{line}")
70
+ end
71
+ end
72
+
73
+ def test_started(name)
74
+ @n_tests += 1
75
+ end
76
+
77
+ def test_finished(name)
78
+ unless @already_outputted
79
+ puts("ok #{@n_tests} - #{name}")
80
+ end
81
+ @already_outputted = false
82
+ end
83
+
84
+ def puts(*args)
85
+ @output.puts(*args)
86
+ @output.flush
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end