test-unit 2.0.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +30 -0
- data/Manifest.txt +20 -12
- data/README.txt +28 -12
- data/Rakefile +5 -0
- data/TODO +1 -0
- data/html/classic.html +15 -0
- data/html/index.html +25 -0
- data/html/index.html.ja +27 -0
- data/html/test-unit-classic.png +0 -0
- data/lib/test/unit.rb +62 -0
- data/lib/test/unit/assertions.rb +350 -66
- data/lib/test/unit/autorunner.rb +68 -13
- data/lib/test/unit/collector/load.rb +1 -1
- data/lib/test/unit/color-scheme.rb +85 -0
- data/lib/test/unit/color.rb +40 -5
- data/lib/test/unit/diff.rb +14 -0
- data/lib/test/unit/fixture.rb +2 -2
- data/lib/test/unit/runner/console.rb +8 -2
- data/lib/test/unit/testcase.rb +86 -2
- data/lib/test/unit/ui/console/testrunner.rb +51 -26
- data/lib/test/unit/version.rb +1 -1
- data/sample/test_user.rb +22 -0
- data/test/collector/{test_descendant.rb → test-descendant.rb} +0 -0
- data/test/collector/{test_load.rb → test-load.rb} +1 -1
- data/test/{test_attribute.rb → test-attribute.rb} +0 -0
- data/test/test-color-scheme.rb +55 -0
- data/test/{test_color.rb → test-color.rb} +10 -0
- data/test/{test_diff.rb → test-diff.rb} +0 -0
- data/test/{test_emacs_runner.rb → test-emacs-runner.rb} +0 -0
- data/test/test-fixture.rb +287 -0
- data/test/{test_notification.rb → test-notification.rb} +4 -4
- data/test/{test_omission.rb → test-omission.rb} +6 -6
- data/test/{test_pending.rb → test-pending.rb} +6 -6
- data/test/{test_priority.rb → test-priority.rb} +0 -0
- data/test/test_assertions.rb +366 -63
- data/test/test_testcase.rb +48 -0
- data/test/{testunit_test_util.rb → testunit-test-util.rb} +1 -1
- metadata +27 -29
- data/test/test_fixture.rb +0 -275
data/lib/test/unit/autorunner.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'test/unit'
|
2
|
+
require 'test/unit/color-scheme'
|
2
3
|
require 'optparse'
|
3
4
|
|
4
5
|
module Test
|
@@ -11,10 +12,24 @@ module Test
|
|
11
12
|
class << self
|
12
13
|
def register_runner(id, runner_builder=Proc.new)
|
13
14
|
RUNNERS[id] = runner_builder
|
15
|
+
RUNNERS[id.to_s] = runner_builder
|
16
|
+
end
|
17
|
+
|
18
|
+
def runner(id)
|
19
|
+
RUNNERS[id.to_s]
|
14
20
|
end
|
15
21
|
|
16
22
|
def register_collector(id, collector_builder=Proc.new)
|
17
23
|
COLLECTORS[id] = collector_builder
|
24
|
+
COLLECTORS[id.to_s] = collector_builder
|
25
|
+
end
|
26
|
+
|
27
|
+
def collector(id)
|
28
|
+
COLLECTORS[id.to_s]
|
29
|
+
end
|
30
|
+
|
31
|
+
def register_color_scheme(id, scheme)
|
32
|
+
ColorScheme[id] = scheme
|
18
33
|
end
|
19
34
|
|
20
35
|
def setup_option(option_builder=Proc.new)
|
@@ -76,6 +91,7 @@ module Test
|
|
76
91
|
|
77
92
|
attr_reader :suite, :runner_options
|
78
93
|
attr_accessor :filters, :to_run, :pattern, :exclude, :base, :workdir
|
94
|
+
attr_accessor :color_scheme
|
79
95
|
attr_writer :runner, :collector
|
80
96
|
|
81
97
|
def initialize(standalone)
|
@@ -85,8 +101,11 @@ module Test
|
|
85
101
|
@collector = default_collector
|
86
102
|
@filters = []
|
87
103
|
@to_run = []
|
104
|
+
@color_scheme = ColorScheme.default
|
88
105
|
@runner_options = {}
|
89
106
|
@workdir = nil
|
107
|
+
default_config_file = "test-unit.yml"
|
108
|
+
load_config(default_config_file) if File.exist?(default_config_file)
|
90
109
|
yield(self) if block_given?
|
91
110
|
end
|
92
111
|
|
@@ -96,8 +115,7 @@ module Test
|
|
96
115
|
rescue OptionParser::ParseError => e
|
97
116
|
puts e
|
98
117
|
puts options
|
99
|
-
|
100
|
-
abort
|
118
|
+
exit(false)
|
101
119
|
else
|
102
120
|
@filters << proc{false} unless(@filters.empty?)
|
103
121
|
end
|
@@ -116,7 +134,7 @@ module Test
|
|
116
134
|
@runner = r
|
117
135
|
end
|
118
136
|
|
119
|
-
if(@standalone)
|
137
|
+
if (@standalone)
|
120
138
|
o.on('-b', '--basedir=DIR', "Base directory of test suites.") do |b|
|
121
139
|
@base = b
|
122
140
|
end
|
@@ -169,7 +187,11 @@ module Test
|
|
169
187
|
end
|
170
188
|
|
171
189
|
priority_filter = Proc.new do |test|
|
172
|
-
|
190
|
+
if @filters.size > 2
|
191
|
+
nil
|
192
|
+
else
|
193
|
+
Priority::Checker.new(test).need_to_run? or nil
|
194
|
+
end
|
173
195
|
end
|
174
196
|
o.on("--[no-]priority-mode",
|
175
197
|
"Runs some tests based on their priority.") do |priority_mode|
|
@@ -185,6 +207,18 @@ module Test
|
|
185
207
|
$LOAD_PATH.concat(dirs.split(File::PATH_SEPARATOR))
|
186
208
|
end
|
187
209
|
|
210
|
+
color_schemes = ColorScheme.all
|
211
|
+
o.on("--color-scheme=SCHEME", color_schemes,
|
212
|
+
"Use SCHEME as color scheme.",
|
213
|
+
"(#{keyword_display(color_schemes)})") do |scheme|
|
214
|
+
@color_scheme = scheme
|
215
|
+
end
|
216
|
+
|
217
|
+
o.on("--config=FILE",
|
218
|
+
"Use YAML fomat FILE content as configuration file.") do |file|
|
219
|
+
load_config(file)
|
220
|
+
end
|
221
|
+
|
188
222
|
ADDITIONAL_OPTIONS.each do |option_builder|
|
189
223
|
option_builder.call(self, o)
|
190
224
|
end
|
@@ -201,13 +235,13 @@ module Test
|
|
201
235
|
|
202
236
|
o.on_tail('--console', 'Console runner (use --runner).') do
|
203
237
|
warn("Deprecated option (--console).")
|
204
|
-
@runner =
|
238
|
+
@runner = self.class.runner(:console)
|
205
239
|
end
|
206
240
|
|
207
241
|
if RUNNERS[:fox]
|
208
242
|
o.on_tail('--fox', 'Fox runner (use --runner).') do
|
209
243
|
warn("Deprecated option (--fox).")
|
210
|
-
@runner =
|
244
|
+
@runner = self.class.runner(:fox)
|
211
245
|
end
|
212
246
|
end
|
213
247
|
|
@@ -215,10 +249,12 @@ module Test
|
|
215
249
|
end
|
216
250
|
end
|
217
251
|
|
218
|
-
def keyword_display(
|
219
|
-
|
220
|
-
|
221
|
-
|
252
|
+
def keyword_display(keywords)
|
253
|
+
keywords.collect do |keyword, _|
|
254
|
+
keyword.to_s
|
255
|
+
end.uniq.sort.collect do |keyword|
|
256
|
+
keyword.sub(/^(.)([A-Za-z]+)(?=\w*$)/, '\\1[\\2]')
|
257
|
+
end.join(", ")
|
222
258
|
end
|
223
259
|
|
224
260
|
def run
|
@@ -226,21 +262,40 @@ module Test
|
|
226
262
|
return false if suite.nil?
|
227
263
|
runner = @runner[self]
|
228
264
|
return false if runner.nil?
|
265
|
+
@runner_options[:color_scheme] ||= @color_scheme
|
229
266
|
Dir.chdir(@workdir) if @workdir
|
230
267
|
runner.run(suite, @runner_options).passed?
|
231
268
|
end
|
232
269
|
|
270
|
+
def load_config(file)
|
271
|
+
require 'yaml'
|
272
|
+
config = YAML.load(File.read(file))
|
273
|
+
runner_name = config["runner"]
|
274
|
+
@runner = self.class.runner(runner_name) || @runner
|
275
|
+
@collector = self.class.collector(config["collector"]) || @collector
|
276
|
+
(config["color_schemes"] || {}).each do |name, options|
|
277
|
+
ColorScheme[name] = options
|
278
|
+
end
|
279
|
+
runner_options = {}
|
280
|
+
(config["#{runner_name}_options"] || {}).each do |key, value|
|
281
|
+
key = key.to_sym
|
282
|
+
value = ColorScheme[value] if key == :color_scheme
|
283
|
+
runner_options[key.to_sym] = value
|
284
|
+
end
|
285
|
+
@runner_options = @runner_options.merge(runner_options)
|
286
|
+
end
|
287
|
+
|
233
288
|
private
|
234
289
|
def default_runner
|
235
290
|
if ENV["EMACS"] == "t"
|
236
|
-
|
291
|
+
self.class.runner(:emacs)
|
237
292
|
else
|
238
|
-
|
293
|
+
self.class.runner(:console)
|
239
294
|
end
|
240
295
|
end
|
241
296
|
|
242
297
|
def default_collector
|
243
|
-
|
298
|
+
self.class.collector(@standalone ? :load : :descendant)
|
244
299
|
end
|
245
300
|
end
|
246
301
|
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'test/unit/color'
|
2
|
+
|
3
|
+
module Test
|
4
|
+
module Unit
|
5
|
+
class ColorScheme
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
class << self
|
9
|
+
@@default = nil
|
10
|
+
def default
|
11
|
+
@@default ||= new("success" => Color.new("green", :bold => true),
|
12
|
+
"failure" => Color.new("red", :bold => true),
|
13
|
+
"pending" => Color.new("magenta", :bold => true),
|
14
|
+
"omission" => Color.new("blue", :bold => true),
|
15
|
+
"notification" => Color.new("cyan", :bold => true),
|
16
|
+
"error" => Color.new("yellow", :bold => true))
|
17
|
+
end
|
18
|
+
|
19
|
+
@@schemes = {}
|
20
|
+
def all
|
21
|
+
@@schemes.merge("default" => default)
|
22
|
+
end
|
23
|
+
|
24
|
+
def [](id)
|
25
|
+
@@schemes[id.to_s]
|
26
|
+
end
|
27
|
+
|
28
|
+
def []=(id, scheme_or_spec)
|
29
|
+
if scheme_or_spec.is_a?(self)
|
30
|
+
scheme = scheme_or_spec
|
31
|
+
else
|
32
|
+
scheme = new(scheme_or_spec)
|
33
|
+
end
|
34
|
+
@@schemes[id.to_s] = scheme
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def initialize(scheme_spec)
|
39
|
+
@scheme = {}
|
40
|
+
scheme_spec.each do |key, color_spec|
|
41
|
+
self[key] = color_spec
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def [](name)
|
46
|
+
@scheme[name.to_s]
|
47
|
+
end
|
48
|
+
|
49
|
+
def []=(name, color_spec)
|
50
|
+
@scheme[name.to_s] = make_color(color_spec)
|
51
|
+
end
|
52
|
+
|
53
|
+
def each(&block)
|
54
|
+
@scheme.each(&block)
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_hash
|
58
|
+
hash = {}
|
59
|
+
@scheme.each do |key, color|
|
60
|
+
hash[key] = color
|
61
|
+
end
|
62
|
+
hash
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
def make_color(color_spec)
|
67
|
+
if color_spec.is_a?(Color)
|
68
|
+
color_spec
|
69
|
+
else
|
70
|
+
color_name = nil
|
71
|
+
normalized_color_spec = {}
|
72
|
+
color_spec.each do |key, value|
|
73
|
+
key = key.to_sym
|
74
|
+
if key == :name
|
75
|
+
color_name = value
|
76
|
+
else
|
77
|
+
normalized_color_spec[key] = value
|
78
|
+
end
|
79
|
+
end
|
80
|
+
Color.new(color_name, normalized_color_spec)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/lib/test/unit/color.rb
CHANGED
@@ -3,6 +3,8 @@ module Test
|
|
3
3
|
class Color
|
4
4
|
NAMES = ["black", "red", "green", "yellow",
|
5
5
|
"blue", "magenta", "cyan", "white"]
|
6
|
+
|
7
|
+
attr_reader :name
|
6
8
|
def initialize(name, options={})
|
7
9
|
@name = name
|
8
10
|
@foreground = options[:foreground]
|
@@ -13,19 +15,47 @@ module Test
|
|
13
15
|
@underline = options[:underline]
|
14
16
|
end
|
15
17
|
|
18
|
+
def foreground?
|
19
|
+
@foreground
|
20
|
+
end
|
21
|
+
|
22
|
+
def intensity?
|
23
|
+
@intensity
|
24
|
+
end
|
25
|
+
|
26
|
+
def bold?
|
27
|
+
@bold
|
28
|
+
end
|
29
|
+
|
30
|
+
def italic?
|
31
|
+
@italic
|
32
|
+
end
|
33
|
+
|
34
|
+
def underline?
|
35
|
+
@underline
|
36
|
+
end
|
37
|
+
|
38
|
+
def ==(other)
|
39
|
+
self.class === other and
|
40
|
+
[name, foreground?, intensity?,
|
41
|
+
bold?, italic?, underline?] ==
|
42
|
+
[other.name, other.foreground?, other.intensity?,
|
43
|
+
other.bold?, other.italic?, other.underline?]
|
44
|
+
end
|
45
|
+
|
16
46
|
def sequence
|
17
47
|
sequence = []
|
18
48
|
if @name == "none"
|
19
49
|
elsif @name == "reset"
|
20
50
|
sequence << "0"
|
21
51
|
else
|
22
|
-
foreground_parameter =
|
23
|
-
foreground_parameter += 6 if
|
52
|
+
foreground_parameter = foreground? ? 3 : 4
|
53
|
+
foreground_parameter += 6 if intensity?
|
24
54
|
sequence << "#{foreground_parameter}#{NAMES.index(@name)}"
|
25
55
|
end
|
26
|
-
sequence << "1" if
|
27
|
-
sequence << "3" if
|
28
|
-
sequence << "4" if
|
56
|
+
sequence << "1" if bold?
|
57
|
+
sequence << "3" if italic?
|
58
|
+
sequence << "4" if underline?
|
29
59
|
sequence
|
30
60
|
end
|
31
61
|
|
@@ -39,6 +69,7 @@ module Test
|
|
39
69
|
end
|
40
70
|
|
41
71
|
class MixColor
|
72
|
+
attr_reader :colors
|
42
73
|
def initialize(colors)
|
43
74
|
@colors = colors
|
44
75
|
end
|
@@ -56,6 +87,10 @@ module Test
|
|
56
87
|
def +(other)
|
57
88
|
self.class.new([self, other])
|
58
89
|
end
|
90
|
+
|
91
|
+
def ==(other)
|
92
|
+
self.class === other and colors == other.colors
|
93
|
+
end
|
59
94
|
end
|
60
95
|
end
|
61
96
|
end
|
data/lib/test/unit/diff.rb
CHANGED
@@ -507,6 +507,20 @@ module Test
|
|
507
507
|
end
|
508
508
|
|
509
509
|
module_function
|
510
|
+
def need_fold?(diff)
|
511
|
+
/^[-+].{79}/ =~ diff
|
512
|
+
end
|
513
|
+
|
514
|
+
def fold(string)
|
515
|
+
string.split(/\r?\n/).collect do |line|
|
516
|
+
line.gsub(/(.{78})/, "\\1\n")
|
517
|
+
end.join("\n")
|
518
|
+
end
|
519
|
+
|
520
|
+
def folded_readable(from, to, options={})
|
521
|
+
readable(fold(from), fold(to), options)
|
522
|
+
end
|
523
|
+
|
510
524
|
def readable(from, to, options={})
|
511
525
|
diff(ReadableDiffer, from, to, options)
|
512
526
|
end
|
data/lib/test/unit/fixture.rb
CHANGED
@@ -153,10 +153,10 @@ module Test
|
|
153
153
|
unregistered_methods =
|
154
154
|
instance_variable_get(unregistered_methods_variable)
|
155
155
|
end
|
156
|
-
result
|
156
|
+
(result | methods) - unregistered_methods
|
157
157
|
end
|
158
158
|
else
|
159
|
-
|
159
|
+
result
|
160
160
|
end
|
161
161
|
end
|
162
162
|
end
|
@@ -31,8 +31,8 @@ module Test
|
|
31
31
|
["true", true],
|
32
32
|
]
|
33
33
|
opts.on("--[no-]use-color=[auto]", use_color_options,
|
34
|
-
"
|
35
|
-
"(default is auto") do |use_color|
|
34
|
+
"Uses color output",
|
35
|
+
"(default is auto)") do |use_color|
|
36
36
|
case use_color
|
37
37
|
when nil
|
38
38
|
use_color = true
|
@@ -41,6 +41,12 @@ module Test
|
|
41
41
|
end
|
42
42
|
auto_runner.runner_options[:use_color] = use_color
|
43
43
|
end
|
44
|
+
|
45
|
+
opts.on("--progress-row-max=MAX", Integer,
|
46
|
+
"Uses MAX as max terminal width for progress mark",
|
47
|
+
"(default is auto)") do |max|
|
48
|
+
auto_runner.runner_options[:progress_row_max] = max
|
49
|
+
end
|
44
50
|
end
|
45
51
|
end
|
46
52
|
end
|
data/lib/test/unit/testcase.rb
CHANGED
@@ -109,6 +109,79 @@ module Test
|
|
109
109
|
end
|
110
110
|
suite
|
111
111
|
end
|
112
|
+
|
113
|
+
# Called before every test case runs. Can be used
|
114
|
+
# to set up fixture information used in test case
|
115
|
+
# scope.
|
116
|
+
#
|
117
|
+
# Here is an example test case:
|
118
|
+
# class TestMyClass < Test::Unit::TestCase
|
119
|
+
# class << self
|
120
|
+
# def startup
|
121
|
+
# ...
|
122
|
+
# end
|
123
|
+
# end
|
124
|
+
#
|
125
|
+
# def setup
|
126
|
+
# ...
|
127
|
+
# end
|
128
|
+
#
|
129
|
+
# def test_my_class1
|
130
|
+
# ...
|
131
|
+
# end
|
132
|
+
#
|
133
|
+
# def test_my_class2
|
134
|
+
# ...
|
135
|
+
# end
|
136
|
+
# end
|
137
|
+
#
|
138
|
+
# Here is a call order:
|
139
|
+
# * startup
|
140
|
+
# * setup
|
141
|
+
# * test_my_class1 (or test_my_class2)
|
142
|
+
# * setup
|
143
|
+
# * test_my_class2 (or test_my_class1)
|
144
|
+
#
|
145
|
+
# Note that you should not assume test order. Tests
|
146
|
+
# should be worked in any order.
|
147
|
+
def startup
|
148
|
+
end
|
149
|
+
|
150
|
+
# Called after every test case runs. Can be used to tear
|
151
|
+
# down fixture information used in test case scope.
|
152
|
+
#
|
153
|
+
# Here is an example test case:
|
154
|
+
# class TestMyClass < Test::Unit::TestCase
|
155
|
+
# class << self
|
156
|
+
# def shutdown
|
157
|
+
# ...
|
158
|
+
# end
|
159
|
+
# end
|
160
|
+
#
|
161
|
+
# def teardown
|
162
|
+
# ...
|
163
|
+
# end
|
164
|
+
#
|
165
|
+
# def test_my_class1
|
166
|
+
# ...
|
167
|
+
# end
|
168
|
+
#
|
169
|
+
# def test_my_class2
|
170
|
+
# ...
|
171
|
+
# end
|
172
|
+
# end
|
173
|
+
#
|
174
|
+
# Here is a call order:
|
175
|
+
# * test_my_class1 (or test_my_class2)
|
176
|
+
# * teardown
|
177
|
+
# * test_my_class2 (or test_my_class1)
|
178
|
+
# * teardown
|
179
|
+
# * shutdown
|
180
|
+
#
|
181
|
+
# Note that you should not assume test order. Tests
|
182
|
+
# should be worked in any order.
|
183
|
+
def shutdown
|
184
|
+
end
|
112
185
|
end
|
113
186
|
|
114
187
|
attr_reader :method_name
|
@@ -117,7 +190,14 @@ module Test
|
|
117
190
|
# test represented by test_method_name.
|
118
191
|
def initialize(test_method_name)
|
119
192
|
throw :invalid_test unless respond_to?(test_method_name)
|
120
|
-
|
193
|
+
test_method = method(test_method_name)
|
194
|
+
throw :invalid_test if test_method.arity > 0
|
195
|
+
if test_method.respond_to?(:owner)
|
196
|
+
if test_method.owner.class != Module and
|
197
|
+
self.class != test_method.owner
|
198
|
+
throw :invalid_test
|
199
|
+
end
|
200
|
+
end
|
121
201
|
@method_name = test_method_name
|
122
202
|
@test_passed = true
|
123
203
|
@interrupted = false
|
@@ -132,7 +212,7 @@ module Test
|
|
132
212
|
yield(STARTED, name)
|
133
213
|
begin
|
134
214
|
run_setup
|
135
|
-
|
215
|
+
run_test
|
136
216
|
rescue Exception
|
137
217
|
@interrupted = true
|
138
218
|
raise unless handle_exception($!)
|
@@ -251,6 +331,10 @@ module Test
|
|
251
331
|
@_result
|
252
332
|
end
|
253
333
|
|
334
|
+
def run_test
|
335
|
+
__send__(@method_name)
|
336
|
+
end
|
337
|
+
|
254
338
|
def handle_exception(exception)
|
255
339
|
self.class.exception_handlers.each do |handler|
|
256
340
|
return true if send(handler, exception)
|