rubytest 0.5.4 → 0.6.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/lib/rubytest/rake.rb CHANGED
@@ -1,17 +1,19 @@
1
+ require 'rubytest'
1
2
  require 'rake/tasklib'
2
3
 
3
- module Ruth
4
+ module Test
4
5
 
6
+ ##
7
+ # Rake subspace.
5
8
  #
6
9
  module Rake
7
10
 
8
- # TODO: The test task uses #fork. Maybe it should shell out instead?
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 the task.
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 scripts to load. Can be a file glob.
27
- attr_accessor :tests
28
-
29
- # Paths to add to $LOAD_PATH.
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="run tests", &block)
50
- @name = name
51
- @desc = 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
- @loadpath = ['lib']
54
- @requires = []
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(self)
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
- @tests ||= default_tests
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
- #require 'test'
78
- require 'test/runner'
79
-
80
- loadpath.each { |d| $LOAD_PATH.unshift(d) }
81
- requires.each { |f| require f }
82
- test_files.each { |f| require f }
83
-
84
- suite = $TEST_SUITE || []
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
- Process.wait
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
- # TODO: simplify?
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['tests']
109
- ENV['tests'].split(/[:;]/)
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
- #def ruby_command
117
- # File.join(RbConfig::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])
118
- #end
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
 
@@ -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
- # Default report is in the old "dot-progress" format.
8
- DEFAULT_FORMAT = 'dotprogress'
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
- # / / / D E F A U L T S / / /
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
- # Default selection of units for filtering tests.
56
- def self.units
57
- @unit ||= []
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
- def self.hard=(boolean)
67
- @hard = !!boolean
68
- end
69
-
41
+ # TODO: Cache or not?
70
42
  #
71
- def self.autopath
72
- @autopath
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
- attr :format
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
- @verbose
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 [Array] suite
162
- # A list of compliant tests/testcases.
83
+ # @param [Config] config
84
+ # Config instance.
163
85
  #
164
- def initialize(options={}, &block)
165
- @suite = options[:suite] || self.class.suite
166
- @files = options[:files] || self.class.files
167
- @format = options[:format] || self.class.format
168
- @tags = options[:tags] || self.class.tags
169
- @units = options[:units] || self.class.units
170
- @match = options[:match] || self.class.match
171
- @verbose = options[:verbose] || self.class.verbose
172
- @hard = options[:hard] || self.class.hard
173
- @autopath = options[:autopath] || self.class.autopath
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
- ignore_callers
114
+ cd_chdir do
115
+ Test::Config.load_path_setup if config.autopath?
197
116
 
198
- files_resolved.each do |file|
199
- require file
200
- end
117
+ ignore_callers
201
118
 
202
- @reporter = reporter_load(format)
203
- @recorder = Recorder.new
119
+ config.loadpath.each{ |path| $LOAD_PATH.unshift(path) }
120
+ config.requires.each{ |file| require file }
204
121
 
205
- @observers = [advice, @recorder, @reporter]
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
- #end
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
- def files_resolved
372
- list = files.flatten
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
- =begin
381
- # TODO ?
382
- def cd_tmp(&block)
383
- dir = Test::Config.root + '/tmp'
384
- if Directory.exist?(dir)
385
- dir = File.join(dir, 'test')
386
- FileUtils.mkdir(dir) unless File.exist?(dir)
387
- else
388
- dir = File.join(Dir.tmpdir)
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