test-unit 3.1.5 → 3.6.1
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 +797 -56
- 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 +175 -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/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 +2 -17
- metadata +20 -94
- 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,16 @@ 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
|
136
148
|
attr_writer :runner, :collector
|
137
149
|
|
138
150
|
def initialize(standalone)
|
@@ -141,11 +153,14 @@ module Test
|
|
141
153
|
@collector = default_collector
|
142
154
|
@filters = []
|
143
155
|
@to_run = []
|
156
|
+
@default_test_paths = []
|
144
157
|
@color_scheme = ColorScheme.default
|
145
158
|
@runner_options = {}
|
146
159
|
@default_arguments = []
|
147
160
|
@workdir = nil
|
148
161
|
@listeners = []
|
162
|
+
@stop_on_failure = false
|
163
|
+
@debug_on_failure = false
|
149
164
|
config_file = "test-unit.yml"
|
150
165
|
if File.exist?(config_file)
|
151
166
|
load_config(config_file)
|
@@ -155,6 +170,14 @@ module Test
|
|
155
170
|
yield(self) if block_given?
|
156
171
|
end
|
157
172
|
|
173
|
+
def stop_on_failure?
|
174
|
+
@stop_on_failure
|
175
|
+
end
|
176
|
+
|
177
|
+
def debug_on_failure?
|
178
|
+
@debug_on_failure
|
179
|
+
end
|
180
|
+
|
158
181
|
def prepare
|
159
182
|
PREPARE_HOOKS.each do |handler|
|
160
183
|
handler.call(self)
|
@@ -164,7 +187,7 @@ module Test
|
|
164
187
|
def process_args(args=ARGV)
|
165
188
|
begin
|
166
189
|
args.unshift(*@default_arguments)
|
167
|
-
options.order!(args) {|arg|
|
190
|
+
options.order!(args) {|arg| add_test_path(arg)}
|
168
191
|
rescue OptionParser::ParseError => e
|
169
192
|
puts e
|
170
193
|
puts options
|
@@ -176,110 +199,119 @@ module Test
|
|
176
199
|
def options
|
177
200
|
@options ||= OptionParser.new do |o|
|
178
201
|
o.banner = "Test::Unit automatic runner."
|
179
|
-
o.banner
|
202
|
+
o.banner += "\nUsage: #{$0} [options] [-- untouched arguments]"
|
180
203
|
|
181
|
-
o.on(
|
204
|
+
o.on("-r", "--runner=RUNNER", RUNNERS,
|
182
205
|
"Use the given RUNNER.",
|
183
206
|
"(" + keyword_display(RUNNERS) + ")") do |r|
|
184
207
|
@runner = r
|
185
208
|
end
|
186
209
|
|
187
|
-
o.on(
|
210
|
+
o.on("--collector=COLLECTOR", COLLECTORS,
|
188
211
|
"Use the given COLLECTOR.",
|
189
212
|
"(" + keyword_display(COLLECTORS) + ")") do |collector|
|
190
213
|
@collector = collector
|
191
214
|
end
|
192
215
|
|
193
216
|
if (@standalone)
|
194
|
-
o.on(
|
217
|
+
o.on("-b", "--basedir=DIR", "Base directory of test suites.") do |b|
|
195
218
|
@base = b
|
196
219
|
end
|
197
220
|
|
198
|
-
o.on(
|
221
|
+
o.on("-w", "--workdir=DIR", "Working directory to run tests.") do |w|
|
199
222
|
@workdir = w
|
200
223
|
end
|
201
224
|
|
202
|
-
o.on(
|
225
|
+
o.on("--default-test-path=PATH",
|
226
|
+
"Add PATH to the default test paths.",
|
227
|
+
"The PATH is used when user doesn't specify any test path.",
|
228
|
+
"You can specify this option multiple times.") do |path|
|
229
|
+
@default_test_paths << path
|
230
|
+
end
|
231
|
+
|
232
|
+
o.on("-a", "--add=TORUN", Array,
|
203
233
|
"Add TORUN to the list of things to run;",
|
204
|
-
"can be a file or a directory.") do |
|
205
|
-
|
234
|
+
"can be a file or a directory.") do |paths|
|
235
|
+
paths.each do |path|
|
236
|
+
add_test_path(path)
|
237
|
+
end
|
206
238
|
end
|
207
239
|
|
208
240
|
@pattern = []
|
209
|
-
o.on(
|
241
|
+
o.on("-p", "--pattern=PATTERN", Regexp,
|
210
242
|
"Match files to collect against PATTERN.") do |e|
|
211
243
|
@pattern << e
|
212
244
|
end
|
213
245
|
|
214
246
|
@exclude = []
|
215
|
-
o.on(
|
247
|
+
o.on("-x", "--exclude=PATTERN", Regexp,
|
216
248
|
"Ignore files to collect against PATTERN.") do |e|
|
217
249
|
@exclude << e
|
218
250
|
end
|
219
251
|
end
|
220
252
|
|
221
|
-
o.on(
|
253
|
+
o.on("-n", "--name=NAME", String,
|
222
254
|
"Runs tests matching NAME.",
|
223
|
-
"Use '/PATTERN/' for NAME to use regular expression."
|
224
|
-
|
255
|
+
"Use '/PATTERN/' for NAME to use regular expression.",
|
256
|
+
"Regular expression accepts options.",
|
257
|
+
"Example: '/taRget/i' matches 'target' and 'TARGET'") do |name|
|
258
|
+
name = prepare_name(name)
|
225
259
|
@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
|
260
|
+
match_test_name(test, name)
|
232
261
|
end
|
233
262
|
end
|
234
263
|
|
235
|
-
o.on(
|
264
|
+
o.on("--ignore-name=NAME", String,
|
236
265
|
"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}
|
266
|
+
"Use '/PATTERN/' for NAME to use regular expression.",
|
267
|
+
"Regular expression accepts options.",
|
268
|
+
"Example: '/taRget/i' matches 'target' and 'TARGET'") do |name|
|
269
|
+
name = prepare_name(name)
|
270
|
+
@filters << lambda do |test|
|
271
|
+
not match_test_name(test, name)
|
244
272
|
end
|
245
273
|
end
|
246
274
|
|
247
|
-
o.on(
|
275
|
+
o.on("-t", "--testcase=TESTCASE", String,
|
248
276
|
"Runs tests in TestCases matching TESTCASE.",
|
249
|
-
"Use '/PATTERN/' for TESTCASE to use regular expression."
|
250
|
-
|
277
|
+
"Use '/PATTERN/' for TESTCASE to use regular expression.",
|
278
|
+
"Regular expression accepts options.",
|
279
|
+
"Example: '/taRget/i' matches 'target' and 'TARGET'") do |name|
|
280
|
+
name = prepare_name(name)
|
251
281
|
@filters << lambda do |test|
|
252
|
-
match_test_case_name(test,
|
282
|
+
match_test_case_name(test, name)
|
253
283
|
end
|
254
284
|
end
|
255
285
|
|
256
|
-
o.on(
|
286
|
+
o.on("--ignore-testcase=TESTCASE", String,
|
257
287
|
"Ignores tests in TestCases matching TESTCASE.",
|
258
|
-
"Use '/PATTERN/' for TESTCASE to use regular expression."
|
259
|
-
|
288
|
+
"Use '/PATTERN/' for TESTCASE to use regular expression.",
|
289
|
+
"Regular expression accepts options.",
|
290
|
+
"Example: '/taRget/i' matches 'target' and 'TARGET'") do |name|
|
291
|
+
name = prepare_name(name)
|
260
292
|
@filters << lambda do |test|
|
261
|
-
not match_test_case_name(test,
|
293
|
+
not match_test_case_name(test, name)
|
262
294
|
end
|
263
295
|
end
|
264
296
|
|
265
|
-
o.on(
|
297
|
+
o.on("--location=LOCATION", String,
|
266
298
|
"Runs tests that defined in LOCATION.",
|
267
|
-
"LOCATION is one of PATH:LINE, PATH or LINE") do |location|
|
268
|
-
|
299
|
+
"LOCATION is one of PATH:LINE, PATH or LINE.") do |location|
|
300
|
+
case location
|
301
|
+
when /\A(\d+)\z/
|
269
302
|
path = nil
|
270
|
-
line =
|
303
|
+
line = $1.to_i
|
304
|
+
when /:(\d+)\z/
|
305
|
+
path = $PREMATCH
|
306
|
+
line = $1.to_i
|
271
307
|
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)
|
308
|
+
path = location
|
309
|
+
line = nil
|
279
310
|
end
|
311
|
+
add_location_filter(path, line)
|
280
312
|
end
|
281
313
|
|
282
|
-
o.on(
|
314
|
+
o.on("--attribute=EXPRESSION", String,
|
283
315
|
"Runs tests that matches EXPRESSION.",
|
284
316
|
"EXPRESSION is evaluated as Ruby's expression.",
|
285
317
|
"Test attribute name can be used with no receiver in EXPRESSION.",
|
@@ -317,7 +349,7 @@ module Test
|
|
317
349
|
Priority.default = priority
|
318
350
|
end
|
319
351
|
|
320
|
-
o.on(
|
352
|
+
o.on("-I", "--load-path=DIR[#{File::PATH_SEPARATOR}DIR...]",
|
321
353
|
"Appends directory list to $LOAD_PATH.") do |dirs|
|
322
354
|
$LOAD_PATH.concat(dirs.split(File::PATH_SEPARATOR))
|
323
355
|
end
|
@@ -330,7 +362,7 @@ module Test
|
|
330
362
|
end
|
331
363
|
|
332
364
|
o.on("--config=FILE",
|
333
|
-
"Use YAML
|
365
|
+
"Use YAML format FILE content as configuration file.") do |file|
|
334
366
|
load_config(file)
|
335
367
|
end
|
336
368
|
|
@@ -349,27 +381,39 @@ module Test
|
|
349
381
|
assertion_message_class.max_diff_target_string_size = size
|
350
382
|
end
|
351
383
|
|
384
|
+
o.on("--[no-]stop-on-failure",
|
385
|
+
"Stops immediately on the first non success test",
|
386
|
+
"(#{@stop_on_failure})") do |boolean|
|
387
|
+
@stop_on_failure = boolean
|
388
|
+
end
|
389
|
+
|
390
|
+
o.on("--[no-]debug-on-failure",
|
391
|
+
"Run debugger if available on failure",
|
392
|
+
"(#{AssertionFailedError.debug_on_failure?})") do |boolean|
|
393
|
+
AssertionFailedError.debug_on_failure = boolean
|
394
|
+
end
|
395
|
+
|
352
396
|
ADDITIONAL_OPTIONS.each do |option_builder|
|
353
397
|
option_builder.call(self, o)
|
354
398
|
end
|
355
399
|
|
356
|
-
o.on(
|
400
|
+
o.on("--",
|
357
401
|
"Stop processing options so that the",
|
358
402
|
"remaining options will be passed to the",
|
359
403
|
"test."){o.terminate}
|
360
404
|
|
361
|
-
o.on(
|
405
|
+
o.on("-h", "--help", "Display this help."){puts o; exit}
|
362
406
|
|
363
407
|
o.on_tail
|
364
|
-
o.on_tail(
|
408
|
+
o.on_tail("Deprecated options:")
|
365
409
|
|
366
|
-
o.on_tail(
|
410
|
+
o.on_tail("--console", "Console runner (use --runner).") do
|
367
411
|
warn("Deprecated option (--console).")
|
368
412
|
@runner = self.class.runner(:console)
|
369
413
|
end
|
370
414
|
|
371
415
|
if RUNNERS[:fox]
|
372
|
-
o.on_tail(
|
416
|
+
o.on_tail("--fox", "Fox runner (use --runner).") do
|
373
417
|
warn("Deprecated option (--fox).")
|
374
418
|
@runner = self.class.runner(:fox)
|
375
419
|
end
|
@@ -393,7 +437,7 @@ module Test
|
|
393
437
|
n = 1
|
394
438
|
end
|
395
439
|
i += 1
|
396
|
-
keyword.sub(/^(.{#{n}})([A-Za-z]+)(?=\w*$)/, '\\1[\\2]')
|
440
|
+
keyword.sub(/^(.{#{n}})([A-Za-z-]+)(?=\w*$)/, '\\1[\\2]')
|
397
441
|
end.join(", ")
|
398
442
|
end
|
399
443
|
|
@@ -407,13 +451,16 @@ module Test
|
|
407
451
|
@runner_options[:color_scheme] ||= @color_scheme
|
408
452
|
@runner_options[:listeners] ||= []
|
409
453
|
@runner_options[:listeners].concat(@listeners)
|
454
|
+
if @stop_on_failure
|
455
|
+
@runner_options[:listeners] << StopOnFailureListener.new
|
456
|
+
end
|
410
457
|
change_work_directory do
|
411
458
|
runner.run(suite, @runner_options).passed?
|
412
459
|
end
|
413
460
|
end
|
414
461
|
|
415
462
|
def load_config(file)
|
416
|
-
require
|
463
|
+
require "yaml"
|
417
464
|
config = YAML.load(File.read(file))
|
418
465
|
runner_name = config["runner"]
|
419
466
|
@runner = self.class.runner(runner_name) || @runner
|
@@ -428,7 +475,7 @@ module Test
|
|
428
475
|
if key == :arguments
|
429
476
|
@default_arguments.concat(value.split)
|
430
477
|
else
|
431
|
-
runner_options[key
|
478
|
+
runner_options[key] = value
|
432
479
|
end
|
433
480
|
end
|
434
481
|
@runner_options = @runner_options.merge(runner_options)
|
@@ -468,6 +515,31 @@ module Test
|
|
468
515
|
end
|
469
516
|
end
|
470
517
|
|
518
|
+
def prepare_name(name)
|
519
|
+
case name
|
520
|
+
when /\A\/(.*)\/([imx]*)\z/
|
521
|
+
pattern = $1
|
522
|
+
options_raw = $2
|
523
|
+
options = 0
|
524
|
+
options |= Regexp::IGNORECASE if options_raw.include?("i")
|
525
|
+
options |= Regexp::MULTILINE if options_raw.include?("m")
|
526
|
+
options |= Regexp::EXTENDED if options_raw.include?("x")
|
527
|
+
Regexp.new(pattern, options)
|
528
|
+
else
|
529
|
+
name
|
530
|
+
end
|
531
|
+
end
|
532
|
+
|
533
|
+
def match_test_name(test, pattern)
|
534
|
+
return true if pattern === test.method_name
|
535
|
+
return true if pattern === test.local_name
|
536
|
+
if pattern.is_a?(String)
|
537
|
+
return true if pattern === "#{test.class}##{test.method_name}"
|
538
|
+
return true if pattern === "#{test.class}##{test.local_name}"
|
539
|
+
end
|
540
|
+
false
|
541
|
+
end
|
542
|
+
|
471
543
|
def match_test_case_name(test, pattern)
|
472
544
|
test.class.ancestors.each do |test_class|
|
473
545
|
break if test_class == TestCase
|
@@ -475,10 +547,35 @@ module Test
|
|
475
547
|
end
|
476
548
|
false
|
477
549
|
end
|
550
|
+
|
551
|
+
def add_test_path(path)
|
552
|
+
if /:(\d+)\z/ =~ path
|
553
|
+
line = $1.to_i
|
554
|
+
path = $PREMATCH
|
555
|
+
add_location_filter(path, line)
|
556
|
+
end
|
557
|
+
@to_run << path
|
558
|
+
end
|
559
|
+
|
560
|
+
def add_location_filter(path, line)
|
561
|
+
@filters << lambda do |test|
|
562
|
+
test.class.test_defined?(:path => path,
|
563
|
+
:line => line,
|
564
|
+
:method_name => test.method_name)
|
565
|
+
end
|
566
|
+
end
|
567
|
+
|
568
|
+
class StopOnFailureListener
|
569
|
+
def attach_to_mediator(mediator)
|
570
|
+
mediator.add_listener(TestResult::FINISHED) do |result|
|
571
|
+
result.stop unless result.passed?
|
572
|
+
end
|
573
|
+
end
|
574
|
+
end
|
478
575
|
end
|
479
576
|
end
|
480
577
|
end
|
481
578
|
|
482
|
-
require
|
483
|
-
require
|
484
|
-
require
|
579
|
+
require "test/unit/runner/console"
|
580
|
+
require "test/unit/runner/emacs"
|
581
|
+
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
|