test-unit 2.2.0 → 2.3.0

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.
@@ -31,8 +31,10 @@ module Test
31
31
  include TestResultOmissionSupport
32
32
  include TestResultNotificationSupport
33
33
 
34
- CHANGED = "CHANGED"
35
- FAULT = "FAULT"
34
+ FINISHED = name + "::FINISHED"
35
+ CHANGED = name + "::CHANGED"
36
+ PASS_ASSERTION = name + "::PASS_ASSERTION"
37
+ FAULT = name + "::FAULT"
36
38
 
37
39
  attr_reader :run_count, :pass_count, :assertion_count, :faults
38
40
 
@@ -48,6 +50,7 @@ module Test
48
50
  # Records a test run.
49
51
  def add_run
50
52
  @run_count += 1
53
+ notify_listeners(FINISHED, self)
51
54
  notify_changed
52
55
  end
53
56
 
@@ -58,6 +61,7 @@ module Test
58
61
  # Records an individual assertion.
59
62
  def add_assertion
60
63
  @assertion_count += 1
64
+ notify_listeners(PASS_ASSERTION, self)
61
65
  notify_changed
62
66
  end
63
67
 
@@ -18,14 +18,16 @@ module Test
18
18
  # has a suite method as simply providing a way to get a
19
19
  # meaningful TestSuite instance.
20
20
  class TestSuite
21
- attr_reader :name, :tests
21
+ attr_reader :name, :tests, :test_case, :start_time, :elapsed_time
22
22
 
23
23
  # Test suite that has higher priority is ran prior to
24
24
  # test suites that have lower priority.
25
25
  attr_accessor :priority
26
26
 
27
27
  STARTED = name + "::STARTED"
28
+ STARTED_OBJECT = name + "::STARTED::OBJECT"
28
29
  FINISHED = name + "::FINISHED"
30
+ FINISHED_OBJECT = name + "::FINISHED::OBJECT"
29
31
 
30
32
  # Creates a new TestSuite with the given name.
31
33
  def initialize(name="Unnamed TestSuite", test_case=nil)
@@ -34,19 +36,28 @@ module Test
34
36
  @test_case = test_case
35
37
  @n_tests = 0
36
38
  @priority = 0
39
+ @start_time = nil
40
+ @elapsed_time = nil
41
+ @passed = true
37
42
  end
38
43
 
39
44
  # Runs the tests and/or suites contained in this
40
45
  # TestSuite.
41
46
  def run(result, &progress_block)
47
+ @start_time = Time.now
42
48
  yield(STARTED, name)
49
+ yield(STARTED_OBJECT, self)
43
50
  run_startup(result)
44
51
  while test = @tests.shift
45
52
  @n_tests += test.size
46
53
  test.run(result, &progress_block)
54
+ @passed = false unless test.passed?
47
55
  end
48
56
  run_shutdown(result)
57
+ ensure
58
+ @elapsed_time = Time.now - @start_time
49
59
  yield(FINISHED, name)
60
+ yield(FINISHED_OBJECT, self)
50
61
  end
51
62
 
52
63
  # Adds the test to the suite.
@@ -85,6 +96,10 @@ module Test
85
96
  @tests == other.tests
86
97
  end
87
98
 
99
+ def passed?
100
+ @passed
101
+ end
102
+
88
103
  private
89
104
  def run_startup(result)
90
105
  return if @test_case.nil? or !@test_case.respond_to?(:startup)
@@ -110,6 +125,7 @@ module Test
110
125
  false
111
126
  else
112
127
  result.add_error(Error.new(@test_case.name, exception))
128
+ @passed = false
113
129
  true
114
130
  end
115
131
  end
