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.
@@ -83,6 +83,14 @@ module Test
83
83
  collector.collect(*auto_runner.to_run)
84
84
  end
85
85
 
86
+ # JUST TEST!
87
+ # register_collector(:xml) do |auto_runner|
88
+ # require 'test/unit/collector/xml'
89
+ # collector = Collector::XML.new
90
+ # collector.filter = auto_runner.filters
91
+ # collector.collect(auto_runner.to_run[0])
92
+ # end
93
+
86
94
  # deprecated
87
95
  register_collector(:object_space) do |auto_runner|
88
96
  require 'test/unit/collector/objectspace'
@@ -152,13 +160,18 @@ module Test
152
160
  o.banner = "Test::Unit automatic runner."
153
161
  o.banner << "\nUsage: #{$0} [options] [-- untouched arguments]"
154
162
 
155
- o.on
156
163
  o.on('-r', '--runner=RUNNER', RUNNERS,
157
164
  "Use the given RUNNER.",
158
165
  "(" + keyword_display(RUNNERS) + ")") do |r|
159
166
  @runner = r
160
167
  end
161
168
 
169
+ o.on('--collector=COLLECTOR', COLLECTORS,
170
+ "Use the given COLLECTOR.",
171
+ "(" + keyword_display(COLLECTORS) + ")") do |collector|
172
+ @collector = collector
173
+ end
174
+
162
175
  if (@standalone)
163
176
  o.on('-b', '--basedir=DIR', "Base directory of test suites.") do |b|
164
177
  @base = b
@@ -397,3 +410,4 @@ end
397
410
  require 'test/unit/runner/console'
398
411
  require 'test/unit/runner/emacs'
399
412
  require 'test/unit/runner/tap'
