test-unit 1.2.3

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.
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