@@ -0,0 +1,79 @@
1
+ #--
2
+ #
3
+ # Author:: Kouhei Sutou
4
+ # Copyright::
5
+ # * Copyright (c) 2011 Kouhei Sutou <tt><kou@clear-code.com></tt>
6
+ # License:: Ruby license.
7
+
8
+ module Test
9
+ module Unit
10
+ class TestSuiteCreator # :nodoc:
11
+ def initialize(test_case)
12
+ @test_case = test_case
13
+ end
14
+
15
+ def create
16
+ suite = TestSuite.new(@test_case.name, @test_case)
17
+ collect_test_names.each do |test_name|
18
+ data_sets = @test_case.attributes(test_name)[:data]
19
+ if data_sets
20
+ data_sets.each do |data_set|
21
+ data_set = data_set.call if data_set.respond_to?(:call)
22
+ data_set.each do |label, data|
23
+ append_test(suite, test_name) do |test|
24
+ test.assign_test_data(label, data)
25
+ end
26
+ end
27
+ end
28
+ else
29
+ append_test(suite, test_name)
30
+ end
31
+ end
32
+ append_test(suite, "default_test") if suite.empty?
33
+ suite
34
+ end
35
+
36
+ private
37
+ def append_test(suite, test_name)
38
+ test = @test_case.new(test_name)
39
+ yield(test) if block_given?
40
+ suite << test if test.valid?
41
+ end
42
+
43
+ def collect_test_names
44
+ method_names = @test_case.public_instance_methods(true).collect do |name|
45
+ name.to_s
46
+ end
47
+ test_names = method_names.find_all do |method_name|
48
+ method_name =~ /^test./ or @test_case.attributes(method_name)[:test]
49
+ end
50
+ send("sort_test_names_in_#{@test_case.test_order}_order", test_names)
51
+ end
52
+
53
+ def sort_test_names_in_alphabetic_order(test_names)
54
+ test_names.sort
55
+ end
56
+
57
+ def sort_test_names_in_random_order(test_names)
58
+ test_names.sort_by {rand(test_names.size)}
59
+ end
60
+
61
+ def sort_test_names_in_defined_order(test_names)
62
+ added_methods = @test_case.added_methods
63
+ test_names.sort do |test1, test2|
64
+ test1_defined_order = added_methods.index(test1)
65
+ test2_defined_order = added_methods.index(test2)
66
+ if test1_defined_order and test2_defined_order
67
+ test1_defined_order <=> test2_defined_order
68
+ elsif test1_defined_order
69
+ 1
70
+ elsif test2_defined_order
71
+ -1
72
+ else
73
+ test1 <=> test2
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -56,13 +56,20 @@ module Test
56
56
  end
57
57
 
58
58
  def attach_to_mediator
59
- @mediator.add_listener(TestResult::FAULT, &method(:add_fault))
60
- @mediator.add_listener(TestRunnerMediator::STARTED, &method(:started))
61
- @mediator.add_listener(TestRunnerMediator::FINISHED, &method(:finished))
62
- @mediator.add_listener(TestCase::STARTED, &method(:test_started))
63
- @mediator.add_listener(TestCase::FINISHED, &method(:test_finished))
64
- @mediator.add_listener(TestSuite::STARTED, &method(:test_suite_started))
65
- @mediator.add_listener(TestSuite::FINISHED, &method(:test_suite_finished))
59
+ @mediator.add_listener(TestResult::FAULT,
60
+ &method(:add_fault))
61
+ @mediator.add_listener(TestRunnerMediator::STARTED,
62
+ &method(:started))
63
+ @mediator.add_listener(TestRunnerMediator::FINISHED,
64
+ &method(:finished))
65
+ @mediator.add_listener(TestCase::STARTED_OBJECT,
66
+ &method(:test_started))
67
+ @mediator.add_listener(TestCase::FINISHED_OBJECT,
68
+ &method(:test_finished))
69
+ @mediator.add_listener(TestSuite::STARTED_OBJECT,
70
+ &method(:test_suite_started))
71
+ @mediator.add_listener(TestSuite::FINISHED_OBJECT,
72
+ &method(:test_suite_finished))
66
73
  end
67
74
 
68
75
  def add_fault(fault)
@@ -191,10 +198,10 @@ module Test
191
198
  fault.long_display
192
199
  end
193
200
 
194
- def test_started(name)
201
+ def test_started(test)
195
202
  return unless output?(VERBOSE)
196
203
 
197
- name = name.sub(/\(.+?\)\z/, '')
204
+ name = test.name.sub(/\(.+?\)\z/, '')
198
205
  right_space = 8 * 2
199
206
  left_space = @progress_row_max - right_space
200
207
  left_space = left_space - indent.size - name.size
@@ -203,7 +210,7 @@ module Test
203
210
  @test_start = Time.now
204
211
  end
205
212
 
206
- def test_finished(name)
213
+ def test_finished(test)
207
214
  unless @already_outputted
208
215
  output_progress(".", color("pass"))
209
216
  end
@@ -214,24 +221,24 @@ module Test
214
221
  output(": (%f)" % (Time.now - @test_start), nil, VERBOSE)
215
222
  end
216
223
 
217
- def test_suite_started(name)
224
+ def test_suite_started(suite)
218
225
  if @top_level
219
226
  @top_level = false
220
227
  return
221
228
  end
222
229
 
223
230
  output_single(indent, nil, VERBOSE)
224
- if /\A[A-Z]/ =~ name
225
- _color = color("case")
226
- else
231
+ if suite.test_case.nil?
227
232
  _color = color("suite")
233
+ else
234
+ _color = color("case")
228
235
  end