413
+ require 'test/unit/runner/xml'
@@ -0,0 +1,250 @@
1
+ #--
2
+ #
3
+ # Author:: Kouhei Sutou
4
+ # Copyright::
5
+ # * Copyright (c) 2011 Kouhei Sutou <kou@clear-code.com>
6
+ # License:: Ruby license.
7
+
8
+ # just test!!! don't use it yet!!!
9
+
10
+ require 'test/unit/collector'
11
+
12
+ require 'rexml/document'
13
+ require 'rexml/streamlistener'
14
+
15
+ module Test
16
+ module Unit
17
+ module Collector
18
+ class XML
19
+ include Collector
20
+
21
+ def collect(xml_log_path)
22
+ listener = Listener.new
23
+ File.open(xml_log_path) do |xml_log|
24
+ parser = REXML::Parsers::StreamParser.new(xml_log, listener)
25
+ parser.parse
26
+ end
27
+ suite = TestSuite.new("tests in #{xml_log_path}")
28
+ suites = listener.test_suites
29
+ sort(suites).each {|s| add_suite(suite, s)}
30
+ suite
31
+ end
32
+
33
+ class Listener
34
+ include REXML::StreamListener
35
+
36
+ attr_reader :test_suites
37
+ def initialize
38
+ @ns_stack = [{"xml" => :xml}]
39
+ @tag_stack = [["", :root]]
40
+ @text_stack = ['']
41
+ @state_stack = [:root]
42
+ @values = {}
43
+ @test_suites = []
44
+ end
45
+
46
+ def tag_start(name, attributes)
47
+ @text_stack.push('')
48
+
49
+ ns = @ns_stack.last.dup
50
+ attrs = {}
51
+ attributes.each do |n, v|
52
+ if /\Axmlns(?:\z|:)/ =~ n
53
+ ns[$POSTMATCH] = v
54
+ else
55
+ attrs[n] = v
56
+ end
57
+ end
58
+ @ns_stack.push(ns)
59
+
60
+ _parent_tag = parent_tag
61
+ prefix, local = split_name(name)
62
+ uri = _ns(ns, prefix)
63
+ @tag_stack.push([uri, local])
64
+
65
+ state = next_state(@state_stack.last, uri, local)
66
+ @state_stack.push(state)
67
+ case state
68
+ when :test_suite, :test_case
69
+ @values = {}
70
+ when :test
71
+ @values = {}
72
+ @n_pass_assertions = 0 if _parent_tag == "start-test"
73
+ when :backtrace
74
+ @backtrace = []
75
+ @values_backup = @values
76
+ @values = {}
77
+ end
78
+ end
79
+
80
+ def tag_end(name)
81
+ state = @state_stack.pop
82
+ text = @text_stack.pop
83
+ uri, local = @tag_stack.pop
84
+ no_action_states = [:root, :stream]
85
+ case state
86
+ when *no_action_states
87
+ # do nothing
88
+ when :test_suite
89
+ test_suite_end
90
+ when :complete_test_case
91
+ @test_suites.last << @test_case.suite
92
+ when :test_case
93
+ test_case_end
94
+ when :result
95
+ @result = @values
96
+ when :test
97
+ test_end
98
+ when :pass_assertion
99
+ @n_pass_assertions += 1
100
+ when :backtrace
101
+ @values = @values_backup
102
+ @values["backtrace"] = @backtrace
103
+ when :entry
104
+ file = @values['file']
105
+ line = @values['line']
106
+ info = @values['info']
107
+ @backtrace << "#{file}:#{line}: #{info}"
108
+ @values = {}
109
+ else
110
+ local = normalize_local(local)
111
+ @values[local] = text
112
+ end
113
+ @ns_stack.pop
114
+ end
115
+
116
+ def text(data)
117
+ @text_stack.last << data
118
+ end
119
+
120
+ private
121
+ def _ns(ns, prefix)
122
+ ns.fetch(prefix, "")
123
+ end
124
+
125
+ NAME_SPLIT = /^(?:([\w:][-\w\d.]*):)?([\w:][-\w\d.]*)/
126
+ def split_name(name)
127
+ name =~ NAME_SPLIT
128
+ [$1 || '', $2]
129
+ end
130
+
131
+ STATE_TABLE = {
132
+ :root => [:stream],
133
+ :stream => [:ready_test_suite,
134
+ :start_test_suite,
135
+ :ready_test_case,
136
+ :start_test_case,
137
+ :start_test,
138
+ :pass_assertion,
139
+ :test_result,
140
+ :complete_test,
141
+ :complete_test_case,
142
+ :complete_test_suite,
143
+ :success],
144
+ :ready_test_suite => [:n_tests],
145
+ :start_test_suite => [:test_suite],
146
+ :ready_test_case => [:test_case,
147
+ :n_tests],
148
+ :start_test_case => [:test_case],
149
+ :start_test => [:test],
150
+ :pass_assertion => [:test],
151
+ :complete_test => [:test, :success],
152
+ :complete_test_case => [:test_case,
153
+ :elapsed,
154
+ :success],
155
+ :complete_test_suite => [:test_suite,
156
+ :success],
157
+ :test_suite => [:start_time,
158
+ :elapsed],
159
+ :test_case => [:name,
160
+ :start_time,
161
+ :elapsed],
162
+ :test => [:name,
163
+ :start_time,
164
+ :elapsed],
165
+ :test_result => [:test,
166
+ :result],
167
+ :result => [:test_case,
168
+ :test,
169
+ :status,
170
+ :backtrace,
171
+ :detail],
172
+ :backtrace => [:entry],
173
+ :entry => [:file,
174
+ :line,
175
+ :info],
176
+ }
177
+ def next_state(current_state, uri, local)
178
+ local = normalize_local(local)
179
+ valid_elements = STATE_TABLE[current_state]
180
+ if valid_elements.nil?
181
+ raise "unexpected element: #{current_path}"
182
+ end
183
+ next_state = local.to_sym
184
+ unless valid_elements.include?(next_state)
185
+ raise "unexpected element: #{current_path}"
186
+ end
187
+ next_state
188
+ end
189
+
190
+ def current_path
191
+ locals = @tag_stack.collect do |uri, local|
192
+ local
193
+ end
194
+ ["", *locals].join("/")
195
+ end
196
+
197
+ def normalize_local(local)
198
+ local.gsub(/-/, "_")
199
+ end
200
+
201
+ def parent_tag
202
+ @tag_stack.last[1]
203
+ end
204
+
205
+ def test_suite_end
206
+ return unless parent_tag == "start-test-suite"
207
+ suite = TestSuite.new
208
+ ["start_time", "elapsed_time", "n_tests"].each do |key|
209
+ if @values.has_key?(key)
210
+ suite.instance_variable_set("@#{key}", @values[key])
211
+ end
212
+ end
213
+ @test_suites << suite
214
+ end
215
+
216
+ def test_case_end
217
+ return unless parent_tag == "start-test-case"
218
+ name = @values["name"]
219
+ @test_case = Class.new(TestCase) do
220
+ define_method(:name) do
221
+ name
222
+ end
223
+ end
224
+ end
225
+
226
+ def test_end
227
+ return unless parent_tag == "complete-test"
228
+ name = @values["name"]
229
+ n_pass_assertions = @n_pass_assertions
230
+ result = @result
231
+ @test_case.module_eval do
232
+ test
233
+ define_method(name) do
234
+ n_pass_assertions.times do
235
+ add_assertion
236
+ end
237
+ case result["status"]
238
+ when "omission"
239
+ add_omission(Omission.new(name,
240
+ result["backtrace"],
241
+ result["detail"]))
242
+ end
243
+ end
244
+ end
245
+ end
246
+ end
247
+ end
248
+ end
249
+ end
250
+ end
@@ -0,0 +1,80 @@
1
+ module Test
2
+ module Unit
3
+ module Data
4
+ class << self
5
+ def included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+ end
9
+
10
+ module ClassMethods
11
+ # TODO: WRITE ME.
12
+ def data(*arguments, &block)
13
+ n_arguments = arguments.size
14
+ case n_arguments
15
+ when 0
16
+ data_set = block
17
+ when 1
18
+ data_set = arguments[0]
19
+ when 2
20
+ data_set = {arguments[0] => arguments[1]}
21
+ else
22
+ message= "wrong number arguments(#{n_arguments} for 1..2)"
23
+ raise ArgumentError, message
24
+ end
25
+ current_data = current_attribute(:data)[:value] || []
26
+ attribute(:data, current_data + [data_set])
27
+ end
28
+
29
+ # TODO: WRITE ME.
30
+ def load_data(file_name)
31
+ case file_name
32
+ when /\.csv/i
33
+ loader = CSVDataLoader.new(self)
34
+ loader.load(file_name)
35
+ else
36
+ raise ArgumentError, "unsupported file format: <#{file_name}>"
37
+ end
38
+ end
39
+
40
+ class CSVDataLoader
41
+ def initialize(test_case)
42
+ @test_case = test_case
43
+ end
44
+
45
+ def load(file_name)
46
+ require 'csv'
47
+ header = nil
48
+ CSV.foreach(file_name) do |row|
49
+ if header.nil?
50
+ header = row
51
+ next
52
+ end
53
+ label = nil
54
+ data = {}
55
+ header.each_with_index do |key, i|
56
+ if key == "label"
57
+ label = row[i]
58
+ else
59
+ data[key] = normalize_value(row[i])
60
+ end
61
+ end
62
+ @test_case.data(label, data)
63
+ end
64
+ end
65
+
66
+ private
67
+ def normalize_value(value)
68
+ Integer(value)
69
+ rescue ArgumentError
70
+ begin
71
+ Float(value)
72
+ rescue ArgumentError
73
+ value
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -48,13 +48,14 @@ module Test
48
48
 
