piko-max-mod 0.0.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 +7 -0
- data/piko-max-mod.gemspec +12 -0
- data/test-unit-3.7.8/BSDL +24 -0
- data/test-unit-3.7.8/COPYING +64 -0
- data/test-unit-3.7.8/PSFL +271 -0
- data/test-unit-3.7.8/README.md +108 -0
- data/test-unit-3.7.8/Rakefile +74 -0
- data/test-unit-3.7.8/bin/test-unit +5 -0
- data/test-unit-3.7.8/doc/text/getting-started.md +120 -0
- data/test-unit-3.7.8/doc/text/how-to.md +90 -0
- data/test-unit-3.7.8/doc/text/news.md +2070 -0
- data/test-unit-3.7.8/lib/test/unit/assertion-failed-error.rb +60 -0
- data/test-unit-3.7.8/lib/test/unit/assertions.rb +2536 -0
- data/test-unit-3.7.8/lib/test/unit/attribute-matcher.rb +26 -0
- data/test-unit-3.7.8/lib/test/unit/attribute.rb +228 -0
- data/test-unit-3.7.8/lib/test/unit/auto-runner-loader.rb +17 -0
- data/test-unit-3.7.8/lib/test/unit/autorunner.rb +654 -0
- data/test-unit-3.7.8/lib/test/unit/code-snippet-fetcher.rb +58 -0
- data/test-unit-3.7.8/lib/test/unit/collector/descendant.rb +20 -0
- data/test-unit-3.7.8/lib/test/unit/collector/dir.rb +110 -0
- data/test-unit-3.7.8/lib/test/unit/collector/load.rb +201 -0
- data/test-unit-3.7.8/lib/test/unit/collector/objectspace.rb +35 -0
- data/test-unit-3.7.8/lib/test/unit/collector/xml.rb +249 -0
- data/test-unit-3.7.8/lib/test/unit/collector.rb +104 -0
- data/test-unit-3.7.8/lib/test/unit/color-scheme.rb +225 -0
- data/test-unit-3.7.8/lib/test/unit/color.rb +134 -0
- data/test-unit-3.7.8/lib/test/unit/data-sets.rb +127 -0
- data/test-unit-3.7.8/lib/test/unit/data.rb +371 -0
- data/test-unit-3.7.8/lib/test/unit/diff.rb +745 -0
- data/test-unit-3.7.8/lib/test/unit/error.rb +158 -0
- data/test-unit-3.7.8/lib/test/unit/exception-handler.rb +82 -0
- data/test-unit-3.7.8/lib/test/unit/failure.rb +169 -0
- data/test-unit-3.7.8/lib/test/unit/fault-location-detector.rb +104 -0
- data/test-unit-3.7.8/lib/test/unit/fixture.rb +304 -0
- data/test-unit-3.7.8/lib/test/unit/notification.rb +138 -0
- data/test-unit-3.7.8/lib/test/unit/omission.rb +198 -0
- data/test-unit-3.7.8/lib/test/unit/pending.rb +155 -0
- data/test-unit-3.7.8/lib/test/unit/priority.rb +194 -0
- data/test-unit-3.7.8/lib/test/unit/process-test-result.rb +55 -0
- data/test-unit-3.7.8/lib/test/unit/process-worker.rb +87 -0
- data/test-unit-3.7.8/lib/test/unit/runner/console.rb +86 -0
- data/test-unit-3.7.8/lib/test/unit/runner/emacs.rb +8 -0
- data/test-unit-3.7.8/lib/test/unit/runner/xml.rb +15 -0
- data/test-unit-3.7.8/lib/test/unit/sub-test-result.rb +59 -0
- data/test-unit-3.7.8/lib/test/unit/test-process-run-context.rb +21 -0
- data/test-unit-3.7.8/lib/test/unit/test-run-context.rb +16 -0
- data/test-unit-3.7.8/lib/test/unit/test-suite-creator.rb +103 -0
- data/test-unit-3.7.8/lib/test/unit/test-suite-process-runner.rb +205 -0
- data/test-unit-3.7.8/lib/test/unit/test-suite-runner.rb +132 -0
- data/test-unit-3.7.8/lib/test/unit/test-suite-thread-runner.rb +96 -0
- data/test-unit-3.7.8/lib/test/unit/test-thread-run-context.rb +23 -0
- data/test-unit-3.7.8/lib/test/unit/testcase.rb +1058 -0
- data/test-unit-3.7.8/lib/test/unit/testresult.rb +132 -0
- data/test-unit-3.7.8/lib/test/unit/testsuite.rb +133 -0
- data/test-unit-3.7.8/lib/test/unit/ui/console/outputlevel.rb +15 -0
- data/test-unit-3.7.8/lib/test/unit/ui/console/testrunner.rb +891 -0
- data/test-unit-3.7.8/lib/test/unit/ui/emacs/testrunner.rb +49 -0
- data/test-unit-3.7.8/lib/test/unit/ui/testrunner.rb +53 -0
- data/test-unit-3.7.8/lib/test/unit/ui/testrunnermediator.rb +131 -0
- data/test-unit-3.7.8/lib/test/unit/ui/testrunnerutilities.rb +41 -0
- data/test-unit-3.7.8/lib/test/unit/ui/xml/testrunner.rb +225 -0
- data/test-unit-3.7.8/lib/test/unit/util/backtracefilter.rb +65 -0
- data/test-unit-3.7.8/lib/test/unit/util/memory-usage.rb +47 -0
- data/test-unit-3.7.8/lib/test/unit/util/method-owner-finder.rb +28 -0
- data/test-unit-3.7.8/lib/test/unit/util/observable.rb +86 -0
- data/test-unit-3.7.8/lib/test/unit/util/output.rb +32 -0
- data/test-unit-3.7.8/lib/test/unit/util/procwrapper.rb +48 -0
- data/test-unit-3.7.8/lib/test/unit/version.rb +5 -0
- data/test-unit-3.7.8/lib/test/unit/warning.rb +3 -0
- data/test-unit-3.7.8/lib/test/unit/worker-context.rb +20 -0
- data/test-unit-3.7.8/lib/test/unit.rb +521 -0
- data/test-unit-3.7.8/lib/test-unit.rb +19 -0
- data/test-unit-3.7.8/sample/adder.rb +13 -0
- data/test-unit-3.7.8/sample/subtracter.rb +12 -0
- data/test-unit-3.7.8/sample/test_adder.rb +20 -0
- data/test-unit-3.7.8/sample/test_subtracter.rb +20 -0
- data/test-unit-3.7.8/sample/test_user.rb +23 -0
- metadata +117 -0
|
@@ -0,0 +1,654 @@
|
|
|
1
|
+
require "English"
|
|
2
|
+
require "optparse"
|
|
3
|
+
|
|
4
|
+
require_relative "color-scheme"
|
|
5
|
+
require_relative "priority"
|
|
6
|
+
require_relative "attribute-matcher"
|
|
7
|
+
require_relative "testcase"
|
|
8
|
+
require_relative "test-suite-thread-runner"
|
|
9
|
+
require_relative "test-suite-process-runner"
|
|
10
|
+
require_relative "version"
|
|
11
|
+
|
|
12
|
+
module Test
|
|
13
|
+
module Unit
|
|
14
|
+
class AutoRunner
|
|
15
|
+
RUNNERS = {}
|
|
16
|
+
COLLECTORS = {}
|
|
17
|
+
ADDITIONAL_OPTIONS = []
|
|
18
|
+
PREPARE_HOOKS = []
|
|
19
|
+
|
|
20
|
+
class << self
|
|
21
|
+
def register_runner(id, runner_builder=nil, &block)
|
|
22
|
+
runner_builder ||= Proc.new(&block)
|
|
23
|
+
RUNNERS[id] = runner_builder
|
|
24
|
+
RUNNERS[id.to_s] = runner_builder
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def runner(id)
|
|
28
|
+
RUNNERS[id.to_s]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
@@default_runner = nil
|
|
32
|
+
def default_runner
|
|
33
|
+
runner(@@default_runner)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def default_runner=(id)
|
|
37
|
+
@@default_runner = id
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def register_collector(id, collector_builder=nil, &block)
|
|
41
|
+
collector_builder ||= Proc.new(&block)
|
|
42
|
+
COLLECTORS[id] = collector_builder
|
|
43
|
+
COLLECTORS[id.to_s] = collector_builder
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def collector(id)
|
|
47
|
+
COLLECTORS[id.to_s]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def register_color_scheme(id, scheme)
|
|
51
|
+
ColorScheme[id] = scheme
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def setup_option(option_builder=nil, &block)
|
|
55
|
+
option_builder ||= Proc.new(&block)
|
|
56
|
+
ADDITIONAL_OPTIONS << option_builder
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def prepare(hook=nil, &block)
|
|
60
|
+
hook ||= Proc.new(&block)
|
|
61
|
+
PREPARE_HOOKS << hook
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def run(force_standalone=false, default_dir=nil, argv=ARGV, &block)
|
|
65
|
+
r = new(force_standalone || standalone?, &block)
|
|
66
|
+
r.base = default_dir
|
|
67
|
+
r.prepare
|
|
68
|
+
r.process_args(argv)
|
|
69
|
+
r.run
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def standalone?
|
|
73
|
+
return false unless("-e" == $0)
|
|
74
|
+
ObjectSpace.each_object(Class) do |klass|
|
|
75
|
+
return false if(klass < TestCase)
|
|
76
|
+
end
|
|
77
|
+
true
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
@@need_auto_run = true
|
|
81
|
+
def need_auto_run?
|
|
82
|
+
@@need_auto_run
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def need_auto_run=(need)
|
|
86
|
+
@@need_auto_run = need
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
register_collector(:descendant) do |auto_runner|
|
|
91
|
+
require_relative "collector/descendant"
|
|
92
|
+
collector = Collector::Descendant.new
|
|
93
|
+
collector.filter = auto_runner.filters
|
|
94
|
+
collector.collect($0.sub(/\.rb\Z/, ""))
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
register_collector(:load) do |auto_runner|
|
|
98
|
+
require_relative "collector/load"
|
|
99
|
+
collector = Collector::Load.new
|
|
100
|
+
unless auto_runner.pattern.empty?
|
|
101
|
+
collector.patterns.replace(auto_runner.pattern)
|
|
102
|
+
end
|
|
103
|
+
unless auto_runner.exclude.empty?
|
|
104
|
+
collector.excludes.replace(auto_runner.exclude)
|
|
105
|
+
end
|
|
106
|
+
collector.base = auto_runner.base
|
|
107
|
+
collector.default_test_paths = auto_runner.default_test_paths
|
|
108
|
+
collector.filter = auto_runner.filters
|
|
109
|
+
collector.collect(*auto_runner.to_run)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# JUST TEST!
|
|
113
|
+
# register_collector(:xml) do |auto_runner|
|
|
114
|
+
# require_relative "collector/xml"
|
|
115
|
+
# collector = Collector::XML.new
|
|
116
|
+
# collector.filter = auto_runner.filters
|
|
117
|
+
# collector.collect(auto_runner.to_run[0])
|
|
118
|
+
# end
|
|
119
|
+
|
|
120
|
+
# deprecated
|
|
121
|
+
register_collector(:object_space) do |auto_runner|
|
|
122
|
+
require_relative "collector/objectspace"
|
|
123
|
+
c = Collector::ObjectSpace.new
|
|
124
|
+
c.filter = auto_runner.filters
|
|
125
|
+
c.collect($0.sub(/\.rb\Z/, ""))
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# deprecated
|
|
129
|
+
register_collector(:dir) do |auto_runner|
|
|
130
|
+
require_relative "collector/dir"
|
|
131
|
+
c = Collector::Dir.new
|
|
132
|
+
c.filter = auto_runner.filters
|
|
133
|
+
unless auto_runner.pattern.empty?
|
|
134
|
+
c.pattern.replace(auto_runner.pattern)
|
|
135
|
+
end
|
|
136
|
+
unless auto_runner.exclude.empty?
|
|
137
|
+
c.exclude.replace(auto_runner.exclude)
|
|
138
|
+
end
|
|
139
|
+
c.base = auto_runner.base
|
|
140
|
+
$:.push(auto_runner.base) if auto_runner.base
|
|
141
|
+
c.collect(*(auto_runner.to_run.empty? ? ["."] : auto_runner.to_run))
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
attr_reader :suite, :runner_options
|
|
145
|
+
attr_accessor :filters, :to_run
|
|
146
|
+
attr_accessor :default_test_paths
|
|
147
|
+
attr_accessor :pattern, :exclude, :base, :workdir
|
|
148
|
+
attr_accessor :color_scheme, :listeners
|
|
149
|
+
attr_writer :stop_on_failure
|
|
150
|
+
attr_writer :debug_on_failure
|
|
151
|
+
attr_writer :gc_stress
|
|
152
|
+
attr_writer :runner, :collector
|
|
153
|
+
|
|
154
|
+
def initialize(standalone)
|
|
155
|
+
@standalone = standalone
|
|
156
|
+
@runner = default_runner
|
|
157
|
+
@collector = default_collector
|
|
158
|
+
@filters = []
|
|
159
|
+
@to_run = []
|
|
160
|
+
@default_test_paths = []
|
|
161
|
+
@color_scheme = ColorScheme.default
|
|
162
|
+
@runner_options = {}
|
|
163
|
+
@default_arguments = []
|
|
164
|
+
@workdir = nil
|
|
165
|
+
@listeners = []
|
|
166
|
+
@stop_on_failure = false
|
|
167
|
+
@debug_on_failure = false
|
|
168
|
+
@gc_stress = false
|
|
169
|
+
@test_suite_runner_class = TestSuiteRunner
|
|
170
|
+
@load_paths = []
|
|
171
|
+
config_file = "test-unit.yml"
|
|
172
|
+
if File.exist?(config_file)
|
|
173
|
+
load_config(config_file)
|
|
174
|
+
else
|
|
175
|
+
load_global_config
|
|
176
|
+
end
|
|
177
|
+
plain_text_config_file = ".test-unit"
|
|
178
|
+
if File.exist?(plain_text_config_file)
|
|
179
|
+
load_plain_text_config(plain_text_config_file)
|
|
180
|
+
end
|
|
181
|
+
yield(self) if block_given?
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def stop_on_failure?
|
|
185
|
+
@stop_on_failure
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def debug_on_failure?
|
|
189
|
+
@debug_on_failure
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def prepare
|
|
193
|
+
PREPARE_HOOKS.each do |handler|
|
|
194
|
+
handler.call(self)
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def process_args(args=ARGV)
|
|
199
|
+
begin
|
|
200
|
+
args.unshift(*@default_arguments)
|
|
201
|
+
options.order!(args) {|arg| add_test_path(arg)}
|
|
202
|
+
$LOAD_PATH.unshift(*@load_paths)
|
|
203
|
+
rescue OptionParser::ParseError => e
|
|
204
|
+
puts e
|
|
205
|
+
puts options
|
|
206
|
+
exit(false)
|
|
207
|
+
end
|
|
208
|
+
not @to_run.empty?
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def options
|
|
212
|
+
@options ||= OptionParser.new do |o|
|
|
213
|
+
o.version = VERSION
|
|
214
|
+
|
|
215
|
+
o.banner = "Test::Unit automatic runner."
|
|
216
|
+
o.banner += "\nUsage: #{$0} [options] [-- untouched arguments]"
|
|
217
|
+
|
|
218
|
+
o.on("-r", "--runner=RUNNER", RUNNERS,
|
|
219
|
+
"Use the given RUNNER.",
|
|
220
|
+
"(" + keyword_display(RUNNERS) + ")") do |r|
|
|
221
|
+
@runner = r
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
o.on("--collector=COLLECTOR", COLLECTORS,
|
|
225
|
+
"Use the given COLLECTOR.",
|
|
226
|
+
"(" + keyword_display(COLLECTORS) + ")") do |collector|
|
|
227
|
+
@collector = collector
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
if (@standalone)
|
|
231
|
+
o.on("-b", "--basedir=DIR", "Base directory of test suites.") do |b|
|
|
232
|
+
@base = b
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
o.on("-w", "--workdir=DIR", "Working directory to run tests.") do |w|
|
|
236
|
+
@workdir = w
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
o.on("--default-test-path=PATH",
|
|
240
|
+
"Add PATH to the default test paths.",
|
|
241
|
+
"The PATH is used when user doesn't specify any test path.",
|
|
242
|
+
"You can specify this option multiple times.") do |path|
|
|
243
|
+
@default_test_paths << path
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
o.on("-a", "--add=TORUN", Array,
|
|
247
|
+
"Add TORUN to the list of things to run;",
|
|
248
|
+
"can be a file or a directory.") do |paths|
|
|
249
|
+
paths.each do |path|
|
|
250
|
+
add_test_path(path)
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
@pattern = []
|
|
255
|
+
o.on("-p", "--pattern=PATTERN", Regexp,
|
|
256
|
+
"Match files to collect against PATTERN.") do |e|
|
|
257
|
+
@pattern << e
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
@exclude = []
|
|
261
|
+
o.on("-x", "--exclude=PATTERN", Regexp,
|
|
262
|
+
"Ignore files to collect against PATTERN.") do |e|
|
|
263
|
+
@exclude << e
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
o.on("-n", "--name=NAME", String,
|
|
268
|
+
"Runs tests matching NAME.",
|
|
269
|
+
"Use '/PATTERN/' for NAME to use regular expression.",
|
|
270
|
+
"Regular expression accepts options.",
|
|
271
|
+
"Example: '/taRget/i' matches 'target' and 'TARGET'") do |name|
|
|
272
|
+
name = prepare_name(name)
|
|
273
|
+
@filters << lambda do |test|
|
|
274
|
+
match_test_name(test, name)
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
o.on("--ignore-name=NAME", String,
|
|
279
|
+
"Ignores tests matching NAME.",
|
|
280
|
+
"Use '/PATTERN/' for NAME to use regular expression.",
|
|
281
|
+
"Regular expression accepts options.",
|
|
282
|
+
"Example: '/taRget/i' matches 'target' and 'TARGET'") do |name|
|
|
283
|
+
name = prepare_name(name)
|
|
284
|
+
@filters << lambda do |test|
|
|
285
|
+
not match_test_name(test, name)
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
o.on("-t", "--testcase=TESTCASE", String,
|
|
290
|
+
"Runs tests in TestCases matching TESTCASE.",
|
|
291
|
+
"Use '/PATTERN/' for TESTCASE to use regular expression.",
|
|
292
|
+
"Regular expression accepts options.",
|
|
293
|
+
"Example: '/taRget/i' matches 'target' and 'TARGET'") do |name|
|
|
294
|
+
name = prepare_name(name)
|
|
295
|
+
@filters << lambda do |test|
|
|
296
|
+
match_test_case_name(test, name)
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
o.on("--ignore-testcase=TESTCASE", String,
|
|
301
|
+
"Ignores tests in TestCases matching TESTCASE.",
|
|
302
|
+
"Use '/PATTERN/' for TESTCASE to use regular expression.",
|
|
303
|
+
"Regular expression accepts options.",
|
|
304
|
+
"Example: '/taRget/i' matches 'target' and 'TARGET'") do |name|
|
|
305
|
+
name = prepare_name(name)
|
|
306
|
+
@filters << lambda do |test|
|
|
307
|
+
not match_test_case_name(test, name)
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
o.on("--location=LOCATION", String,
|
|
312
|
+
"Runs tests that defined in LOCATION.",
|
|
313
|
+
"LOCATION is one of PATH:LINE, PATH or LINE.") do |location|
|
|
314
|
+
case location
|
|
315
|
+
when /\A(\d+)\z/
|
|
316
|
+
path = nil
|
|
317
|
+
line = $1.to_i
|
|
318
|
+
when /:(\d+)\z/
|
|
319
|
+
path = $PREMATCH
|
|
320
|
+
line = $1.to_i
|
|
321
|
+
else
|
|
322
|
+
path = location
|
|
323
|
+
line = nil
|
|
324
|
+
end
|
|
325
|
+
add_location_filter(path, line)
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
o.on("--attribute=EXPRESSION", String,
|
|
329
|
+
"Runs tests that matches EXPRESSION.",
|
|
330
|
+
"EXPRESSION is evaluated as Ruby's expression.",
|
|
331
|
+
"Test attribute name can be used with no receiver in EXPRESSION.",
|
|
332
|
+
"EXPRESSION examples:",
|
|
333
|
+
" !slow",
|
|
334
|
+
" tag == 'important' and !slow") do |expression|
|
|
335
|
+
@filters << lambda do |test|
|
|
336
|
+
matcher = AttributeMatcher.new(test)
|
|
337
|
+
matcher.match?(expression)
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
priority_filter = Proc.new do |test|
|
|
342
|
+
if @filters == [priority_filter]
|
|
343
|
+
Priority::Checker.new(test).need_to_run?
|
|
344
|
+
else
|
|
345
|
+
nil
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
o.on("--[no-]priority-mode",
|
|
349
|
+
"Runs some tests based on their priority.") do |priority_mode|
|
|
350
|
+
if priority_mode
|
|
351
|
+
Priority.enable
|
|
352
|
+
@filters |= [priority_filter]
|
|
353
|
+
else
|
|
354
|
+
Priority.disable
|
|
355
|
+
@filters -= [priority_filter]
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
o.on("--default-priority=PRIORITY",
|
|
360
|
+
Priority.available_values,
|
|
361
|
+
"Uses PRIORITY as default priority",
|
|
362
|
+
"(#{keyword_display(Priority.available_values)})") do |priority|
|
|
363
|
+
Priority.default = priority
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
o.on("-I", "--load-path=DIR[#{File::PATH_SEPARATOR}DIR...]",
|
|
367
|
+
"Prepends directory list to $LOAD_PATH.") do |dirs|
|
|
368
|
+
@load_paths.concat(dirs.split(File::PATH_SEPARATOR))
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
color_schemes = ColorScheme.all
|
|
372
|
+
o.on("--color-scheme=SCHEME", color_schemes,
|
|
373
|
+
"Use SCHEME as color scheme.",
|
|
374
|
+
"(#{keyword_display(color_schemes)})") do |scheme|
|
|
375
|
+
@color_scheme = scheme
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
o.on("--config=FILE",
|
|
379
|
+
"Use YAML format FILE content as configuration file.") do |file|
|
|
380
|
+
load_config(file)
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
o.on("--order=ORDER", TestCase::AVAILABLE_ORDERS,
|
|
384
|
+
"Run tests in a test case in ORDER order.",
|
|
385
|
+
"(#{keyword_display(TestCase::AVAILABLE_ORDERS)})") do |order|
|
|
386
|
+
TestCase.test_order = order
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
assertion_message_class = Test::Unit::Assertions::AssertionMessage
|
|
390
|
+
o.on("--max-diff-target-string-size=SIZE", Integer,
|
|
391
|
+
"Shows diff if both expected result string size and " +
|
|
392
|
+
"actual result string size are " +
|
|
393
|
+
"less than or equal SIZE in bytes.",
|
|
394
|
+
"(#{assertion_message_class.max_diff_target_string_size})") do |size|
|
|
395
|
+
assertion_message_class.max_diff_target_string_size = size
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
o.on("--[no-]stop-on-failure",
|
|
399
|
+
"Stops immediately on the first non success test",
|
|
400
|
+
"(#{@stop_on_failure})") do |boolean|
|
|
401
|
+
@stop_on_failure = boolean
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
o.on("--[no-]debug-on-failure",
|
|
405
|
+
"Run debugger if available on failure",
|
|
406
|
+
"(#{AssertionFailedError.debug_on_failure?})") do |boolean|
|
|
407
|
+
AssertionFailedError.debug_on_failure = boolean
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
o.on("--[no-]gc-stress",
|
|
411
|
+
"Enable GC.stress only while each test is running",
|
|
412
|
+
"(#{@gc_stress})") do |boolean|
|
|
413
|
+
@gc_stress = boolean
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
parallel_options = [
|
|
417
|
+
:thread,
|
|
418
|
+
:process,
|
|
419
|
+
]
|
|
420
|
+
o.on("--[no-]parallel=[PARALLEL]", parallel_options,
|
|
421
|
+
"Runs tests in parallel: #{parallel_options.join(", ")}",
|
|
422
|
+
"(#{parallel_options.first})") do |parallel|
|
|
423
|
+
case parallel
|
|
424
|
+
when nil, :thread
|
|
425
|
+
@test_suite_runner_class = TestSuiteThreadRunner
|
|
426
|
+
when :process
|
|
427
|
+
@test_suite_runner_class = TestSuiteProcessRunner
|
|
428
|
+
else
|
|
429
|
+
@test_suite_runner_class = TestSuiteRunner
|
|
430
|
+
end
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
o.on("--n-workers=N", Integer,
|
|
434
|
+
"The number of parallelism",
|
|
435
|
+
"(#{TestSuiteRunner.n_workers})") do |n|
|
|
436
|
+
TestSuiteRunner.n_workers = n
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
ADDITIONAL_OPTIONS.each do |option_builder|
|
|
440
|
+
option_builder.call(self, o)
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
o.on("--",
|
|
444
|
+
"Stop processing options so that the",
|
|
445
|
+
"remaining options will be passed to the",
|
|
446
|
+
"test."){o.terminate}
|
|
447
|
+
|
|
448
|
+
o.on("-h", "--help", "Display this help."){puts o; exit}
|
|
449
|
+
|
|
450
|
+
o.on_tail
|
|
451
|
+
o.on_tail("Deprecated options:")
|
|
452
|
+
|
|
453
|
+
o.on_tail("--console", "Console runner (use --runner).") do
|
|
454
|
+
warn("Deprecated option (--console).")
|
|
455
|
+
@runner = self.class.runner(:console)
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
if RUNNERS[:fox]
|
|
459
|
+
o.on_tail("--fox", "Fox runner (use --runner).") do
|
|
460
|
+
warn("Deprecated option (--fox).")
|
|
461
|
+
@runner = self.class.runner(:fox)
|
|
462
|
+
end
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
o.on_tail
|
|
466
|
+
end
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
def keyword_display(keywords)
|
|
470
|
+
keywords = keywords.collect do |keyword, _|
|
|
471
|
+
keyword.to_s
|
|
472
|
+
end.uniq.sort
|
|
473
|
+
|
|
474
|
+
i = 0
|
|
475
|
+
keywords.collect do |keyword|
|
|
476
|
+
if (i > 0 and keyword[0] == keywords[i - 1][0]) or
|
|
477
|
+
((i < keywords.size - 1) and (keyword[0] == keywords[i + 1][0]))
|
|
478
|
+
n = 2
|
|
479
|
+
else
|
|
480
|
+
n = 1
|
|
481
|
+
end
|
|
482
|
+
i += 1
|
|
483
|
+
keyword.sub(/^(.{#{n}})([A-Za-z-]+)(?=\w*$)/, '\\1[\\2]')
|
|
484
|
+
end.join(", ")
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
def run
|
|
488
|
+
self.class.need_auto_run = false
|
|
489
|
+
suite = @collector[self]
|
|
490
|
+
return false if suite.nil?
|
|
491
|
+
return true if suite.empty?
|
|
492
|
+
runner = @runner[self]
|
|
493
|
+
return false if runner.nil?
|
|
494
|
+
@runner_options[:color_scheme] ||= @color_scheme
|
|
495
|
+
@runner_options[:listeners] ||= []
|
|
496
|
+
@runner_options[:listeners].concat(@listeners)
|
|
497
|
+
if @stop_on_failure
|
|
498
|
+
@runner_options[:listeners] << StopOnFailureListener.new
|
|
499
|
+
end
|
|
500
|
+
if @gc_stress
|
|
501
|
+
@runner_options[:listeners] << GCStressListener.new
|
|
502
|
+
end
|
|
503
|
+
@runner_options[:test_suite_runner_class] = @test_suite_runner_class
|
|
504
|
+
@runner_options[:load_paths] = @load_paths
|
|
505
|
+
@runner_options[:base_directory] = @base
|
|
506
|
+
@runner_options[:test_paths] = @to_run
|
|
507
|
+
change_work_directory do
|
|
508
|
+
runner.run(suite, @runner_options).passed?
|
|
509
|
+
end
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
def load_config(file)
|
|
513
|
+
require "yaml"
|
|
514
|
+
config = YAML.load(File.read(file))
|
|
515
|
+
runner_name = config["runner"]
|
|
516
|
+
@runner = self.class.runner(runner_name) || @runner
|
|
517
|
+
@collector = self.class.collector(config["collector"]) || @collector
|
|
518
|
+
(config["color_schemes"] || {}).each do |name, options|
|
|
519
|
+
ColorScheme[name] = options
|
|
520
|
+
end
|
|
521
|
+
runner_options = {}
|
|
522
|
+
(config["#{runner_name}_options"] || {}).each do |key, value|
|
|
523
|
+
key = key.to_sym
|
|
524
|
+
value = ColorScheme[value] if key == :color_scheme
|
|
525
|
+
if key == :arguments
|
|
526
|
+
@default_arguments.concat(value.split)
|
|
527
|
+
else
|
|
528
|
+
runner_options[key] = value
|
|
529
|
+
end
|
|
530
|
+
end
|
|
531
|
+
@runner_options = @runner_options.merge(runner_options)
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
def load_plain_text_config(file)
|
|
535
|
+
require "shellwords"
|
|
536
|
+
File.readlines(file, chomp: true).each do |line|
|
|
537
|
+
next if line.empty?
|
|
538
|
+
args = Shellwords.shellsplit(line)
|
|
539
|
+
@default_arguments.concat(args)
|
|
540
|
+
end
|
|
541
|
+
end
|
|
542
|
+
|
|
543
|
+
private
|
|
544
|
+
def default_runner
|
|
545
|
+
runner = self.class.default_runner
|
|
546
|
+
if ENV["EMACS"] == "t"
|
|
547
|
+
runner ||= self.class.runner(:emacs)
|
|
548
|
+
else
|
|
549
|
+
runner ||= self.class.runner(:console)
|
|
550
|
+
end
|
|
551
|
+
runner
|
|
552
|
+
end
|
|
553
|
+
|
|
554
|
+
def default_collector
|
|
555
|
+
self.class.collector(@standalone ? :load : :descendant)
|
|
556
|
+
end
|
|
557
|
+
|
|
558
|
+
def global_config_file
|
|
559
|
+
File.expand_path("~/.test-unit.yml")
|
|
560
|
+
rescue ArgumentError
|
|
561
|
+
nil
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
def load_global_config
|
|
565
|
+
file = global_config_file
|
|
566
|
+
load_config(file) if file and File.exist?(file)
|
|
567
|
+
end
|
|
568
|
+
|
|
569
|
+
def change_work_directory(&block)
|
|
570
|
+
if @workdir
|
|
571
|
+
Dir.chdir(@workdir, &block)
|
|
572
|
+
else
|
|
573
|
+
yield
|
|
574
|
+
end
|
|
575
|
+
end
|
|
576
|
+
|
|
577
|
+
def prepare_name(name)
|
|
578
|
+
case name
|
|
579
|
+
when /\A\/(.*)\/([imx]*)\z/
|
|
580
|
+
pattern = $1
|
|
581
|
+
options_raw = $2
|
|
582
|
+
options = 0
|
|
583
|
+
options |= Regexp::IGNORECASE if options_raw.include?("i")
|
|
584
|
+
options |= Regexp::MULTILINE if options_raw.include?("m")
|
|
585
|
+
options |= Regexp::EXTENDED if options_raw.include?("x")
|
|
586
|
+
Regexp.new(pattern, options)
|
|
587
|
+
else
|
|
588
|
+
name
|
|
589
|
+
end
|
|
590
|
+
end
|
|
591
|
+
|
|
592
|
+
def match_test_name(test, pattern)
|
|
593
|
+
return true if pattern === test.method_name
|
|
594
|
+
return true if pattern === test.local_name
|
|
595
|
+
if pattern.is_a?(String)
|
|
596
|
+
return true if pattern === "#{test.class}##{test.method_name}"
|
|
597
|
+
return true if pattern === "#{test.class}##{test.local_name}"
|
|
598
|
+
end
|
|
599
|
+
false
|
|
600
|
+
end
|
|
601
|
+
|
|
602
|
+
def match_test_case_name(test, pattern)
|
|
603
|
+
test.class.ancestors.each do |test_class|
|
|
604
|
+
break if test_class == TestCase
|
|
605
|
+
return true if pattern === test_class.name
|
|
606
|
+
end
|
|
607
|
+
false
|
|
608
|
+
end
|
|
609
|
+
|
|
610
|
+
def add_test_path(path)
|
|
611
|
+
if /:(\d+)\z/ =~ path
|
|
612
|
+
line = $1.to_i
|
|
613
|
+
path = $PREMATCH
|
|
614
|
+
add_location_filter(path, line)
|
|
615
|
+
end
|
|
616
|
+
@to_run << path
|
|
617
|
+
end
|
|
618
|
+
|
|
619
|
+
def add_location_filter(path, line)
|
|
620
|
+
@filters << lambda do |test|
|
|
621
|
+
test.class.test_defined?(:path => path,
|
|
622
|
+
:line => line,
|
|
623
|
+
:method_name => test.method_name)
|
|
624
|
+
end
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
class StopOnFailureListener
|
|
628
|
+
def attach_to_mediator(mediator)
|
|
629
|
+
mediator.add_listener(TestResult::FINISHED) do |result|
|
|
630
|
+
result.stop unless result.passed?
|
|
631
|
+
end
|
|
632
|
+
end
|
|
633
|
+
end
|
|
634
|
+
|
|
635
|
+
class GCStressListener
|
|
636
|
+
def attach_to_mediator(mediator)
|
|
637
|
+
mediator.add_listener(TestCase::STARTED) do |test|
|
|
638
|
+
GC.start
|
|
639
|
+
GC.stress = true
|
|
640
|
+
end
|
|
641
|
+
|
|
642
|
+
mediator.add_listener(TestCase::FINISHED) do |test|
|
|
643
|
+
GC.start
|
|
644
|
+
GC.stress = false
|
|
645
|
+
end
|
|
646
|
+
end
|
|
647
|
+
end
|
|
648
|
+
end
|
|
649
|
+
end
|
|
650
|
+
end
|
|
651
|
+
|
|
652
|
+
require_relative "runner/console"
|
|
653
|
+
require_relative "runner/emacs"
|
|
654
|
+
require_relative "runner/xml"
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
module Test
|
|
2
|
+
module Unit
|
|
3
|
+
class CodeSnippetFetcher
|
|
4
|
+
def initialize
|
|
5
|
+
@sources = {}
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def fetch(path, line, options={})
|
|
9
|
+
n_context_line = options[:n_context_line] || 3
|
|
10
|
+
lines = source(path)
|
|
11
|
+
return [] if lines.nil?
|
|
12
|
+
min_line = [line - n_context_line, 1].max
|
|
13
|
+
max_line = [line + n_context_line, lines.length].min
|
|
14
|
+
window = min_line..max_line
|
|
15
|
+
window.collect do |n|
|
|
16
|
+
attributes = {:target_line? => (n == line)}
|
|
17
|
+
[n, lines[n - 1].chomp, attributes]
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def source(path)
|
|
22
|
+
@sources[path] ||= read_source(path)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
def read_source(path)
|
|
27
|
+
return nil unless File.exist?(path)
|
|
28
|
+
lines = []
|
|
29
|
+
File.open(path, "rb") do |file|
|
|
30
|
+
first_line = file.gets
|
|
31
|
+
break if first_line.nil?
|
|
32
|
+
encoding = detect_encoding(first_line) || Encoding::UTF_8
|
|
33
|
+
first_line.force_encoding(encoding)
|
|
34
|
+
lines << first_line
|
|
35
|
+
file.each_line do |line|
|
|
36
|
+
line.force_encoding(encoding)
|
|
37
|
+
lines << line
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
lines
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def detect_encoding(first_line)
|
|
44
|
+
return nil unless first_line.respond_to?(:ascii_only?)
|
|
45
|
+
return nil unless first_line.ascii_only?
|
|
46
|
+
if /\b(?:en)?coding[:=]\s*([a-z\d_-]+)/i =~ first_line
|
|
47
|
+
begin
|
|
48
|
+
Encoding.find($1)
|
|
49
|
+
rescue ArgumentError
|
|
50
|
+
nil
|
|
51
|
+
end
|
|
52
|
+
else
|
|
53
|
+
nil
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|