229
- output_single(name, _color, VERBOSE)
236
+ output_single(suite.name, _color, VERBOSE)
230
237
  output(": ", nil, VERBOSE)
231
238
  @indent += 2
232
239
  end
233
240
 
234
- def test_suite_finished(name)
241
+ def test_suite_finished(suite)
235
242
  @indent -= 2
236
243
  end
237
244
 
@@ -458,7 +465,3 @@ module Test
458
465
  end
459
466
  end
460
467
  end
461
-
462
- if __FILE__ == $0
463
- Test::Unit::UI::Console::TestRunner.start_command_line_test
464
- end
@@ -33,9 +33,15 @@ module Test
33
33
  Unit.run = true
34
34
 
35
35
  result = create_result
36
- result_listener = result.add_listener(TestResult::CHANGED) do |*args|
36
+ finished_listener = result.add_listener(TestResult::FINISHED) do |*args|
37
+ notify_listeners(TestResult::FINISHED, *args)
38
+ end
39
+ changed_listener = result.add_listener(TestResult::CHANGED) do |*args|
37
40
  notify_listeners(TestResult::CHANGED, *args)
38
41
  end
42
+ pass_assertion_listener = result.add_listener(TestResult::PASS_ASSERTION) do |*args|
43
+ notify_listeners(TestResult::PASS_ASSERTION, *args)
44
+ end
39
45
  fault_listener = result.add_listener(TestResult::FAULT) do |*args|
40
46
  notify_listeners(TestResult::FAULT, *args)
41
47
  end
@@ -51,7 +57,10 @@ module Test
51
57
  ensure
52
58
  elapsed_time = Time.now - start_time
53
59
  result.remove_listener(TestResult::FAULT, fault_listener)
54
- result.remove_listener(TestResult::CHANGED, result_listener)
60
+ result.remove_listener(TestResult::CHANGED, changed_listener)
61
+ result.remove_listener(TestResult::FINISHED, finished_listener)
62
+ result.remove_listener(TestResult::PASS_ASSERTION,
63
+ pass_assertion_listener)
55
64
  notify_listeners(FINISHED, elapsed_time)
56
65
  end
57
66
 
