rubysl-test-unit 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,220 @@
1
+ require 'test/unit'
2
+ require 'test/unit/ui/testrunnerutilities'
3
+ require 'optparse'
4
+
5
+ module Test
6
+ module Unit
7
+ class AutoRunner
8
+ def self.run(force_standalone=false, default_dir=nil, argv=ARGV, &block)
9
+ r = new(force_standalone || standalone?, &block)
10
+ r.base = default_dir
11
+ r.process_args(argv)
12
+ r.run
13
+ end
14
+
15
+ def self.standalone?
16
+ return false unless("-e" == $0)
17
+ ObjectSpace.each_object(Class) do |klass|
18
+ return false if(klass < TestCase)
19
+ end
20
+ true
21
+ end
22
+
23
+ RUNNERS = {
24
+ :console => proc do |r|
25
+ require 'test/unit/ui/console/testrunner'
26
+ Test::Unit::UI::Console::TestRunner
27
+ end,
28
+ :gtk => proc do |r|
29
+ require 'test/unit/ui/gtk/testrunner'
30
+ Test::Unit::UI::GTK::TestRunner
31
+ end,
32
+ :gtk2 => proc do |r|
33
+ require 'test/unit/ui/gtk2/testrunner'
34
+ Test::Unit::UI::GTK2::TestRunner
35
+ end,
36
+ :fox => proc do |r|
37
+ require 'test/unit/ui/fox/testrunner'
38
+ Test::Unit::UI::Fox::TestRunner
39
+ end,
40
+ :tk => proc do |r|
41
+ require 'test/unit/ui/tk/testrunner'
42
+ Test::Unit::UI::Tk::TestRunner
43
+ end,
44
+ }
45
+
46
+ OUTPUT_LEVELS = [
47
+ [:silent, UI::SILENT],
48
+ [:progress, UI::PROGRESS_ONLY],
49
+ [:normal, UI::NORMAL],
50
+ [:verbose, UI::VERBOSE],
51
+ ]
52
+
53
+ COLLECTORS = {
54
+ :objectspace => proc do |r|
55
+ require 'test/unit/collector/objectspace'
56
+ c = Collector::ObjectSpace.new
57
+ c.filter = r.filters
58
+ c.collect($0.sub(/\.rb\Z/, ''))
59
+ end,
60
+ :dir => proc do |r|
61
+ require 'test/unit/collector/dir'
62
+ c = Collector::Dir.new
63
+ c.filter = r.filters
64
+ c.pattern.concat(r.pattern) if(r.pattern)
65
+ c.exclude.concat(r.exclude) if(r.exclude)
66
+ c.base = r.base
67
+ $:.push(r.base) if r.base
68
+ c.collect(*(r.to_run.empty? ? ['.'] : r.to_run))
69
+ end,
70
+ }
71
+
72
+ attr_reader :suite
73
+ attr_accessor :output_level, :filters, :to_run, :pattern, :exclude, :base, :workdir
74
+ attr_writer :runner, :collector
75
+
76
+ def initialize(standalone)
77
+ Unit.run = true
78
+ @standalone = standalone
79
+ @runner = RUNNERS[:console]
80
+ @collector = COLLECTORS[(standalone ? :dir : :objectspace)]
81
+ @filters = []
82
+ @to_run = []
83
+ @output_level = UI::NORMAL
84
+ @workdir = nil
85
+ yield(self) if(block_given?)
86
+ end
87
+
88
+ def process_args(args = ARGV)
89
+ begin
90
+ options.order!(args) {|arg| @to_run << arg}
91
+ rescue OptionParser::ParseError => e
92
+ puts e
93
+ puts options
94
+ $! = nil
95
+ abort
96
+ else
97
+ @filters << proc{false} unless(@filters.empty?)
98
+ end
99
+ not @to_run.empty?
100
+ end
101
+
102
+ def options
103
+ @options ||= OptionParser.new do |o|
104
+ o.banner = "Test::Unit automatic runner."
105
+ o.banner << "\nUsage: #{$0} [options] [-- untouched arguments]"
106
+
107
+ o.on
108
+ o.on('-r', '--runner=RUNNER', RUNNERS,
109
+ "Use the given RUNNER.",
110
+ "(" + keyword_display(RUNNERS) + ")") do |r|
111
+ @runner = r
112
+ end
113
+
114
+ if(@standalone)
115
+ o.on('-b', '--basedir=DIR', "Base directory of test suites.") do |b|
116
+ @base = b
117
+ end
118
+
119
+ o.on('-w', '--workdir=DIR', "Working directory to run tests.") do |w|
120
+ @workdir = w
121
+ end
122
+
123
+ o.on('-a', '--add=TORUN', Array,
124
+ "Add TORUN to the list of things to run;",
125
+ "can be a file or a directory.") do |a|
126
+ @to_run.concat(a)
127
+ end
128
+
129
+ @pattern = []
130
+ o.on('-p', '--pattern=PATTERN', Regexp,
131
+ "Match files to collect against PATTERN.") do |e|
132
+ @pattern << e
133
+ end
134
+
135
+ @exclude = []
136
+ o.on('-x', '--exclude=PATTERN', Regexp,
137
+ "Ignore files to collect against PATTERN.") do |e|
138
+ @exclude << e
139
+ end
140
+ end
141
+
142
+ o.on('-n', '--name=NAME', String,
143
+ "Runs tests matching NAME.",
144
+ "(patterns may be used).") do |n|
145
+ n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n)
146
+ case n
147
+ when Regexp
148
+ @filters << proc{|t| n =~ t.method_name ? true : nil}
149
+ else
150
+ @filters << proc{|t| n == t.method_name ? true : nil}
151
+ end
152
+ end
153
+
154
+ o.on('-t', '--testcase=TESTCASE', String,
155
+ "Runs tests in TestCases matching TESTCASE.",
156
+ "(patterns may be used).") do |n|
157
+ n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n)
158
+ case n
159
+ when Regexp
160
+ @filters << proc{|t| n =~ t.class.name ? true : nil}
161
+ else
162
+ @filters << proc{|t| n == t.class.name ? true : nil}
163
+ end
164
+ end
165
+
166
+ o.on('-I', "--load-path=DIR[#{File::PATH_SEPARATOR}DIR...]",
167
+ "Appends directory list to $LOAD_PATH.") do |dirs|
168
+ $LOAD_PATH.concat(dirs.split(File::PATH_SEPARATOR))
169
+ end
170
+
171
+ o.on('-v', '--verbose=[LEVEL]', OUTPUT_LEVELS,
172
+ "Set the output level (default is verbose).",
173
+ "(" + keyword_display(OUTPUT_LEVELS) + ")") do |l|
174
+ @output_level = l || UI::VERBOSE
175
+ end
176
+
177
+ o.on('--',
178
+ "Stop processing options so that the",
179
+ "remaining options will be passed to the",
180
+ "test."){o.terminate}
181
+
182
+ o.on('-h', '--help', 'Display this help.'){puts o; exit}
183
+
184
+ o.on_tail
185
+ o.on_tail('Deprecated options:')
186
+
187
+ o.on_tail('--console', 'Console runner (use --runner).') do
188
+ warn("Deprecated option (--console).")
189
+ @runner = RUNNERS[:console]
190
+ end
191
+
192
+ o.on_tail('--gtk', 'GTK runner (use --runner).') do
193
+ warn("Deprecated option (--gtk).")
194
+ @runner = RUNNERS[:gtk]
195
+ end
196
+
197
+ o.on_tail('--fox', 'Fox runner (use --runner).') do
198
+ warn("Deprecated option (--fox).")
199
+ @runner = RUNNERS[:fox]
200
+ end
201
+
202
+ o.on_tail
203
+ end
204
+ end
205
+
206
+ def keyword_display(array)
207
+ list = array.collect {|e, *| e.to_s}
208
+ Array === array or list.sort!
209
+ list.collect {|e| e.sub(/^(.)([A-Za-z]+)(?=\w*$)/, '\\1[\\2]')}.join(", ")
210
+ end
211
+
212
+ def run
213
+ @suite = @collector[self]
214
+ result = @runner[self] or return false
215
+ Dir.chdir(@workdir) if @workdir
216
+ result.run(@suite, @output_level).passed?
217
+ end
218
+ end
219
+ end
220
+ end
@@ -0,0 +1,43 @@
1
+ module Test
2
+ module Unit
3
+ module Collector
4
+ def initialize
5
+ @filters = []
6
+ end
7
+
8
+ def filter=(filters)
9
+ @filters = case(filters)
10
+ when Proc
11
+ [filters]
12
+ when Array
13
+ filters
14
+ end
15
+ end
16
+
17
+ def add_suite(destination, suite)
18
+ to_delete = suite.tests.find_all{|t| !include?(t)}
19
+ to_delete.each{|t| suite.delete(t)}
20
+ destination << suite unless(suite.size == 0)
21
+ end
22
+
23
+ def include?(test)
24
+ return true if(@filters.empty?)
25
+ @filters.each do |filter|
26
+ result = filter[test]
27
+ if(result.nil?)
28
+ next
29
+ elsif(!result)
30
+ return false
31
+ else
32
+ return true
33
+ end
34
+ end
35
+ true
36
+ end
37
+
38
+ def sort(suites)
39
+ suites.sort_by{|s| s.name}
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,107 @@
1
+ require 'test/unit/testsuite'
2
+ require 'test/unit/collector'
3
+
4
+ module Test
5
+ module Unit
6
+ module Collector
7
+ class Dir
8
+ include Collector
9
+
10
+ attr_reader :pattern, :exclude
11
+ attr_accessor :base
12
+
13
+ def initialize(dir=::Dir, file=::File, object_space=::ObjectSpace, req=nil)
14
+ super()
15
+ @dir = dir
16
+ @file = file
17
+ @object_space = object_space
18
+ @req = req
19
+ @pattern = [/\btest_.*\.rb\Z/m]
20
+ @exclude = []
21
+ end
22
+
23
+ def collect(*from)
24
+ basedir = @base
25
+ $:.push(basedir) if basedir
26
+ if(from.empty?)
27
+ recursive_collect('.', find_test_cases)
28
+ elsif(from.size == 1)
29
+ recursive_collect(from.first, find_test_cases)
30
+ else
31
+ suites = []
32
+ from.each do |f|
33
+ suite = recursive_collect(f, find_test_cases)
34
+ suites << suite unless(suite.tests.empty?)
35
+ end
36
+ suite = TestSuite.new("[#{from.join(', ')}]")
37
+ sort(suites).each{|s| suite << s}
38
+ suite
39
+ end
40
+ ensure
41
+ $:.delete_at($:.rindex(basedir)) if basedir
42
+ end
43
+
44
+ def find_test_cases(ignore=[])
45
+ cases = []
46
+ @object_space.each_object(Class) do |c|
47
+ cases << c if(c < TestCase && !ignore.include?(c))
48
+ end
49
+ ignore.concat(cases)
50
+ cases
51
+ end
52
+
53
+ def recursive_collect(name, already_gathered)
54
+ sub_suites = []
55
+ path = realdir(name)
56
+ if @file.directory?(path)
57
+ dir_name = name unless name == '.'
58
+ @dir.entries(path).each do |e|
59
+ next if(e == '.' || e == '..')
60
+ e_name = dir_name ? @file.join(dir_name, e) : e
61
+ if @file.directory?(realdir(e_name))
62
+ next if /\ACVS\z/ =~ e
63
+ sub_suite = recursive_collect(e_name, already_gathered)
64
+ sub_suites << sub_suite unless(sub_suite.empty?)
65
+ else
66
+ next if /~\z/ =~ e_name or /\A\.\#/ =~ e
67
+ if @pattern and !@pattern.empty?
68
+ next unless @pattern.any? {|pat| pat =~ e_name}
69
+ end
70
+ if @exclude and !@exclude.empty?
71
+ next if @exclude.any? {|pat| pat =~ e_name}
72
+ end
73
+ collect_file(e_name, sub_suites, already_gathered)
74
+ end
75
+ end
76
+ else
77
+ collect_file(name, sub_suites, already_gathered)
78
+ end
79
+ suite = TestSuite.new(@file.basename(name))
80
+ sort(sub_suites).each{|s| suite << s}
81
+ suite
82
+ end
83
+
84
+ def collect_file(name, suites, already_gathered)
85
+ dir = @file.dirname(@file.expand_path(name, @base))
86
+ $:.unshift(dir)
87
+ if(@req)
88
+ @req.require(name)
89
+ else
90
+ require(name)
91
+ end
92
+ find_test_cases(already_gathered).each{|t| add_suite(suites, t.suite)}
93
+ ensure
94
+ $:.delete_at($:.rindex(dir)) if(dir)
95
+ end
96
+
97
+ def realdir(path)
98
+ if @base
99
+ @file.join(@base, path)
100
+ else
101
+ path
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,34 @@
1
+ # Author:: Nathaniel Talbott.
2
+ # Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
3
+ # License:: Ruby license.
4
+
5
+ require 'test/unit/collector'
6
+
7
+ module Test
8
+ module Unit
9
+ module Collector
10
+ class ObjectSpace
11
+ include Collector
12
+
13
+ NAME = 'collected from the ObjectSpace'
14
+
15
+ def initialize(source=::ObjectSpace)
16
+ super()
17
+ @source = source
18
+ end
19
+
20
+ def collect(name=NAME)
21
+ suite = TestSuite.new(name)
22
+ sub_suites = []
23
+ @source.each_object(Class) do |klass|
24
+ if(Test::Unit::TestCase > klass)
25
+ add_suite(sub_suites, klass.suite)
26
+ end
27
+ end
28
+ sort(sub_suites).each{|s| suite << s}
29
+ suite
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,56 @@
1
+ #--
2
+ #
3
+ # Author:: Nathaniel Talbott.
4
+ # Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
5
+ # License:: Ruby license.
6
+
7
+ require 'test/unit/util/backtracefilter'
8
+
9
+ module Test
10
+ module Unit
11
+
12
+ # Encapsulates an error in a test. Created by
13
+ # Test::Unit::TestCase when it rescues an exception thrown
14
+ # during the processing of a test.
15
+ class Error
16
+ include Util::BacktraceFilter
17
+
18
+ attr_reader(:test_name, :exception)
19
+
20
+ SINGLE_CHARACTER = 'E'
21
+
22
+ # Creates a new Error with the given test_name and
23
+ # exception.
24
+ def initialize(test_name, exception)
25
+ @test_name = test_name
26
+ @exception = exception
27
+ end
28
+
29
+ # Returns a single character representation of an error.
30
+ def single_character_display
31
+ SINGLE_CHARACTER
32
+ end
33
+
34
+ # Returns the message associated with the error.
35
+ def message
36
+ "#{@exception.class.name}: #{@exception.message}"
37
+ end
38
+
39
+ # Returns a brief version of the error description.
40
+ def short_display
41
+ "#@test_name: #{message.split("\n")[0]}"
42
+ end
43
+
44
+ # Returns a verbose version of the error description.
45
+ def long_display
46
+ backtrace = filter_backtrace(@exception.backtrace).join("\n ")
47
+ "Error:\n#@test_name:\n#{message}\n #{backtrace}"
48
+ end
49
+
50
+ # Overridden to return long_display.
51
+ def to_s
52
+ long_display
53
+ end
54
+ end
55
+ end
56
+ end