9
ADDITIONAL_OPTIONS = []
12
def register_runner(id, runner_builder=Proc.new)
13
RUNNERS[id] = runner_builder
16
def register_collector(id, collector_builder=Proc.new)
17
COLLECTORS[id] = collector_builder
20
def setup_option(option_builder=Proc.new)
21
ADDITIONAL_OPTIONS << option_builder
25
def self.run(force_standalone=false, default_dir=nil, argv=ARGV, &block)
26
r = new(force_standalone || standalone?, &block)
33
return false unless("-e" == $0)
34
ObjectSpace.each_object(Class) do |klass|
35
return false if(klass < TestCase)
40
register_collector(:descendant) do |auto_runner|
41
require 'test/unit/collector/descendant'
42
collector = Collector::Descendant.new
43
collector.filter = auto_runner.filters
44
collector.collect($0.sub(/\.rb\Z/, ''))
47
register_collector(:load) do |auto_runner|
48
require 'test/unit/collector/load'
49
collector = Collector::Load.new
50
collector.patterns.concat(auto_runner.pattern) if auto_runner.pattern
51
collector.excludes.concat(auto_runner.exclude) if auto_runner.exclude
52
collector.base = auto_runner.base
53
collector.filter = auto_runner.filters
54
collector.collect(*auto_runner.to_run)
58
register_collector(:object_space) do |auto_runner|
59
require 'test/unit/collector/objectspace'
60
c = Collector::ObjectSpace.new
61
c.filter = auto_runner.filters
62
c.collect($0.sub(/\.rb\Z/, ''))
66
register_collector(:dir) do |auto_runner|
67
require 'test/unit/collector/dir'
68
c = Collector::Dir.new
69
c.filter = auto_runner.filters
70
c.pattern.concat(auto_runner.pattern) if auto_runner.pattern
71
c.exclude.concat(auto_runner.exclude) if auto_runner.exclude
72
c.base = auto_runner.base
73
$:.push(auto_runner.base) if auto_runner.base
74
c.collect(*(auto_runner.to_run.empty? ? ['.'] : auto_runner.to_run))
77
attr_reader :suite, :runner_options
78
attr_accessor :filters, :to_run, :pattern, :exclude, :base, :workdir
79
attr_writer :runner, :collector
81
def initialize(standalone)
83
@standalone = standalone
84
@runner = default_runner
85
@collector = default_collector
90
yield(self) if block_given?
93
def process_args(args = ARGV)
95
options.order!(args) {|arg| @to_run << arg}
96
rescue OptionParser::ParseError => e
102
@filters << proc{false} unless(@filters.empty?)
108
@options ||= OptionParser.new do |o|
109
o.banner = "Test::Unit automatic runner."
110
o.banner << "\nUsage: #{$0} [options] [-- untouched arguments]"
113
o.on('-r', '--runner=RUNNER', RUNNERS,
114
"Use the given RUNNER.",
115
"(" + keyword_display(RUNNERS) + ")") do |r|
120
o.on('-b', '--basedir=DIR', "Base directory of test suites.") do |b|
124
o.on('-w', '--workdir=DIR', "Working directory to run tests.") do |w|
128
o.on('-a', '--add=TORUN', Array,
129
"Add TORUN to the list of things to run;",
130
"can be a file or a directory.") do |a|
135
o.on('-p', '--pattern=PATTERN', Regexp,
136
"Match files to collect against PATTERN.") do |e|
141
o.on('-x', '--exclude=PATTERN', Regexp,
142
"Ignore files to collect against PATTERN.") do |e|
147
o.on('-n', '--name=NAME', String,
148
"Runs tests matching NAME.",
149
"(patterns may be used).") do |n|
150
n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n)
153
@filters << proc{|t| n =~ t.method_name ? true : nil}
155
@filters << proc{|t| n == t.method_name ? true : nil}
159
o.on('-t', '--testcase=TESTCASE', String,
160
"Runs tests in TestCases matching TESTCASE.",
161
"(patterns may be used).") do |n|
162
n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n)
165
@filters << proc{|t| n =~ t.class.name ? true : nil}
167
@filters << proc{|t| n == t.class.name ? true : nil}
171
priority_filter = Proc.new do |test|
175
Priority::Checker.new(test).need_to_run? or nil
178
o.on("--[no-]priority-mode",
179
"Runs some tests based on their priority.") do |priority_mode|
181
@filters |= [priority_filter]
183
@filters -= [priority_filter]
187
o.on('-I', "--load-path=DIR[#{File::PATH_SEPARATOR}DIR...]",
188
"Appends directory list to $LOAD_PATH.") do |dirs|
189
$LOAD_PATH.concat(dirs.split(File::PATH_SEPARATOR))
192
ADDITIONAL_OPTIONS.each do |option_builder|
193
option_builder.call(self, o)
197
"Stop processing options so that the",
198
"remaining options will be passed to the",
199
"test."){o.terminate}
201
o.on('-h', '--help', 'Display this help.'){puts o; exit}
204
o.on_tail('Deprecated options:')
206
o.on_tail('--console', 'Console runner (use --runner).') do
207
warn("Deprecated option (--console).")
208
@runner = RUNNERS[:console]
212
o.on_tail('--fox', 'Fox runner (use --runner).') do
213
warn("Deprecated option (--fox).")
214
@runner = RUNNERS[:fox]
222
def keyword_display(array)
223
list = array.collect {|e, *| e.to_s}
224
Array === array or list.sort!
225
list.collect {|e| e.sub(/^(.)([A-Za-z]+)(?=\w*$)/, '\\1[\\2]')}.join(", ")
229
suite = @collector[self]
230
return false if suite.nil?
231
runner = @runner[self]
232
return false if runner.nil?
233
Dir.chdir(@workdir) if @workdir
234
runner.run(suite, @runner_options).passed?
239
if ENV["EMACS"] == "t"
246
def default_collector
247
COLLECTORS[@standalone ? :load : :descendant]
253
require 'test/unit/runner/console'
254
require 'test/unit/runner/emacs'