rubytest 0.5.4 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.index +15 -3
- data/HISTORY.md +30 -0
- data/README.md +62 -38
- data/bin/ruby-test +7 -2
- data/bin/rubytest +7 -2
- data/lib/rubytest.rb +18 -3
- data/lib/rubytest.yml +65 -0
- data/lib/rubytest/autorun.rb +2 -14
- data/lib/rubytest/cli.rb +86 -87
- data/lib/rubytest/config.rb +381 -46
- data/lib/rubytest/rake.rb +72 -59
- data/lib/rubytest/runner.rb +80 -159
- data/test/basic_case.rb +2 -0
- data/{.ruby → test/helper.rb} +0 -0
- metadata +53 -4
- data/lib/rubytest/rc.rb +0 -8
data/lib/rubytest/rake.rb
CHANGED
@@ -1,17 +1,19 @@
|
|
1
|
+
require 'rubytest'
|
1
2
|
require 'rake/tasklib'
|
2
3
|
|
3
|
-
module
|
4
|
+
module Test
|
4
5
|
|
6
|
+
##
|
7
|
+
# Rake subspace.
|
5
8
|
#
|
6
9
|
module Rake
|
7
10
|
|
8
|
-
|
9
|
-
# Or provide the option for either?
|
10
|
-
|
11
|
+
##
|
11
12
|
# Define a test rake task.
|
12
13
|
#
|
13
14
|
# The `TEST` environment variable can be used to select tests
|
14
|
-
# when using
|
15
|
+
# when using this task. Note, this is just a more convenient
|
16
|
+
# way than using `RUBYTEST_FILES`.
|
15
17
|
#
|
16
18
|
class TestTask < ::Rake::TaskLib
|
17
19
|
|
@@ -23,77 +25,67 @@ module Ruth
|
|
23
25
|
'test/**/*_test.rb'
|
24
26
|
]
|
25
27
|
|
26
|
-
# Test
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
attr_accessor :loadpath
|
31
|
-
|
32
|
-
# Scripts to load prior to loading tests.
|
33
|
-
attr_accessor :requires
|
34
|
-
|
35
|
-
# Report format to use.
|
36
|
-
attr_accessor :format
|
37
|
-
|
38
|
-
# Filter tests based by tags.
|
39
|
-
attr_accessor :tags
|
40
|
-
|
41
|
-
# Filter tests by matching description.
|
42
|
-
attr_accessor :match
|
43
|
-
|
44
|
-
# From Rake's own TestTask.
|
45
|
-
alias_method :libs, :loadpath
|
46
|
-
alias_method :test_files, :tests
|
28
|
+
# Test run configuration.
|
29
|
+
#
|
30
|
+
# @return [Config]
|
31
|
+
attr :config
|
47
32
|
|
33
|
+
# Initialize new Rake::TestTask instance.
|
48
34
|
#
|
49
|
-
def initialize(name='test', desc=
|
50
|
-
@name
|
51
|
-
@desc
|
35
|
+
def initialize(name='test', desc='run tests', &block)
|
36
|
+
@name = name || 'test'
|
37
|
+
@desc = desc
|
38
|
+
|
39
|
+
@config = Test::Config.new
|
52
40
|
|
53
|
-
@
|
54
|
-
@
|
55
|
-
@tests = [ENV['TEST'] || DEFAULT_TESTS].flatten
|
56
|
-
@format = nil
|
57
|
-
@match = nil
|
58
|
-
@tags = []
|
41
|
+
@config.files << default_tests if @config.files.empty?
|
42
|
+
@config.loadpath << 'lib' if @config.loadpath.empty?
|
59
43
|
|
60
|
-
block.call(
|
44
|
+
block.call(@config)
|
61
45
|
|
62
46
|
define_task
|
63
47
|
end
|
64
48
|
|
49
|
+
# Define rake task for testing.
|
65
50
|
#
|
51
|
+
# @return nothing
|
66
52
|
def define_task
|
67
53
|
desc @desc
|
68
54
|
task @name do
|
69
|
-
|
70
|
-
run
|
55
|
+
config.mode == 'shell' ? run_shell : run
|
71
56
|
end
|
72
57
|
end
|
73
58
|
|
59
|
+
# Run tests, via fork is possible, otherwise straight out.
|
74
60
|
#
|
61
|
+
# @return nothing
|
75
62
|
def run
|
76
|
-
fork
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
runner = new(suite, :format=>format, :tags=>tags, :match=>match)
|
63
|
+
if Process.respond_to?(:fork)
|
64
|
+
fork {
|
65
|
+
runner = Test::Runner.new(config)
|
66
|
+
success = runner.run
|
67
|
+
exit -1 unless success
|
68
|
+
}
|
69
|
+
Process.wait
|
70
|
+
else
|
71
|
+
runner = Test::Runner.new(config)
|
86
72
|
success = runner.run
|
87
|
-
|
88
73
|
exit -1 unless success
|
89
|
-
|
90
|
-
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Run test via command line shell.
|
78
|
+
#
|
79
|
+
# @return nothing
|
80
|
+
def shell_run
|
81
|
+
success = ruby(*config.to_shellwords)
|
82
|
+
exit -1 unless success
|
91
83
|
end
|
92
84
|
|
93
85
|
# Resolve test globs.
|
94
|
-
|
95
|
-
#
|
96
|
-
|
86
|
+
#
|
87
|
+
# @todo Implementation probably cna be simplified.
|
88
|
+
# @return [Array<String>] List of test files.
|
97
89
|
def test_files
|
98
90
|
files = tests
|
99
91
|
files = files.map{ |f| Dir[f] }.flatten
|
@@ -103,19 +95,40 @@ module Ruth
|
|
103
95
|
files
|
104
96
|
end
|
105
97
|
|
98
|
+
# Default test globs. For extra convenience will look for list in
|
99
|
+
# `ENV['TEST']` first.
|
106
100
|
#
|
101
|
+
# @return [Array<String>]
|
107
102
|
def default_tests
|
108
|
-
if ENV['
|
109
|
-
ENV['
|
103
|
+
if ENV['TEST']
|
104
|
+
ENV['TEST'].split(/[:;]/)
|
110
105
|
else
|
111
106
|
DEFAULT_TESTS
|
112
107
|
end
|
113
108
|
end
|
114
109
|
|
110
|
+
=begin
|
111
|
+
# Shell out to current ruby command.
|
115
112
|
#
|
116
|
-
#
|
117
|
-
|
118
|
-
|
113
|
+
# @return [Boolean] Success of shell call.
|
114
|
+
def ruby(*argv)
|
115
|
+
system(ruby_command, *argv)
|
116
|
+
end
|
117
|
+
|
118
|
+
# Get current ruby shell command.
|
119
|
+
#
|
120
|
+
# @return [String] Ruby shell command.
|
121
|
+
def ruby_command
|
122
|
+
@ruby_command ||= (
|
123
|
+
require 'rbconfig'
|
124
|
+
ENV['RUBY'] ||
|
125
|
+
File.join(
|
126
|
+
RbConfig::CONFIG['bindir'],
|
127
|
+
RbConfig::CONFIG['ruby_install_name'] + RbConfig::CONFIG['EXEEXT']
|
128
|
+
).sub(/.*\s.*/m, '"\&"')
|
129
|
+
)
|
130
|
+
end
|
131
|
+
=end
|
119
132
|
|
120
133
|
end
|
121
134
|
|
data/lib/rubytest/runner.rb
CHANGED
@@ -1,136 +1,58 @@
|
|
1
1
|
module Test
|
2
2
|
|
3
|
+
# Currently this is an alias for configure, however it is likely
|
4
|
+
# to become an alias for `Runner.run` in the future.
|
5
|
+
#
|
6
|
+
# @deprecated Will probably change behavior in future.
|
7
|
+
def self.run(config=nil, &config_proc)
|
8
|
+
$stderr.puts "configuration profiles no longer supported." if config
|
9
|
+
configure(&config_proc)
|
10
|
+
end
|
11
|
+
|
3
12
|
# The Test::Runner class handles the execution of tests.
|
4
13
|
#
|
5
14
|
class Runner
|
6
15
|
|
7
|
-
#
|
8
|
-
|
16
|
+
# TODO: Wrap run in at_exit ?
|
17
|
+
def self.run(config=nil, &config_proc)
|
18
|
+
runner = Runner.new(config, &config_proc)
|
19
|
+
begin
|
20
|
+
success = runner.run
|
21
|
+
exit -1 unless success
|
22
|
+
rescue => error
|
23
|
+
raise error if $DEBUG
|
24
|
+
$stderr.puts('ERROR: ' + error.to_s)
|
25
|
+
exit -1
|
26
|
+
end
|
27
|
+
end
|
9
28
|
|
10
29
|
# Exceptions that are not caught by test runner.
|
11
30
|
OPEN_ERRORS = [NoMemoryError, SignalException, Interrupt, SystemExit]
|
12
31
|
|
13
|
-
#
|
14
|
-
|
15
|
-
# Default test suite ($TEST_SUITE).
|
16
|
-
def self.suite
|
17
|
-
$TEST_SUITE
|
18
|
-
end
|
19
|
-
|
20
|
-
# Default list of test files to load.
|
21
|
-
def self.files
|
22
|
-
@files ||= []
|
23
|
-
end
|
24
|
-
|
25
|
-
#
|
26
|
-
def self.format
|
27
|
-
@format || DEFAULT_FORMAT
|
28
|
-
end
|
29
|
-
|
30
|
-
#
|
31
|
-
def self.format=(format)
|
32
|
-
@format = format
|
33
|
-
end
|
34
|
-
|
35
|
-
#
|
36
|
-
def self.verbose
|
37
|
-
@verbose
|
38
|
-
end
|
39
|
-
|
40
|
-
#
|
41
|
-
def self.verbose=(boolean)
|
42
|
-
@verbose = !!boolean
|
43
|
-
end
|
44
|
-
|
45
|
-
# Default description match for filtering tests.
|
46
|
-
def self.match
|
47
|
-
@match ||= []
|
48
|
-
end
|
49
|
-
|
50
|
-
# Default selection of tags for filtering tests.
|
51
|
-
def self.tags
|
52
|
-
@tags ||= []
|
53
|
-
end
|
32
|
+
# Handle all configuration via the config instance.
|
33
|
+
attr :config
|
54
34
|
|
55
|
-
#
|
56
|
-
def
|
57
|
-
|
58
|
-
end
|
59
|
-
|
60
|
-
#
|
61
|
-
def self.hard
|
62
|
-
@hard
|
35
|
+
# Test suite to run. This is a list of compliant test units and test cases.
|
36
|
+
def suite
|
37
|
+
config.suite
|
63
38
|
end
|
64
39
|
|
65
40
|
#
|
66
|
-
|
67
|
-
@hard = !!boolean
|
68
|
-
end
|
69
|
-
|
41
|
+
# TODO: Cache or not?
|
70
42
|
#
|
71
|
-
def
|
72
|
-
|
43
|
+
def test_files
|
44
|
+
#@test_files ||= resolve_test_files
|
45
|
+
resolve_test_files
|
73
46
|
end
|
74
47
|
|
75
|
-
#
|
76
|
-
def self.autopath=(boolean)
|
77
|
-
@autopath = !!boolean
|
78
|
-
end
|
79
|
-
|
80
|
-
# / / / A T T R I B U T E S / / /
|
81
|
-
|
82
|
-
# Test suite to run. This is a list of compliant test units and test cases.
|
83
|
-
attr :suite
|
84
|
-
|
85
|
-
# Test files to load.
|
86
|
-
attr :files
|
87
|
-
|
88
48
|
# Reporter format name, or name fragment, used to look up reporter class.
|
89
|
-
|
90
|
-
|
91
|
-
#
|
92
|
-
def format=(name)
|
93
|
-
@format = name.to_s
|
49
|
+
def format
|
50
|
+
config.format
|
94
51
|
end
|
95
52
|
|
96
|
-
# Matching text used to filter which tests are run.
|
97
|
-
attr :match
|
98
|
-
|
99
|
-
# Selected tags used to filter which tests are run.
|
100
|
-
attr :tags
|
101
|
-
|
102
|
-
# List of units with which to filter tests. It is an array of strings
|
103
|
-
# which are matched against module, class and method names.
|
104
|
-
attr :units
|
105
|
-
|
106
53
|
# Show extra details in reports.
|
107
54
|
def verbose?
|
108
|
-
|
109
|
-
end
|
110
|
-
|
111
|
-
#
|
112
|
-
def verbose=(boolean)
|
113
|
-
@verbose = !!boolean
|
114
|
-
end
|
115
|
-
|
116
|
-
# Use "hard" test mode?
|
117
|
-
def hard?
|
118
|
-
@hard
|
119
|
-
end
|
120
|
-
|
121
|
-
#
|
122
|
-
def hard=(boolean)
|
123
|
-
@hard = !!boolean
|
124
|
-
end
|
125
|
-
|
126
|
-
# Automatically assume local loadpaths?
|
127
|
-
def autopath?
|
128
|
-
@autopath
|
129
|
-
end
|
130
|
-
|
131
|
-
#
|
132
|
-
def autopath=(boolean)
|
133
|
-
@autopath = !!boolean
|
55
|
+
config.verbose?
|
134
56
|
end
|
135
57
|
|
136
58
|
# Instance of Advice is a special customizable observer.
|
@@ -158,23 +80,19 @@ module Test
|
|
158
80
|
|
159
81
|
# New Runner.
|
160
82
|
#
|
161
|
-
# @param [
|
162
|
-
#
|
83
|
+
# @param [Config] config
|
84
|
+
# Config instance.
|
163
85
|
#
|
164
|
-
def initialize(
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
@
|
172
|
-
|
173
|
-
@
|
174
|
-
|
175
|
-
@advice = Advice.new
|
176
|
-
|
177
|
-
block.call(self) if block
|
86
|
+
def initialize(config=nil, &block)
|
87
|
+
if config
|
88
|
+
@config = Hash === config ? Config.new(config) : config
|
89
|
+
else
|
90
|
+
@config = Test.configuration
|
91
|
+
end
|
92
|
+
|
93
|
+
block.call(@config) if block
|
94
|
+
|
95
|
+
@advice = Advice.new
|
178
96
|
end
|
179
97
|
|
180
98
|
# The reporter to use for ouput.
|
@@ -193,22 +111,27 @@ module Test
|
|
193
111
|
# That the tests ran without error or failure.
|
194
112
|
#
|
195
113
|
def run
|
196
|
-
|
114
|
+
cd_chdir do
|
115
|
+
Test::Config.load_path_setup if config.autopath?
|
197
116
|
|
198
|
-
|
199
|
-
require file
|
200
|
-
end
|
117
|
+
ignore_callers
|
201
118
|
|
202
|
-
|
203
|
-
|
119
|
+
config.loadpath.each{ |path| $LOAD_PATH.unshift(path) }
|
120
|
+
config.requires.each{ |file| require file }
|
204
121
|
|
205
|
-
|
122
|
+
test_files.each do |test_file|
|
123
|
+
require test_file
|
124
|
+
end
|
125
|
+
|
126
|
+
@reporter = reporter_load(format)
|
127
|
+
@recorder = Recorder.new
|
128
|
+
|
129
|
+
@observers = [advice, @recorder, @reporter]
|
206
130
|
|
207
|
-
#cd_tmp do
|
208
131
|
observers.each{ |o| o.begin_suite(suite) }
|
209
132
|
run_thru(suite)
|
210
133
|
observers.each{ |o| o.end_suite(suite) }
|
211
|
-
|
134
|
+
end
|
212
135
|
|
213
136
|
recorder.success?
|
214
137
|
end
|
@@ -273,7 +196,7 @@ module Test
|
|
273
196
|
observers.each{ |o| o.begin_test(test) }
|
274
197
|
begin
|
275
198
|
success = test.call
|
276
|
-
if hard? && !success # TODO: separate run_test method to speed things up?
|
199
|
+
if config.hard? && !success # TODO: separate run_test method to speed things up?
|
277
200
|
raise Assertion, "failure of #{test}"
|
278
201
|
else
|
279
202
|
observers.each{ |o| o.pass(test) }
|
@@ -312,17 +235,17 @@ module Test
|
|
312
235
|
else
|
313
236
|
cases.each do |tc|
|
314
237
|
next if tc.respond_to?(:skip?) && tc.skip?
|
315
|
-
next if !match.empty? && !match.any?{ |m| m =~ tc.to_s }
|
238
|
+
next if !config.match.empty? && !config.match.any?{ |m| m =~ tc.to_s }
|
316
239
|
|
317
|
-
if !units.empty?
|
240
|
+
if !config.units.empty?
|
318
241
|
next unless tc.respond_to?(:unit)
|
319
|
-
next unless units.find{ |u| tc.unit.start_with?(u) }
|
242
|
+
next unless config.units.find{ |u| tc.unit.start_with?(u) }
|
320
243
|
end
|
321
244
|
|
322
|
-
if !tags.empty?
|
245
|
+
if !config.tags.empty?
|
323
246
|
next unless tc.respond_to?(:tags)
|
324
247
|
tc_tags = [tc.tags].flatten.map{ |t| t.to_s }
|
325
|
-
next if (tags & tc_tags).empty?
|
248
|
+
next if (config.tags & tc_tags).empty?
|
326
249
|
end
|
327
250
|
|
328
251
|
selected << tc
|
@@ -335,7 +258,6 @@ module Test
|
|
335
258
|
#
|
336
259
|
# @return [Reporter::Abstract]
|
337
260
|
# The test reporter instance.
|
338
|
-
#
|
339
261
|
def reporter_load(format)
|
340
262
|
format = DEFAULT_REPORT_FORMAT unless format
|
341
263
|
format = format.to_s.downcase
|
@@ -357,7 +279,6 @@ module Test
|
|
357
279
|
#
|
358
280
|
# @return [Array<String>]
|
359
281
|
# The names of available reporters.
|
360
|
-
#
|
361
282
|
def reporter_list
|
362
283
|
list = Dir[File.dirname(__FILE__) + '/reporters/*.rb']
|
363
284
|
list = list.map{ |r| File.basename(r).chomp('.rb') }
|
@@ -368,8 +289,9 @@ module Test
|
|
368
289
|
# Files can be globs and directories which need to be
|
369
290
|
# resolved to a list of files.
|
370
291
|
#
|
371
|
-
|
372
|
-
|
292
|
+
# @return [Array<String>]
|
293
|
+
def resolve_test_files
|
294
|
+
list = config.files.flatten
|
373
295
|
list = list.map{ |f| Dir[f] }.flatten
|
374
296
|
list = list.map{ |f| File.directory?(f) ? Dir[File.join(f, '**/*.rb')] : f }
|
375
297
|
list = list.flatten.uniq
|
@@ -377,21 +299,20 @@ module Test
|
|
377
299
|
list
|
378
300
|
end
|
379
301
|
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
302
|
+
# Change to directory and run block.
|
303
|
+
#
|
304
|
+
# @raise [Errno::ENOENT] If directory does not exist.
|
305
|
+
def cd_chdir(&block)
|
306
|
+
if dir = config.chdir
|
307
|
+
unless File.directory?(dir)
|
308
|
+
raise Errno::ENOENT, "change directory doesn't exist -- `#{dir}'"
|
309
|
+
end
|
310
|
+
Dir.chdir(dir, &block)
|
311
|
+
else
|
312
|
+
block.call
|
313
|
+
end
|
389
314
|
end
|
390
315
|
|
391
|
-
Dir.chdir(dir, &block)
|
392
|
-
end
|
393
|
-
=end
|
394
|
-
|
395
316
|
end
|
396
317
|
|
397
318
|
end
|