@@ -0,0 +1,224 @@
1
+ #--
2
+ #
3
+ # Author:: Kouhei Sutou
4
+ # Copyright::
5
+ # * Copyright (c) 2011 Kouhei Sutou <kou@clear-code.com>
6
+ # License:: Ruby license.
7
+
8
+ require 'erb'
9
+ require 'time'
10
+ require 'test/unit/ui/testrunner'
11
+ require 'test/unit/ui/testrunnermediator'
12
+
13
+ module Test
14
+ module Unit
15
+ module UI
16
+ module XML
17
+
18
+ # Runs a Test::Unit::TestSuite and outputs XML.
19
+ class TestRunner < UI::TestRunner
20
+ include ERB::Util
21
+
22
+ # Creates a new TestRunner for running the passed
23
+ # suite. :output option specifies where runner
24
+ # output should go to; defaults to STDOUT.
25
+ def initialize(suite, options={})
26
+ super
27
+ @output = @options[:output] || STDOUT
28
+ if @options[:output_file_descriptor]
29
+ @output = IO.new(@options[:output_file_descriptor], "w")
30
+ end
31
+ @already_outputted = false
32
+ @indent = 0
33
+ @top_level = true
34
+ @current_test = nil
35
+ @current_test_suite = nil
36
+ @already_outputted = false
37
+ end
38
+
39
+ private
40
+ def attach_to_mediator
41
+ @mediator.add_listener(TestResult::PASS_ASSERTION,
42
+ &method(:result_pass_assertion))
43
+ @mediator.add_listener(TestResult::FAULT,
44
+ &method(:result_fault))
45
+ @mediator.add_listener(TestRunnerMediator::STARTED,
46
+ &method(:started))
47
+ @mediator.add_listener(TestRunnerMediator::FINISHED,
48
+ &method(:finished))
49
+ @mediator.add_listener(TestCase::STARTED_OBJECT,
50
+ &method(:test_started))
51
+ @mediator.add_listener(TestCase::FINISHED_OBJECT,
52
+ &method(:test_finished))
53
+ @mediator.add_listener(TestSuite::STARTED_OBJECT,
54
+ &method(:test_suite_started))
55
+ @mediator.add_listener(TestSuite::FINISHED_OBJECT,
56
+ &method(:test_suite_finished))
57
+ end
58
+
59
+ def result_pass_assertion(result)
60
+ open_tag("pass-assertion") do
61
+ output_test(@current_test)
62
+ end
63
+ end
64
+
65
+ def result_fault(fault)
66
+ open_tag("test-result") do
67
+ open_tag("result") do
68
+ output_test_suite(@current_test_suite)
69
+ output_test(@current_test)
70
+ open_tag("backtrace") do
71
+ fault.location.each do |entry|
72
+ file, line, info = entry.split(/:/, 3)
73
+ open_tag("entry") do
74
+ add_content("file", file)
75
+ add_content("line", line)
76
+ add_content("info", info)
77
+ end
78
+ end
79
+ end
80
+ if fault.respond_to?(:expected)
81
+ add_content("expected", fault.expected)
82
+ end
83
+ if fault.respond_to?(:actual)
84
+ add_content("actual", fault.actual)
85
+ end
86
+ add_content("detail", fault.message)
87
+ add_content("status", fault.label.downcase)
88
+ end
89
+ end
90
+ @already_outputted = true if fault.critical?
91
+ end
92
+
93
+ def started(result)
94
+ @result = result
95
+ output_started
96
+ end
97
+
98
+ def output_started
99
+ open_tag("stream")
100
+ end
101
+
102
+ def finished(elapsed_time)
103
+ add_content("success", @result.passed?)
104
+ close_tag("stream")
105
+ end
106
+
107
+ def test_started(test)
108
+ @already_outputted = false
109
+ @current_test = test
110
+ open_tag("start-test") do
111
+ output_test(test)
112
+ end
113
+ end
114
+
115
+ def test_finished(test)
116
+ unless @already_outputted
117
+ open_tag("test-result") do
118
+ output_test(test)
119
+ open_tag("result") do
120
+ output_test_suite(@current_test_suite)
121
+ output_test(test)
122
+ add_content("status", "success")
123
+ end
124
+ end
125
+ end
126
+
127
+ open_tag("complete-test") do
128
+ output_test(test)
129
+ add_content("success", test.passed?)
130
+ end
131
+ @current_test = nil
132
+ end
133
+
134
+ def test_suite_started(suite)
135
+ @current_test_suite = suite
136
+ if suite.test_case.nil?
137
+ open_tag("ready-test-suite") do
138
+ add_content("n-tests", suite.size)
139
+ end
140
+ open_tag("start-test-suite") do
141
+ output_test_suite(suite)
142
+ end
143
+ else
144
+ open_tag("ready-test-case") do
145
+ output_test_suite(suite)
146
+ add_content("n-tests", suite.size)
147
+ end
148
+ open_tag("start-test-case") do
149
+ output_test_suite(suite)
150
+ end
151
+ end
152
+ end
153
+
154
+ def test_suite_finished(suite)
155
+ if suite.test_case.nil?
156
+ open_tag("complete-test-suite") do
157
+ output_test_suite(suite)
158
+ add_content("success", suite.passed?)
159
+ end
160
+ else
161
+ open_tag("complete-test-case") do
162
+ output_test_suite(suite)
163
+ add_content("success", suite.passed?)
164
+ end
165
+ end
166
+ @current_test_suite = nil
167
+ end
168
+
169
+ def indent
170
+ " " * @indent
171
+ end
172
+
173
+ def open_tag(name)
174
+ @output.puts("#{indent}<#{name}>")
175
+ @indent += 2
176
+ if block_given?
177
+ yield
178
+ close_tag(name)
179
+ end
180
+ end
181
+
182
+ def add_content(name, content)
183
+ return if content.nil?
184
+ case content
185
+ when Time
186
+ content = content.iso8601
187
+ end
188
+ @output.puts("#{indent}<#{name}>#{h(content)}</#{name}>")
189
+ end
190
+
191
+ def close_tag(name)
192
+ @indent -= 2
193
+ @output.puts("#{indent}</#{name}>")
194
+ end
195
+
196
+ def output_test(test)
197
+ open_tag("test") do
198
+ add_content("name", test.method_name)
199
+ add_content("start-time", test.start_time)
200
+ add_content("elapsed", test.elapsed_time)
201
+ end
202
+ end
203
+
204
+ def output_test_suite(test_suite)
205
+ test_case = test_suite.test_case
206
+ if test_case.nil?
207
+ open_tag("test-suite") do
208
+ add_content("name", test_suite.name)
209
+ add_content("start-time", test_suite.start_time)
210
+ add_content("elapsed", test_suite.elapsed_time)
211
+ end
212
+ else
213
+ open_tag("test-case") do
214
+ add_content("name", test_suite.name)
215
+ add_content("start-time", test_suite.start_time)
216
+ add_content("elapsed", test_suite.elapsed_time)
217
+ end
218
+ end
219
+ end
220
+ end
221
+ end
222
+ end
223
+ end
224
+ end