test-unit 1.2.3 → 2.0.0
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.
- data/History.txt +27 -0
- data/Manifest.txt +30 -8
- data/README.txt +9 -4
- data/Rakefile +16 -1
- data/bin/testrb +0 -0
- data/lib/test/unit/assertions.rb +148 -48
- data/lib/test/unit/attribute.rb +125 -0
- data/lib/test/unit/autorunner.rb +101 -71
- data/lib/test/unit/collector/descendant.rb +23 -0
- data/lib/test/unit/collector/dir.rb +1 -1
- data/lib/test/unit/collector/load.rb +135 -0
- data/lib/test/unit/color.rb +61 -0
- data/lib/test/unit/diff.rb +524 -0
- data/lib/test/unit/error.rb +70 -2
- data/lib/test/unit/exceptionhandler.rb +39 -0
- data/lib/test/unit/failure.rb +63 -4
- data/lib/test/unit/fixture.rb +185 -0
- data/lib/test/unit/notification.rb +125 -0
- data/lib/test/unit/omission.rb +143 -0
- data/lib/test/unit/pending.rb +146 -0
- data/lib/test/unit/priority.rb +146 -0
- data/lib/test/unit/runner/console.rb +46 -0
- data/lib/test/unit/runner/emacs.rb +8 -0
- data/lib/test/unit/testcase.rb +193 -76
- data/lib/test/unit/testresult.rb +37 -28
- data/lib/test/unit/testsuite.rb +35 -1
- data/lib/test/unit/ui/console/outputlevel.rb +14 -0
- data/lib/test/unit/ui/console/testrunner.rb +96 -28
- data/lib/test/unit/ui/emacs/testrunner.rb +49 -0
- data/lib/test/unit/ui/testrunner.rb +20 -0
- data/lib/test/unit/ui/testrunnermediator.rb +28 -19
- data/lib/test/unit/ui/testrunnerutilities.rb +2 -7
- data/lib/test/unit/util/backtracefilter.rb +2 -1
- data/lib/test/unit/version.rb +1 -1
- data/test/collector/test_descendant.rb +135 -0
- data/test/collector/test_load.rb +333 -0
- data/test/run-test.rb +13 -0
- data/test/test_assertions.rb +221 -56
- data/test/test_attribute.rb +86 -0
- data/test/test_color.rb +37 -0
- data/test/test_diff.rb +477 -0
- data/test/test_emacs_runner.rb +60 -0
- data/test/test_fixture.rb +275 -0
- data/test/test_notification.rb +33 -0
- data/test/test_omission.rb +81 -0
- data/test/test_pending.rb +70 -0
- data/test/test_priority.rb +89 -0
- data/test/test_testcase.rb +160 -5
- data/test/test_testresult.rb +61 -52
- data/test/testunit_test_util.rb +14 -0
- data/test/ui/test_testrunmediator.rb +20 -0
- metadata +53 -23
- data/lib/test/unit/ui/fox/testrunner.rb +0 -268
- data/lib/test/unit/ui/gtk/testrunner.rb +0 -416
- data/lib/test/unit/ui/gtk2/testrunner.rb +0 -465
- data/lib/test/unit/ui/tk/testrunner.rb +0 -260
- data/test/runit/test_assert.rb +0 -402
- data/test/runit/test_testcase.rb +0 -91
- data/test/runit/test_testresult.rb +0 -144
- data/test/runit/test_testsuite.rb +0 -49
data/lib/test/unit/autorunner.rb
CHANGED
@@ -1,10 +1,27 @@
|
|
1
1
|
require 'test/unit'
|
2
|
-
require 'test/unit/ui/testrunnerutilities'
|
3
2
|
require 'optparse'
|
4
3
|
|
5
4
|
module Test
|
6
5
|
module Unit
|
7
6
|
class AutoRunner
|
7
|
+
RUNNERS = {}
|
8
|
+
COLLECTORS = {}
|
9
|
+
ADDITIONAL_OPTIONS = []
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def register_runner(id, runner_builder=Proc.new)
|
13
|
+
RUNNERS[id] = runner_builder
|
14
|
+
end
|
15
|
+
|
16
|
+
def register_collector(id, collector_builder=Proc.new)
|
17
|
+
COLLECTORS[id] = collector_builder
|
18
|
+
end
|
19
|
+
|
20
|
+
def setup_option(option_builder=Proc.new)
|
21
|
+
ADDITIONAL_OPTIONS << option_builder
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
8
25
|
def self.run(force_standalone=false, default_dir=nil, argv=ARGV, &block)
|
9
26
|
r = new(force_standalone || standalone?, &block)
|
10
27
|
r.base = default_dir
|
@@ -20,69 +37,57 @@ module Test
|
|
20
37
|
true
|
21
38
|
end
|
22
39
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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
|
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/, ''))
|
45
|
+
end
|
46
|
+
|
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)
|
55
|
+
end
|
56
|
+
|
57
|
+
# deprecated
|
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/, ''))
|
63
|
+
end
|
64
|
+
|
65
|
+
# deprecated
|
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))
|
75
|
+
end
|
76
|
+
|
77
|
+
attr_reader :suite, :runner_options
|
78
|
+
attr_accessor :filters, :to_run, :pattern, :exclude, :base, :workdir
|
74
79
|
attr_writer :runner, :collector
|
75
80
|
|
76
81
|
def initialize(standalone)
|
77
82
|
Unit.run = true
|
78
83
|
@standalone = standalone
|
79
|
-
@runner =
|
80
|
-
@collector =
|
84
|
+
@runner = default_runner
|
85
|
+
@collector = default_collector
|
81
86
|
@filters = []
|
82
87
|
@to_run = []
|
83
|
-
@
|
88
|
+
@runner_options = {}
|
84
89
|
@workdir = nil
|
85
|
-
yield(self) if
|
90
|
+
yield(self) if block_given?
|
86
91
|
end
|
87
92
|
|
88
93
|
def process_args(args = ARGV)
|
@@ -163,15 +168,25 @@ module Test
|
|
163
168
|
end
|
164
169
|
end
|
165
170
|
|
171
|
+
priority_filter = Proc.new do |test|
|
172
|
+
Priority::Checker.new(test).need_to_run? or nil
|
173
|
+
end
|
174
|
+
o.on("--[no-]priority-mode",
|
175
|
+
"Runs some tests based on their priority.") do |priority_mode|
|
176
|
+
if priority_mode
|
177
|
+
@filters |= [priority_filter]
|
178
|
+
else
|
179
|
+
@filters -= [priority_filter]
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
166
183
|
o.on('-I', "--load-path=DIR[#{File::PATH_SEPARATOR}DIR...]",
|
167
184
|
"Appends directory list to $LOAD_PATH.") do |dirs|
|
168
185
|
$LOAD_PATH.concat(dirs.split(File::PATH_SEPARATOR))
|
169
186
|
end
|
170
187
|
|
171
|
-
|
172
|
-
|
173
|
-
"(" + keyword_display(OUTPUT_LEVELS) + ")") do |l|
|
174
|
-
@output_level = l || UI::VERBOSE
|
188
|
+
ADDITIONAL_OPTIONS.each do |option_builder|
|
189
|
+
option_builder.call(self, o)
|
175
190
|
end
|
176
191
|
|
177
192
|
o.on('--',
|
@@ -189,14 +204,11 @@ module Test
|
|
189
204
|
@runner = RUNNERS[:console]
|
190
205
|
end
|
191
206
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
o.on_tail('--fox', 'Fox runner (use --runner).') do
|
198
|
-
warn("Deprecated option (--fox).")
|
199
|
-
@runner = RUNNERS[:fox]
|
207
|
+
if RUNNERS[:fox]
|
208
|
+
o.on_tail('--fox', 'Fox runner (use --runner).') do
|
209
|
+
warn("Deprecated option (--fox).")
|
210
|
+
@runner = RUNNERS[:fox]
|
211
|
+
end
|
200
212
|
end
|
201
213
|
|
202
214
|
o.on_tail
|
@@ -210,11 +222,29 @@ module Test
|
|
210
222
|
end
|
211
223
|
|
212
224
|
def run
|
213
|
-
|
214
|
-
|
225
|
+
suite = @collector[self]
|
226
|
+
return false if suite.nil?
|
227
|
+
runner = @runner[self]
|
228
|
+
return false if runner.nil?
|
215
229
|
Dir.chdir(@workdir) if @workdir
|
216
|
-
|
230
|
+
runner.run(suite, @runner_options).passed?
|
231
|
+
end
|
232
|
+
|
233
|
+
private
|
234
|
+
def default_runner
|
235
|
+
if ENV["EMACS"] == "t"
|
236
|
+
RUNNERS[:emacs]
|
237
|
+
else
|
238
|
+
RUNNERS[:console]
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def default_collector
|
243
|
+
COLLECTORS[@standalone ? :load : :descendant]
|
217
244
|
end
|
218
245
|
end
|
219
246
|
end
|
220
247
|
end
|
248
|
+
|
249
|
+
require 'test/unit/runner/console'
|
250
|
+
require 'test/unit/runner/emacs'
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'test/unit/collector'
|
2
|
+
|
3
|
+
module Test
|
4
|
+
module Unit
|
5
|
+
module Collector
|
6
|
+
class Descendant
|
7
|
+
include Collector
|
8
|
+
|
9
|
+
NAME = 'collected from the subclasses of TestCase'
|
10
|
+
|
11
|
+
def collect(name=NAME)
|
12
|
+
suite = TestSuite.new(name)
|
13
|
+
sub_suites = []
|
14
|
+
TestCase::DESCENDANTS.each do |descendant_test_case|
|
15
|
+
add_suite(sub_suites, descendant_test_case.suite)
|
16
|
+
end
|
17
|
+
sort(sub_suites).each {|s| suite << s}
|
18
|
+
suite
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -60,7 +60,7 @@ module Test
|
|
60
60
|
next if(e == '.' || e == '..')
|
61
61
|
e_name = dir_name ? @file.join(dir_name, e) : e
|
62
62
|
if @file.directory?(realdir(e_name))
|
63
|
-
next if /\
|
63
|
+
next if /\A(?:CVS|\.svn)\z/ =~ e
|
64
64
|
sub_suite = recursive_collect(e_name, already_gathered)
|
65
65
|
sub_suites << sub_suite unless(sub_suite.empty?)
|
66
66
|
else
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
require 'test/unit/testsuite'
|
4
|
+
require 'test/unit/collector'
|
5
|
+
|
6
|
+
module Test
|
7
|
+
module Unit
|
8
|
+
module Collector
|
9
|
+
class Load
|
10
|
+
include Collector
|
11
|
+
|
12
|
+
attr_reader :patterns, :excludes, :base
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
super
|
16
|
+
@system_excludes = [/~\z/, /\A\.\#/]
|
17
|
+
@system_directory_excludes = [/\A(?:CVS|\.svn)\z/]
|
18
|
+
@patterns = [/\Atest_.+\.rb\z/m]
|
19
|
+
@excludes = []
|
20
|
+
@base = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def base=(base)
|
24
|
+
base = Pathname(base) unless base.nil?
|
25
|
+
@base = base
|
26
|
+
end
|
27
|
+
|
28
|
+
def collect(*froms)
|
29
|
+
add_load_path(@base) do
|
30
|
+
froms = ["."] if froms.empty?
|
31
|
+
test_suites = froms.collect do |from|
|
32
|
+
test_suite = collect_recursive(from, find_test_cases)
|
33
|
+
test_suite = nil if test_suite.tests.empty?
|
34
|
+
test_suite
|
35
|
+
end.compact
|
36
|
+
|
37
|
+
if test_suites.size > 1
|
38
|
+
test_suite = TestSuite.new("[#{froms.join(', ')}]")
|
39
|
+
sort(test_suites).each do |sub_test_suite|
|
40
|
+
test_suite << sub_test_suite
|
41
|
+
end
|
42
|
+
test_suite
|
43
|
+
else
|
44
|
+
test_suites.first
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def find_test_cases(ignore=[])
|
50
|
+
test_cases = []
|
51
|
+
TestCase::DESCENDANTS.each do |test_case|
|
52
|
+
test_cases << test_case unless ignore.include?(test_case)
|
53
|
+
end
|
54
|
+
ignore.concat(test_cases)
|
55
|
+
test_cases
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
def collect_recursive(name, already_gathered)
|
60
|
+
sub_test_suites = []
|
61
|
+
|
62
|
+
path = resolve_path(name)
|
63
|
+
if path.directory?
|
64
|
+
directories, files = path.children.partition do |child|
|
65
|
+
child.directory?
|
66
|
+
end
|
67
|
+
|
68
|
+
files.each do |child|
|
69
|
+
next if excluded_file?(child.basename.to_s)
|
70
|
+
collect_file(child, sub_test_suites, already_gathered)
|
71
|
+
end
|
72
|
+
|
73
|
+
directories.each do |child|
|
74
|
+
next if excluded_directory?(child.basename.to_s)
|
75
|
+
sub_test_suite = collect_recursive(child, already_gathered)
|
76
|
+
sub_test_suites << sub_test_suite unless sub_test_suite.empty?
|
77
|
+
end
|
78
|
+
else
|
79
|
+
collect_file(path, sub_test_suites, already_gathered)
|
80
|
+
end
|
81
|
+
|
82
|
+
test_suite = TestSuite.new(path.basename.to_s)
|
83
|
+
sort(sub_test_suites).each do |sub_test_suite|
|
84
|
+
test_suite << sub_test_suite
|
85
|
+
end
|
86
|
+
test_suite
|
87
|
+
end
|
88
|
+
|
89
|
+
def collect_file(path, test_suites, already_gathered)
|
90
|
+
add_load_path(path.expand_path.dirname) do
|
91
|
+
require(path.to_s)
|
92
|
+
find_test_cases(already_gathered).each do |test_case|
|
93
|
+
add_suite(test_suites, test_case.suite)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def resolve_path(path)
|
99
|
+
if @base
|
100
|
+
@base + path
|
101
|
+
else
|
102
|
+
Pathname(path)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def add_load_path(path)
|
107
|
+
$LOAD_PATH.push(path.to_s) if path
|
108
|
+
yield
|
109
|
+
ensure
|
110
|
+
$LOAD_PATH.delete_at($LOAD_PATH.rindex(path.to_s)) if path
|
111
|
+
end
|
112
|
+
|
113
|
+
def excluded_directory?(base)
|
114
|
+
@system_directory_excludes.any? {|pattern| pattern =~ base}
|
115
|
+
end
|
116
|
+
|
117
|
+
def excluded_file?(base)
|
118
|
+
return true if @system_excludes.any? {|pattern| pattern =~ base}
|
119
|
+
|
120
|
+
patterns = @patterns || []
|
121
|
+
unless patterns.empty?
|
122
|
+
return true unless patterns.any? {|pattern| pattern =~ base}
|
123
|
+
end
|
124
|
+
|
125
|
+
excludes = @excludes || []
|
126
|
+
unless excludes.empty?
|
127
|
+
return true if excludes.any? {|pattern| pattern =~ base}
|
128
|
+
end
|
129
|
+
|
130
|
+
false
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Test
|
2
|
+
module Unit
|
3
|
+
class Color
|
4
|
+
NAMES = ["black", "red", "green", "yellow",
|
5
|
+
"blue", "magenta", "cyan", "white"]
|
6
|
+
def initialize(name, options={})
|
7
|
+
@name = name
|
8
|
+
@foreground = options[:foreground]
|
9
|
+
@foreground = true if @foreground.nil?
|
10
|
+
@intensity = options[:intensity]
|
11
|
+
@bold = options[:bold]
|
12
|
+
@italic = options[:italic]
|
13
|
+
@underline = options[:underline]
|
14
|
+
end
|
15
|
+
|
16
|
+
def sequence
|
17
|
+
sequence = []
|
18
|
+
if @name == "none"
|
19
|
+
elsif @name == "reset"
|
20
|
+
sequence << "0"
|
21
|
+
else
|
22
|
+
foreground_parameter = @foreground ? 3 : 4
|
23
|
+
foreground_parameter += 6 if @intensity
|
24
|
+
sequence << "#{foreground_parameter}#{NAMES.index(@name)}"
|
25
|
+
end
|
26
|
+
sequence << "1" if @bold
|
27
|
+
sequence << "3" if @italic
|
28
|
+
sequence << "4" if @underline
|
29
|
+
sequence
|
30
|
+
end
|
31
|
+
|
32
|
+
def escape_sequence
|
33
|
+
"\e[#{sequence.join(';')}m"
|
34
|
+
end
|
35
|
+
|
36
|
+
def +(other)
|
37
|
+
MixColor.new([self, other])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class MixColor
|
42
|
+
def initialize(colors)
|
43
|
+
@colors = colors
|
44
|
+
end
|
45
|
+
|
46
|
+
def sequence
|
47
|
+
@colors.inject([]) do |result, color|
|
48
|
+
result + color.sequence
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def escape_sequence
|
53
|
+
"\e[#{sequence.join(';')}m"
|
54
|
+
end
|
55
|
+
|
56
|
+
def +(other)
|
57
|
+
self.class.new([self, other])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|