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.
- data/History.txt +24 -1
- data/Manifest.txt +8 -0
- data/README.txt +1 -0
- data/Rakefile +1 -2
- data/html/github-logo.png +0 -0
- data/html/index.html +30 -19
- data/html/index.html.ja +29 -17
- data/html/test-unit.css +9 -2
- data/lib/test/unit/assertions.rb +77 -19
- data/lib/test/unit/attribute.rb +33 -29
- data/lib/test/unit/autorunner.rb +15 -1
- data/lib/test/unit/collector/xml.rb +250 -0
- data/lib/test/unit/data.rb +80 -0
- data/lib/test/unit/error.rb +4 -3
- data/lib/test/unit/fixture.rb +30 -1
- data/lib/test/unit/runner/xml.rb +15 -0
- data/lib/test/unit/testcase.rb +201 -85
- data/lib/test/unit/testresult.rb +6 -2
- data/lib/test/unit/testsuite.rb +17 -1
- data/lib/test/unit/testsuitecreator.rb +79 -0
- data/lib/test/unit/ui/console/testrunner.rb +23 -20
- data/lib/test/unit/ui/testrunnermediator.rb +11 -2
- data/lib/test/unit/ui/xml/testrunner.rb +224 -0
- data/lib/test/unit/version.rb +1 -1
- data/test/fixtures/plus.csv +3 -0
- data/test/test-data.rb +179 -0
- data/test/test-fixture.rb +163 -0
- data/test/test-testcase.rb +49 -29
- data/test/test_testsuite.rb +19 -11
- metadata +14 -6
data/lib/test/unit/autorunner.rb
CHANGED
@@ -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
|
data/lib/test/unit/error.rb
CHANGED
@@ -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 =
|
51
|
+
backtrace_display = location.join("\n ")
|
52
52
|
"#{label}:\n#@test_name:\n#{message}\n #{backtrace_display}"
|
53
53
|
end
|
54
54
|
|
55
|
-
def
|
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
|
data/lib/test/unit/fixture.rb
CHANGED
@@ -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
|