49
49
  # Returns a verbose version of the error description.
50
50
  def long_display
51
- backtrace_display = backtrace.join("\n ")
51
+ backtrace_display = location.join("\n ")
52
52
  "#{label}:\n#@test_name:\n#{message}\n #{backtrace_display}"
53
53
  end
54
54
 
55
- def backtrace
56
- filter_backtrace(@exception.backtrace)
55
+ def location
56
+ @location ||= filter_backtrace(@exception.backtrace)
57
57
  end
58
+ alias_method :backtrace, :location # Deprecated
58
59
 
59
60
  # Overridden to return long_display.
60
61
  def to_s
@@ -5,7 +5,7 @@ module Test
5
5
  def included(base)
6
6
  base.extend(ClassMethods)
7
7
 
8
- [:setup, :teardown].each do |fixture|
8
+ [:setup, :cleanup, :teardown].each do |fixture|
9
9
  observer = Proc.new do |test_case, _, _, value, method_name|
10
10
  if value.nil?
11
11
  test_case.send("unregister_#{fixture}_method", method_name)
@@ -28,6 +28,14 @@ module Test
28
28
  unregister_fixture(:setup, *method_names)
29
29
  end
30
30
 
31
+ def cleanup(*method_names)
32
+ register_fixture(:cleanup, *method_names)
33
+ end
34
+
35
+ def unregister_cleanup(*method_names)
36
+ unregister_fixture(:cleanup, *method_names)
37
+ end
38
+
31
39
  def teardown(*method_names)
32
40
  register_fixture(:teardown, *method_names)
33
41
  end
@@ -44,6 +52,15 @@ module Test
44
52
  unregister_fixture_method(:setup, method_name)
45
53
  end
46
54
 
55
+ def register_cleanup_method(method_name, options)
56
+ register_fixture_method(:cleanup, method_name, options,
57
+ :before, :prepend)
58
+ end
59
+
60
+ def unregister_cleanup_method(method_name)
61
+ unregister_fixture_method(:cleanup, method_name)
62
+ end
63
+
47
64
  def register_teardown_method(method_name, options)
48
65
  register_fixture_method(:teardown, method_name, options,
49
66
  :before, :prepend)
@@ -61,6 +78,14 @@ module Test
61
78
  collect_fixture_methods(:setup, :after)
62
79
  end
63
80
 
81
+ def before_cleanup_methods
82
+ collect_fixture_methods(:cleanup, :before)
83
+ end
84
+
85
+ def after_cleanup_methods
86
+ collect_fixture_methods(:cleanup, :after)
87
+ end
88
+
64
89
  def before_teardown_methods
65
90
  collect_fixture_methods(:teardown, :before)
66
91
  end
@@ -177,6 +202,10 @@ module Test
177
202
  run_fixture(:setup)
178
203
  end
179
204
 
205
+ def run_cleanup
206
+ run_fixture(:cleanup)
207
+ end
208
+
180
209
  def run_teardown
181
210
  run_fixture(:teardown, :handle_exception => true)
182
211
  end