test-unit 1.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/History.txt +5 -0
  2. data/Manifest.txt +48 -0
  3. data/README.txt +27 -0
  4. data/Rakefile +15 -0
  5. data/bin/testrb +5 -0
  6. data/lib/test/unit.rb +280 -0
  7. data/lib/test/unit/assertionfailederror.rb +14 -0
  8. data/lib/test/unit/assertions.rb +622 -0
  9. data/lib/test/unit/autorunner.rb +220 -0
  10. data/lib/test/unit/collector.rb +43 -0
  11. data/lib/test/unit/collector/dir.rb +108 -0
  12. data/lib/test/unit/collector/objectspace.rb +34 -0
  13. data/lib/test/unit/error.rb +56 -0
  14. data/lib/test/unit/failure.rb +51 -0
  15. data/lib/test/unit/testcase.rb +160 -0
  16. data/lib/test/unit/testresult.rb +80 -0
  17. data/lib/test/unit/testsuite.rb +76 -0
  18. data/lib/test/unit/ui/console/testrunner.rb +127 -0
  19. data/lib/test/unit/ui/fox/testrunner.rb +268 -0
  20. data/lib/test/unit/ui/gtk/testrunner.rb +416 -0
  21. data/lib/test/unit/ui/gtk2/testrunner.rb +465 -0
  22. data/lib/test/unit/ui/testrunnermediator.rb +68 -0
  23. data/lib/test/unit/ui/testrunnerutilities.rb +46 -0
  24. data/lib/test/unit/ui/tk/testrunner.rb +260 -0
  25. data/lib/test/unit/util/backtracefilter.rb +40 -0
  26. data/lib/test/unit/util/observable.rb +90 -0
  27. data/lib/test/unit/util/procwrapper.rb +48 -0
  28. data/lib/test/unit/version.rb +7 -0
  29. data/sample/adder.rb +13 -0
  30. data/sample/subtracter.rb +12 -0
  31. data/sample/tc_adder.rb +18 -0
  32. data/sample/tc_subtracter.rb +18 -0
  33. data/sample/ts_examples.rb +7 -0
  34. data/test/collector/test_dir.rb +406 -0
  35. data/test/collector/test_objectspace.rb +98 -0
  36. data/test/runit/test_assert.rb +402 -0
  37. data/test/runit/test_testcase.rb +91 -0
  38. data/test/runit/test_testresult.rb +144 -0
  39. data/test/runit/test_testsuite.rb +49 -0
  40. data/test/test_assertions.rb +528 -0
  41. data/test/test_error.rb +26 -0
  42. data/test/test_failure.rb +33 -0
  43. data/test/test_testcase.rb +275 -0
  44. data/test/test_testresult.rb +104 -0
  45. data/test/test_testsuite.rb +129 -0
  46. data/test/util/test_backtracefilter.rb +41 -0
  47. data/test/util/test_observable.rb +102 -0
  48. data/test/util/test_procwrapper.rb +36 -0
  49. metadata +128 -0
@@ -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,108 @@
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
+ @base = nil
22
+ end
23
+
24
+ def collect(*from)
25
+ basedir = @base
26
+ $:.push(basedir) if basedir
27
+ if(from.empty?)
28
+ recursive_collect('.', find_test_cases)
29
+ elsif(from.size == 1)
30
+ recursive_collect(from.first, find_test_cases)
31
+ else
32
+ suites = []
33
+ from.each do |f|
34
+ suite = recursive_collect(f, find_test_cases)
35
+ suites << suite unless(suite.tests.empty?)
36
+ end
37
+ suite = TestSuite.new("[#{from.join(', ')}]")
38
+ sort(suites).each{|s| suite << s}
39
+ suite
40
+ end
41
+ ensure
42
+ $:.delete_at($:.rindex(basedir)) if basedir
43
+ end
44
+
45
+ def find_test_cases(ignore=[])
46
+ cases = []
47
+ @object_space.each_object(Class) do |c|
48
+ cases << c if(c < TestCase && !ignore.include?(c))
49
+ end
50
+ ignore.concat(cases)
51
+ cases
52
+ end
53
+
54
+ def recursive_collect(name, already_gathered)
55
+ sub_suites = []
56
+ path = realdir(name)
57
+ if @file.directory?(path)
58
+ dir_name = name unless name == '.'
59
+ @dir.entries(path).each do |e|
60
+ next if(e == '.' || e == '..')
61
+ e_name = dir_name ? @file.join(dir_name, e) : e
62
+ if @file.directory?(realdir(e_name))
63
+ next if /\ACVS\z/ =~ e
64
+ sub_suite = recursive_collect(e_name, already_gathered)
65
+ sub_suites << sub_suite unless(sub_suite.empty?)
66
+ else
67
+ next if /~\z/ =~ e_name or /\A\.\#/ =~ e
68
+ if @pattern and !@pattern.empty?
69
+ next unless @pattern.any? {|pat| pat =~ e_name}
70
+ end
71
+ if @exclude and !@exclude.empty?
72
+ next if @exclude.any? {|pat| pat =~ e_name}
73
+ end
74
+ collect_file(e_name, sub_suites, already_gathered)
75
+ end
76
+ end
77
+ else
78
+ collect_file(name, sub_suites, already_gathered)
79
+ end
80
+ suite = TestSuite.new(@file.basename(name))
81
+ sort(sub_suites).each{|s| suite << s}
82
+ suite
83
+ end
84
+
85
+ def collect_file(name, suites, already_gathered)
86
+ dir = @file.dirname(@file.expand_path(name, @base))
87
+ $:.unshift(dir)
88
+ if(@req)
89
+ @req.require(name)
90
+ else
91
+ require(name)
92
+ end
93
+ find_test_cases(already_gathered).each{|t| add_suite(suites, t.suite)}
94
+ ensure
95
+ $:.delete_at($:.rindex(dir)) if(dir)
96
+ end
97
+
98
+ def realdir(path)
99
+ if @base
100
+ @file.join(@base, path)
101
+ else
102
+ path
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
108
+ 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