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