test-unit 2.2.0 → 2.3.0

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