test-unit 3.1.4 → 3.6.2
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.
- checksums.yaml +5 -5
- data/BSDL +24 -0
- data/COPYING +41 -41
- data/README.md +24 -17
- data/Rakefile +21 -24
- data/doc/text/getting-started.md +246 -0
- data/doc/text/news.md +824 -54
- data/lib/test/unit/assertion-failed-error.rb +35 -0
- data/lib/test/unit/assertions.rb +542 -220
- data/lib/test/unit/attribute.rb +78 -4
- data/lib/test/unit/auto-runner-loader.rb +17 -0
- data/lib/test/unit/autorunner.rb +200 -78
- data/lib/test/unit/code-snippet-fetcher.rb +7 -7
- data/lib/test/unit/collector/descendant.rb +1 -0
- data/lib/test/unit/collector/dir.rb +4 -2
- data/lib/test/unit/collector/load.rb +25 -15
- data/lib/test/unit/collector/objectspace.rb +1 -0
- data/lib/test/unit/collector.rb +31 -0
- data/lib/test/unit/color-scheme.rb +29 -2
- data/lib/test/unit/data-sets.rb +127 -0
- data/lib/test/unit/data.rb +121 -12
- data/lib/test/unit/diff.rb +10 -11
- data/lib/test/unit/fault-location-detector.rb +1 -1
- data/lib/test/unit/fixture.rb +77 -27
- data/lib/test/unit/notification.rb +9 -7
- data/lib/test/unit/omission.rb +34 -31
- data/lib/test/unit/pending.rb +12 -11
- data/lib/test/unit/priority.rb +7 -5
- data/lib/test/unit/runner/console.rb +20 -1
- data/lib/test/unit/test-suite-creator.rb +30 -9
- data/lib/test/unit/testcase.rb +349 -196
- data/lib/test/unit/testresult.rb +7 -0
- data/lib/test/unit/testsuite.rb +1 -1
- data/lib/test/unit/ui/console/testrunner.rb +171 -60
- data/lib/test/unit/ui/emacs/testrunner.rb +5 -5
- data/lib/test/unit/ui/testrunnermediator.rb +9 -7
- data/lib/test/unit/util/backtracefilter.rb +17 -5
- data/lib/test/unit/util/memory-usage.rb +47 -0
- data/lib/test/unit/util/observable.rb +2 -2
- data/lib/test/unit/util/output.rb +5 -4
- data/lib/test/unit/util/procwrapper.rb +4 -4
- data/lib/test/unit/version.rb +1 -1
- data/lib/test/unit/warning.rb +3 -0
- data/lib/test/unit.rb +177 -161
- data/lib/test-unit.rb +10 -23
- metadata +21 -95
- data/GPL +0 -339
- data/LGPL +0 -502
- data/test/collector/test-descendant.rb +0 -178
- data/test/collector/test-load.rb +0 -442
- data/test/collector/test_dir.rb +0 -406
- data/test/collector/test_objectspace.rb +0 -100
- data/test/fixtures/header-label.csv +0 -3
- data/test/fixtures/header-label.tsv +0 -3
- data/test/fixtures/header.csv +0 -3
- data/test/fixtures/header.tsv +0 -3
- data/test/fixtures/no-header.csv +0 -2
- data/test/fixtures/no-header.tsv +0 -2
- data/test/fixtures/plus.csv +0 -3
- data/test/run-test.rb +0 -22
- data/test/test-assertions.rb +0 -2157
- data/test/test-attribute-matcher.rb +0 -38
- data/test/test-attribute.rb +0 -123
- data/test/test-code-snippet.rb +0 -37
- data/test/test-color-scheme.rb +0 -82
- data/test/test-color.rb +0 -47
- data/test/test-data.rb +0 -281
- data/test/test-diff.rb +0 -518
- data/test/test-emacs-runner.rb +0 -60
- data/test/test-error.rb +0 -26
- data/test/test-failure.rb +0 -33
- data/test/test-fault-location-detector.rb +0 -163
- data/test/test-fixture.rb +0 -659
- data/test/test-notification.rb +0 -33
- data/test/test-omission.rb +0 -81
- data/test/test-pending.rb +0 -70
- data/test/test-priority.rb +0 -173
- data/test/test-test-case.rb +0 -1171
- data/test/test-test-result.rb +0 -113
- data/test/test-test-suite-creator.rb +0 -97
- data/test/test-test-suite.rb +0 -150
- data/test/testunit-test-util.rb +0 -31
- data/test/ui/test_testrunmediator.rb +0 -20
- data/test/util/test-method-owner-finder.rb +0 -38
- data/test/util/test-output.rb +0 -11
- data/test/util/test_backtracefilter.rb +0 -41
- data/test/util/test_observable.rb +0 -102
- data/test/util/test_procwrapper.rb +0 -36
data/lib/test/unit/attribute.rb
CHANGED
@@ -43,12 +43,80 @@ module Test
|
|
43
43
|
kept_attributes = StringifyKeyHash.new
|
44
44
|
@current_attributes.each do |attribute_name, attribute|
|
45
45
|
attributes[attribute_name] = attribute[:value]
|
46
|
-
|
46
|
+
if attribute[:keep]
|
47
|
+
keep_hook = attribute[:keep_hook]
|
48
|
+
attribute = keep_hook.call(attribute) if keep_hook
|
49
|
+
kept_attributes[attribute_name] = attribute
|
50
|
+
end
|
47
51
|
end
|
48
52
|
set_attributes(name, attributes)
|
49
53
|
@current_attributes = kept_attributes
|
50
54
|
end
|
51
55
|
|
56
|
+
# Set an attribute to test methods.
|
57
|
+
#
|
58
|
+
# @overload attribute(name, value)
|
59
|
+
# @example
|
60
|
+
# attribute :speed, :slow
|
61
|
+
# def test_my_slow_method
|
62
|
+
# self[:speed] # => :slow
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# @param [Object] name the attribute name
|
66
|
+
# @param [Object] value the attribute value
|
67
|
+
# @return [void]
|
68
|
+
#
|
69
|
+
# @overload attribute(name, value, *method_names)
|
70
|
+
# @example
|
71
|
+
# def test_my_slow_method1
|
72
|
+
# self[:speed] # => :slow
|
73
|
+
# end
|
74
|
+
#
|
75
|
+
# attribute :speed, :slow, :test_my_slow_method1, :test_my_slow_method2
|
76
|
+
#
|
77
|
+
# def test_my_slow_method2
|
78
|
+
# self[:speed] # => :slow
|
79
|
+
# end
|
80
|
+
#
|
81
|
+
# @param [Object] name the attribute name
|
82
|
+
# @param [Object] value the attribute value
|
83
|
+
# @param [Array<Symbol, String>] method_names the test method names set the attribute
|
84
|
+
# @return [void]
|
85
|
+
#
|
86
|
+
# @overload attribute(name, value, options)
|
87
|
+
# @example
|
88
|
+
# attribute :speed, :slow, keep: true
|
89
|
+
# def test_my_slow_method1
|
90
|
+
# self[:speed] # => :slow
|
91
|
+
# end
|
92
|
+
#
|
93
|
+
# def test_my_slow_method2
|
94
|
+
# self[:speed] # => :slow
|
95
|
+
# end
|
96
|
+
#
|
97
|
+
# @param [Object] name the attribute name
|
98
|
+
# @param [Object] value the attribute value
|
99
|
+
# @option options [Boolean] :keep whether or not to set attribute to following test methods
|
100
|
+
# @return [void]
|
101
|
+
#
|
102
|
+
# @overload attribute(name, value, options, *method_names)
|
103
|
+
# @example
|
104
|
+
# def test_my_slow_method1
|
105
|
+
# self[:speed] # => :slow
|
106
|
+
# end
|
107
|
+
#
|
108
|
+
# # There are no valid options for now.
|
109
|
+
# attribute :speed, :slow, {}, :test_my_slow_method1
|
110
|
+
#
|
111
|
+
# def test_my_slow_method2
|
112
|
+
# self[:speed] # => nil
|
113
|
+
# end
|
114
|
+
#
|
115
|
+
# @param [Object] name the attribute name
|
116
|
+
# @param [Object] value the attribute value
|
117
|
+
# @param [Hash] options ignored
|
118
|
+
# @param [Array<Symbol, String>] method_names the test method names set the attribute
|
119
|
+
# @return [void]
|
52
120
|
def attribute(name, value, options={}, *method_names)
|
53
121
|
unless options.is_a?(Hash)
|
54
122
|
method_names << options
|
@@ -111,7 +179,10 @@ module Test
|
|
111
179
|
attributes || StringifyKeyHash.new
|
112
180
|
end
|
113
181
|
|
114
|
-
def find_attribute(method_name, name)
|
182
|
+
def find_attribute(method_name, name, options={})
|
183
|
+
recursive_p = options[:recursive]
|
184
|
+
recursive_p = true if recursive_p.nil?
|
185
|
+
|
115
186
|
@attributes_table ||= StringifyKeyHash.new
|
116
187
|
if @attributes_table.key?(method_name)
|
117
188
|
attributes = @attributes_table[method_name]
|
@@ -120,6 +191,7 @@ module Test
|
|
120
191
|
end
|
121
192
|
end
|
122
193
|
|
194
|
+
return nil unless recursive_p
|
123
195
|
return nil if self == TestCase
|
124
196
|
|
125
197
|
@cached_parent_test_case ||= ancestors.find do |ancestor|
|
@@ -127,12 +199,14 @@ module Test
|
|
127
199
|
ancestor.is_a?(Class) and
|
128
200
|
ancestor < Test::Unit::Attribute
|
129
201
|
end
|
202
|
+
return nil if @cached_parent_test_case.nil?
|
130
203
|
|
131
|
-
@cached_parent_test_case.find_attribute(method_name, name)
|
204
|
+
@cached_parent_test_case.find_attribute(method_name, name, options)
|
132
205
|
end
|
133
206
|
|
134
207
|
@@attribute_observers = StringifyKeyHash.new
|
135
|
-
def register_attribute_observer(attribute_name, observer=
|
208
|
+
def register_attribute_observer(attribute_name, observer=nil, &block)
|
209
|
+
observer ||= Proc.new(&block)
|
136
210
|
@@attribute_observers[attribute_name] ||= []
|
137
211
|
@@attribute_observers[attribute_name] << observer
|
138
212
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "test/unit/test-suite-creator"
|
2
|
+
|
3
|
+
module Test
|
4
|
+
module Unit
|
5
|
+
module AutoRunnerLoader
|
6
|
+
@loaded = false
|
7
|
+
class << self
|
8
|
+
def check(test_case, method_name)
|
9
|
+
return if @loaded
|
10
|
+
return unless TestSuiteCreator.test_method?(test_case, method_name)
|
11
|
+
require "test/unit"
|
12
|
+
@loaded = true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/test/unit/autorunner.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
|
4
|
-
require
|
1
|
+
require "English"
|
2
|
+
require "optparse"
|
3
|
+
|
4
|
+
require "test/unit/color-scheme"
|
5
|
+
require "test/unit/priority"
|
6
|
+
require "test/unit/attribute-matcher"
|
7
|
+
require "test/unit/testcase"
|
5
8
|
|
6
9
|
module Test
|
7
10
|
module Unit
|
@@ -12,7 +15,8 @@ module Test
|
|
12
15
|
PREPARE_HOOKS = []
|
13
16
|
|
14
17
|
class << self
|
15
|
-
def register_runner(id, runner_builder=
|
18
|
+
def register_runner(id, runner_builder=nil, &block)
|
19
|
+
runner_builder ||= Proc.new(&block)
|
16
20
|
RUNNERS[id] = runner_builder
|
17
21
|
RUNNERS[id.to_s] = runner_builder
|
18
22
|
end
|
@@ -30,7 +34,8 @@ module Test
|
|
30
34
|
@@default_runner = id
|
31
35
|
end
|
32
36
|
|
33
|
-
def register_collector(id, collector_builder=
|
37
|
+
def register_collector(id, collector_builder=nil, &block)
|
38
|
+
collector_builder ||= Proc.new(&block)
|
34
39
|
COLLECTORS[id] = collector_builder
|
35
40
|
COLLECTORS[id.to_s] = collector_builder
|
36
41
|
end
|
@@ -43,11 +48,13 @@ module Test
|
|
43
48
|
ColorScheme[id] = scheme
|
44
49
|
end
|
45
50
|
|
46
|
-
def setup_option(option_builder=
|
51
|
+
def setup_option(option_builder=nil, &block)
|
52
|
+
option_builder ||= Proc.new(&block)
|
47
53
|
ADDITIONAL_OPTIONS << option_builder
|
48
54
|
end
|
49
55
|
|
50
|
-
def prepare(hook=
|
56
|
+
def prepare(hook=nil, &block)
|
57
|
+
hook ||= Proc.new(&block)
|
51
58
|
PREPARE_HOOKS << hook
|
52
59
|
end
|
53
60
|
|
@@ -78,14 +85,14 @@ module Test
|
|
78
85
|
end
|
79
86
|
|
80
87
|
register_collector(:descendant) do |auto_runner|
|
81
|
-
require
|
88
|
+
require "test/unit/collector/descendant"
|
82
89
|
collector = Collector::Descendant.new
|
83
90
|
collector.filter = auto_runner.filters
|
84
|
-
collector.collect($0.sub(/\.rb\Z/,
|
91
|
+
collector.collect($0.sub(/\.rb\Z/, ""))
|
85
92
|
end
|
86
93
|
|
87
94
|
register_collector(:load) do |auto_runner|
|
88
|
-
require
|
95
|
+
require "test/unit/collector/load"
|
89
96
|
collector = Collector::Load.new
|
90
97
|
unless auto_runner.pattern.empty?
|
91
98
|
collector.patterns.replace(auto_runner.pattern)
|
@@ -94,13 +101,14 @@ module Test
|
|
94
101
|
collector.excludes.replace(auto_runner.exclude)
|
95
102
|
end
|
96
103
|
collector.base = auto_runner.base
|
104
|
+
collector.default_test_paths = auto_runner.default_test_paths
|
97
105
|
collector.filter = auto_runner.filters
|
98
106
|
collector.collect(*auto_runner.to_run)
|
99
107
|
end
|
100
108
|
|
101
109
|
# JUST TEST!
|
102
110
|
# register_collector(:xml) do |auto_runner|
|
103
|
-
# require
|
111
|
+
# require "test/unit/collector/xml"
|
104
112
|
# collector = Collector::XML.new
|
105
113
|
# collector.filter = auto_runner.filters
|
106
114
|
# collector.collect(auto_runner.to_run[0])
|
@@ -108,15 +116,15 @@ module Test
|
|
108
116
|
|
109
117
|
# deprecated
|
110
118
|
register_collector(:object_space) do |auto_runner|
|
111
|
-
require
|
119
|
+
require "test/unit/collector/objectspace"
|
112
120
|
c = Collector::ObjectSpace.new
|
113
121
|
c.filter = auto_runner.filters
|
114
|
-
c.collect($0.sub(/\.rb\Z/,
|
122
|
+
c.collect($0.sub(/\.rb\Z/, ""))
|
115
123
|
end
|
116
124
|
|
117
125
|
# deprecated
|
118
126
|
register_collector(:dir) do |auto_runner|
|
119
|
-
require
|
127
|
+
require "test/unit/collector/dir"
|
120
128
|
c = Collector::Dir.new
|
121
129
|
c.filter = auto_runner.filters
|
122
130
|
unless auto_runner.pattern.empty?
|
@@ -127,12 +135,17 @@ module Test
|
|
127
135
|
end
|
128
136
|
c.base = auto_runner.base
|
129
137
|
$:.push(auto_runner.base) if auto_runner.base
|
130
|
-
c.collect(*(auto_runner.to_run.empty? ? [
|
138
|
+
c.collect(*(auto_runner.to_run.empty? ? ["."] : auto_runner.to_run))
|
131
139
|
end
|
132
140
|
|
133
141
|
attr_reader :suite, :runner_options
|
134
|
-
attr_accessor :filters, :to_run
|
142
|
+
attr_accessor :filters, :to_run
|
143
|
+
attr_accessor :default_test_paths
|
144
|
+
attr_accessor :pattern, :exclude, :base, :workdir
|
135
145
|
attr_accessor :color_scheme, :listeners
|
146
|
+
attr_writer :stop_on_failure
|
147
|
+
attr_writer :debug_on_failure
|
148
|
+
attr_writer :gc_stress
|
136
149
|
attr_writer :runner, :collector
|
137
150
|
|
138
151
|
def initialize(standalone)
|
@@ -141,11 +154,15 @@ module Test
|
|
141
154
|
@collector = default_collector
|
142
155
|
@filters = []
|
143
156
|
@to_run = []
|
157
|
+
@default_test_paths = []
|
144
158
|
@color_scheme = ColorScheme.default
|
145
159
|
@runner_options = {}
|
146
160
|
@default_arguments = []
|
147
161
|
@workdir = nil
|
148
162
|
@listeners = []
|
163
|
+
@stop_on_failure = false
|
164
|
+
@debug_on_failure = false
|
165
|
+
@gc_stress = false
|
149
166
|
config_file = "test-unit.yml"
|
150
167
|
if File.exist?(config_file)
|
151
168
|
load_config(config_file)
|
@@ -155,6 +172,14 @@ module Test
|
|
155
172
|
yield(self) if block_given?
|
156
173
|
end
|
157
174
|
|
175
|
+
def stop_on_failure?
|
176
|
+
@stop_on_failure
|
177
|
+
end
|
178
|
+
|
179
|
+
def debug_on_failure?
|
180
|
+
@debug_on_failure
|
181
|
+
end
|
182
|
+
|
158
183
|
def prepare
|
159
184
|
PREPARE_HOOKS.each do |handler|
|
160
185
|
handler.call(self)
|
@@ -164,7 +189,7 @@ module Test
|
|
164
189
|
def process_args(args=ARGV)
|
165
190
|
begin
|
166
191
|
args.unshift(*@default_arguments)
|
167
|
-
options.order!(args) {|arg|
|
192
|
+
options.order!(args) {|arg| add_test_path(arg)}
|
168
193
|
rescue OptionParser::ParseError => e
|
169
194
|
puts e
|
170
195
|
puts options
|
@@ -176,110 +201,119 @@ module Test
|
|
176
201
|
def options
|
177
202
|
@options ||= OptionParser.new do |o|
|
178
203
|
o.banner = "Test::Unit automatic runner."
|
179
|
-
o.banner
|
204
|
+
o.banner += "\nUsage: #{$0} [options] [-- untouched arguments]"
|
180
205
|
|
181
|
-
o.on(
|
206
|
+
o.on("-r", "--runner=RUNNER", RUNNERS,
|
182
207
|
"Use the given RUNNER.",
|
183
208
|
"(" + keyword_display(RUNNERS) + ")") do |r|
|
184
209
|
@runner = r
|
185
210
|
end
|
186
211
|
|
187
|
-
o.on(
|
212
|
+
o.on("--collector=COLLECTOR", COLLECTORS,
|
188
213
|
"Use the given COLLECTOR.",
|
189
214
|
"(" + keyword_display(COLLECTORS) + ")") do |collector|
|
190
215
|
@collector = collector
|
191
216
|
end
|
192
217
|
|
193
218
|
if (@standalone)
|
194
|
-
o.on(
|
219
|
+
o.on("-b", "--basedir=DIR", "Base directory of test suites.") do |b|
|
195
220
|
@base = b
|
196
221
|
end
|
197
222
|
|
198
|
-
o.on(
|
223
|
+
o.on("-w", "--workdir=DIR", "Working directory to run tests.") do |w|
|
199
224
|
@workdir = w
|
200
225
|
end
|
201
226
|
|
202
|
-
o.on(
|
227
|
+
o.on("--default-test-path=PATH",
|
228
|
+
"Add PATH to the default test paths.",
|
229
|
+
"The PATH is used when user doesn't specify any test path.",
|
230
|
+
"You can specify this option multiple times.") do |path|
|
231
|
+
@default_test_paths << path
|
232
|
+
end
|
233
|
+
|
234
|
+
o.on("-a", "--add=TORUN", Array,
|
203
235
|
"Add TORUN to the list of things to run;",
|
204
|
-
"can be a file or a directory.") do |
|
205
|
-
|
236
|
+
"can be a file or a directory.") do |paths|
|
237
|
+
paths.each do |path|
|
238
|
+
add_test_path(path)
|
239
|
+
end
|
206
240
|
end
|
207
241
|
|
208
242
|
@pattern = []
|
209
|
-
o.on(
|
243
|
+
o.on("-p", "--pattern=PATTERN", Regexp,
|
210
244
|
"Match files to collect against PATTERN.") do |e|
|
211
245
|
@pattern << e
|
212
246
|
end
|
213
247
|
|
214
248
|
@exclude = []
|
215
|
-
o.on(
|
249
|
+
o.on("-x", "--exclude=PATTERN", Regexp,
|
216
250
|
"Ignore files to collect against PATTERN.") do |e|
|
217
251
|
@exclude << e
|
218
252
|
end
|
219
253
|
end
|
220
254
|
|
221
|
-
o.on(
|
255
|
+
o.on("-n", "--name=NAME", String,
|
222
256
|
"Runs tests matching NAME.",
|
223
|
-
"Use '/PATTERN/' for NAME to use regular expression."
|
224
|
-
|
257
|
+
"Use '/PATTERN/' for NAME to use regular expression.",
|
258
|
+
"Regular expression accepts options.",
|
259
|
+
"Example: '/taRget/i' matches 'target' and 'TARGET'") do |name|
|
260
|
+
name = prepare_name(name)
|
225
261
|
@filters << lambda do |test|
|
226
|
-
|
227
|
-
test_name_without_class_name = test.name.gsub(/\(.+?\)\z/, "")
|
228
|
-
if test_name_without_class_name != test.method_name
|
229
|
-
return true if name === test_name_without_class_name
|
230
|
-
end
|
231
|
-
false
|
262
|
+
match_test_name(test, name)
|
232
263
|
end
|
233
264
|
end
|
234
265
|
|
235
|
-
o.on(
|
266
|
+
o.on("--ignore-name=NAME", String,
|
236
267
|
"Ignores tests matching NAME.",
|
237
|
-
"Use '/PATTERN/' for NAME to use regular expression."
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
@filters << proc {|t| n != t.method_name}
|
268
|
+
"Use '/PATTERN/' for NAME to use regular expression.",
|
269
|
+
"Regular expression accepts options.",
|
270
|
+
"Example: '/taRget/i' matches 'target' and 'TARGET'") do |name|
|
271
|
+
name = prepare_name(name)
|
272
|
+
@filters << lambda do |test|
|
273
|
+
not match_test_name(test, name)
|
244
274
|
end
|
245
275
|
end
|
246
276
|
|
247
|
-
o.on(
|
277
|
+
o.on("-t", "--testcase=TESTCASE", String,
|
248
278
|
"Runs tests in TestCases matching TESTCASE.",
|
249
|
-
"Use '/PATTERN/' for TESTCASE to use regular expression."
|
250
|
-
|
279
|
+
"Use '/PATTERN/' for TESTCASE to use regular expression.",
|
280
|
+
"Regular expression accepts options.",
|
281
|
+
"Example: '/taRget/i' matches 'target' and 'TARGET'") do |name|
|
282
|
+
name = prepare_name(name)
|
251
283
|
@filters << lambda do |test|
|
252
|
-
match_test_case_name(test,
|
284
|
+
match_test_case_name(test, name)
|
253
285
|
end
|
254
286
|
end
|
255
287
|
|
256
|
-
o.on(
|
288
|
+
o.on("--ignore-testcase=TESTCASE", String,
|
257
289
|
"Ignores tests in TestCases matching TESTCASE.",
|
258
|
-
"Use '/PATTERN/' for TESTCASE to use regular expression."
|
259
|
-
|
290
|
+
"Use '/PATTERN/' for TESTCASE to use regular expression.",
|
291
|
+
"Regular expression accepts options.",
|
292
|
+
"Example: '/taRget/i' matches 'target' and 'TARGET'") do |name|
|
293
|
+
name = prepare_name(name)
|
260
294
|
@filters << lambda do |test|
|
261
|
-
not match_test_case_name(test,
|
295
|
+
not match_test_case_name(test, name)
|
262
296
|
end
|
263
297
|
end
|
264
298
|
|
265
|
-
o.on(
|
299
|
+
o.on("--location=LOCATION", String,
|
266
300
|
"Runs tests that defined in LOCATION.",
|
267
|
-
"LOCATION is one of PATH:LINE, PATH or LINE") do |location|
|
268
|
-
|
301
|
+
"LOCATION is one of PATH:LINE, PATH or LINE.") do |location|
|
302
|
+
case location
|
303
|
+
when /\A(\d+)\z/
|
269
304
|
path = nil
|
270
|
-
line =
|
305
|
+
line = $1.to_i
|
306
|
+
when /:(\d+)\z/
|
307
|
+
path = $PREMATCH
|
308
|
+
line = $1.to_i
|
271
309
|
else
|
272
|
-
path
|
273
|
-
line =
|
274
|
-
end
|
275
|
-
@filters << lambda do |test|
|
276
|
-
test.class.test_defined?(:path => path,
|
277
|
-
:line => line,
|
278
|
-
:method_name => test.method_name)
|
310
|
+
path = location
|
311
|
+
line = nil
|
279
312
|
end
|
313
|
+
add_location_filter(path, line)
|
280
314
|
end
|
281
315
|
|
282
|
-
o.on(
|
316
|
+
o.on("--attribute=EXPRESSION", String,
|
283
317
|
"Runs tests that matches EXPRESSION.",
|
284
318
|
"EXPRESSION is evaluated as Ruby's expression.",
|
285
319
|
"Test attribute name can be used with no receiver in EXPRESSION.",
|
@@ -317,7 +351,7 @@ module Test
|
|
317
351
|
Priority.default = priority
|
318
352
|
end
|
319
353
|
|
320
|
-
o.on(
|
354
|
+
o.on("-I", "--load-path=DIR[#{File::PATH_SEPARATOR}DIR...]",
|
321
355
|
"Appends directory list to $LOAD_PATH.") do |dirs|
|
322
356
|
$LOAD_PATH.concat(dirs.split(File::PATH_SEPARATOR))
|
323
357
|
end
|
@@ -330,7 +364,7 @@ module Test
|
|
330
364
|
end
|
331
365
|
|
332
366
|
o.on("--config=FILE",
|
333
|
-
"Use YAML
|
367
|
+
"Use YAML format FILE content as configuration file.") do |file|
|
334
368
|
load_config(file)
|
335
369
|
end
|
336
370
|
|
@@ -349,27 +383,45 @@ module Test
|
|
349
383
|
assertion_message_class.max_diff_target_string_size = size
|
350
384
|
end
|
351
385
|
|
386
|
+
o.on("--[no-]stop-on-failure",
|
387
|
+
"Stops immediately on the first non success test",
|
388
|
+
"(#{@stop_on_failure})") do |boolean|
|
389
|
+
@stop_on_failure = boolean
|
390
|
+
end
|
391
|
+
|
392
|
+
o.on("--[no-]debug-on-failure",
|
393
|
+
"Run debugger if available on failure",
|
394
|
+
"(#{AssertionFailedError.debug_on_failure?})") do |boolean|
|
395
|
+
AssertionFailedError.debug_on_failure = boolean
|
396
|
+
end
|
397
|
+
|
398
|
+
o.on("--[no-]gc-stress",
|
399
|
+
"Enable GC.stress only while each test is running",
|
400
|
+
"(#{@gc_stress})") do |boolean|
|
401
|
+
@gc_stress = boolean
|
402
|
+
end
|
403
|
+
|
352
404
|
ADDITIONAL_OPTIONS.each do |option_builder|
|
353
405
|
option_builder.call(self, o)
|
354
406
|
end
|
355
407
|
|
356
|
-
o.on(
|
408
|
+
o.on("--",
|
357
409
|
"Stop processing options so that the",
|
358
410
|
"remaining options will be passed to the",
|
359
411
|
"test."){o.terminate}
|
360
412
|
|
361
|
-
o.on(
|
413
|
+
o.on("-h", "--help", "Display this help."){puts o; exit}
|
362
414
|
|
363
415
|
o.on_tail
|
364
|
-
o.on_tail(
|
416
|
+
o.on_tail("Deprecated options:")
|
365
417
|
|
366
|
-
o.on_tail(
|
418
|
+
o.on_tail("--console", "Console runner (use --runner).") do
|
367
419
|
warn("Deprecated option (--console).")
|
368
420
|
@runner = self.class.runner(:console)
|
369
421
|
end
|
370
422
|
|
371
423
|
if RUNNERS[:fox]
|
372
|
-
o.on_tail(
|
424
|
+
o.on_tail("--fox", "Fox runner (use --runner).") do
|
373
425
|
warn("Deprecated option (--fox).")
|
374
426
|
@runner = self.class.runner(:fox)
|
375
427
|
end
|
@@ -393,7 +445,7 @@ module Test
|
|
393
445
|
n = 1
|
394
446
|
end
|
395
447
|
i += 1
|
396
|
-
keyword.sub(/^(.{#{n}})([A-Za-z]+)(?=\w*$)/, '\\1[\\2]')
|
448
|
+
keyword.sub(/^(.{#{n}})([A-Za-z-]+)(?=\w*$)/, '\\1[\\2]')
|
397
449
|
end.join(", ")
|
398
450
|
end
|
399
451
|
|
@@ -407,13 +459,19 @@ module Test
|
|
407
459
|
@runner_options[:color_scheme] ||= @color_scheme
|
408
460
|
@runner_options[:listeners] ||= []
|
409
461
|
@runner_options[:listeners].concat(@listeners)
|
462
|
+
if @stop_on_failure
|
463
|
+
@runner_options[:listeners] << StopOnFailureListener.new
|
464
|
+
end
|
465
|
+
if @gc_stress
|
466
|
+
@runner_options[:listeners] << GCStressListener.new
|
467
|
+
end
|
410
468
|
change_work_directory do
|
411
469
|
runner.run(suite, @runner_options).passed?
|
412
470
|
end
|
413
471
|
end
|
414
472
|
|
415
473
|
def load_config(file)
|
416
|
-
require
|
474
|
+
require "yaml"
|
417
475
|
config = YAML.load(File.read(file))
|
418
476
|
runner_name = config["runner"]
|
419
477
|
@runner = self.class.runner(runner_name) || @runner
|
@@ -428,7 +486,7 @@ module Test
|
|
428
486
|
if key == :arguments
|
429
487
|
@default_arguments.concat(value.split)
|
430
488
|
else
|
431
|
-
runner_options[key
|
489
|
+
runner_options[key] = value
|
432
490
|
end
|
433
491
|
end
|
434
492
|
@runner_options = @runner_options.merge(runner_options)
|
@@ -468,6 +526,31 @@ module Test
|
|
468
526
|
end
|
469
527
|
end
|
470
528
|
|
529
|
+
def prepare_name(name)
|
530
|
+
case name
|
531
|
+
when /\A\/(.*)\/([imx]*)\z/
|
532
|
+
pattern = $1
|
533
|
+
options_raw = $2
|
534
|
+
options = 0
|
535
|
+
options |= Regexp::IGNORECASE if options_raw.include?("i")
|
536
|
+
options |= Regexp::MULTILINE if options_raw.include?("m")
|
537
|
+
options |= Regexp::EXTENDED if options_raw.include?("x")
|
538
|
+
Regexp.new(pattern, options)
|
539
|
+
else
|
540
|
+
name
|
541
|
+
end
|
542
|
+
end
|
543
|
+
|
544
|
+
def match_test_name(test, pattern)
|
545
|
+
return true if pattern === test.method_name
|
546
|
+
return true if pattern === test.local_name
|
547
|
+
if pattern.is_a?(String)
|
548
|
+
return true if pattern === "#{test.class}##{test.method_name}"
|
549
|
+
return true if pattern === "#{test.class}##{test.local_name}"
|
550
|
+
end
|
551
|
+
false
|
552
|
+
end
|
553
|
+
|
471
554
|
def match_test_case_name(test, pattern)
|
472
555
|
test.class.ancestors.each do |test_class|
|
473
556
|
break if test_class == TestCase
|
@@ -475,10 +558,49 @@ module Test
|
|
475
558
|
end
|
476
559
|
false
|
477
560
|
end
|
561
|
+
|
562
|
+
def add_test_path(path)
|
563
|
+
if /:(\d+)\z/ =~ path
|
564
|
+
line = $1.to_i
|
565
|
+
path = $PREMATCH
|
566
|
+
add_location_filter(path, line)
|
567
|
+
end
|
568
|
+
@to_run << path
|
569
|
+
end
|
570
|
+
|
571
|
+
def add_location_filter(path, line)
|
572
|
+
@filters << lambda do |test|
|
573
|
+
test.class.test_defined?(:path => path,
|
574
|
+
:line => line,
|
575
|
+
:method_name => test.method_name)
|
576
|
+
end
|
577
|
+
end
|
578
|
+
|
579
|
+
class StopOnFailureListener
|
580
|
+
def attach_to_mediator(mediator)
|
581
|
+
mediator.add_listener(TestResult::FINISHED) do |result|
|
582
|
+
result.stop unless result.passed?
|
583
|
+
end
|
584
|
+
end
|
585
|
+
end
|
586
|
+
|
587
|
+
class GCStressListener
|
588
|
+
def attach_to_mediator(mediator)
|
589
|
+
mediator.add_listener(TestCase::STARTED) do |test|
|
590
|
+
GC.start
|
591
|
+
GC.stress = true
|
592
|
+
end
|
593
|
+
|
594
|
+
mediator.add_listener(TestCase::FINISHED) do |test|
|
595
|
+
GC.start
|
596
|
+
GC.stress = false
|
597
|
+
end
|
598
|
+
end
|
599
|
+
end
|
478
600
|
end
|
479
601
|
end
|
480
602
|
end
|
481
603
|
|
482
|
-
require
|
483
|
-
require
|
484
|
-
require
|
604
|
+
require "test/unit/runner/console"
|
605
|
+
require "test/unit/runner/emacs"
|
606
|
+
require "test/unit/runner/xml"
|
@@ -26,16 +26,16 @@ module Test
|
|
26
26
|
def read_source(path)
|
27
27
|
return nil unless File.exist?(path)
|
28
28
|
lines = []
|
29
|
-
File.open(path) do |file|
|
29
|
+
File.open(path, "rb") do |file|
|
30
30
|
first_line = file.gets
|
31
31
|
break if first_line.nil?
|
32
|
-
encoding = detect_encoding(first_line)
|
33
|
-
|
34
|
-
first_line.force_encoding(encoding)
|
35
|
-
file.set_encoding(encoding, encoding)
|
36
|
-
end
|
32
|
+
encoding = detect_encoding(first_line) || Encoding::UTF_8
|
33
|
+
first_line.force_encoding(encoding)
|
37
34
|
lines << first_line
|
38
|
-
|
35
|
+
file.each_line do |line|
|
36
|
+
line.force_encoding(encoding)
|
37
|
+
lines << line
|
38
|
+
end
|
39
39
|
end
|
40
40
|
lines
|
41
41
|
end
|