tap-test 0.4.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/History CHANGED
@@ -1,3 +1,15 @@
1
+ == 0.6.0 / 2010-05-02
2
+
3
+ This release removes crufty methods that are rarely used and
4
+ add confusion to otherwise focused test modules. Updated to
5
+ Tap-1.3.0.
6
+
7
+ * updated to simplified Tap::Root
8
+ * removed FileTest#assert_files (and associated methods)
9
+ * removed SubsetTest#prompt_test
10
+ * added indent stripping to ShellTest#assert_output_equal
11
+ * added indent stripping to ShellTest#assert_alike
12
+
1
13
  == 0.4.0 / 2009-19-09
2
14
 
3
15
  Various improvements to the test modules. Note that FileTest now will
data/MIT-LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  Copyright (c) 2009, Regents of the University of Colorado.
2
2
 
3
- Copyright (c) 2009, Simon Chiang.
3
+ Copyright (c) 2009-2010, Simon Chiang.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README CHANGED
@@ -13,10 +13,6 @@ the shell behavior of executables and to define conditions for tests (ex
13
13
  integrates with Test::Unit and Mini::Test, but it is possible to include the
14
14
  test modules into other test frameworks.
15
15
 
16
- {Tap-Test}[http://tap.rubyforge.org/tap-test] is a part of the
17
- {Tap-Suite}[http://tap.rubyforge.org/tap-suite]. Check out these links for
18
- documentation, development, and bug tracking.
19
-
20
16
  * Website[http://tap.rubyforge.org]
21
17
  * Github[http://github.com/bahuvrihi/tap/tree/master]
22
18
  * {Google Group}[http://groups.google.com/group/ruby-on-tap]
@@ -40,9 +36,9 @@ saved on a failure (using ENV['KEEP_OUTPUTS']='true').
40
36
  acts_as_file_test
41
37
 
42
38
  def test_method_root
43
- assert_equal "test_method_root", File.basename(method_root.root)
39
+ assert_equal "test_method_root", File.basename(method_root.path)
44
40
 
45
- path = method_root.prepare(:tmp, 'file.txt') {|io| io << 'content' }
41
+ path = method_root.prepare('tmp/file.txt') {|io| io << 'content' }
46
42
  assert_equal "content", File.read(path)
47
43
  end
48
44
  end
@@ -94,15 +90,14 @@ or all tests using an ENV variable (ex ENV['ALL']='true').
94
90
 
95
91
  ==== {TapTest}[link:classes/Tap/Test/TapTest.html] (acts_as_tap_test)
96
92
 
97
- Sets up Tap::App.instance for testing tasks.
93
+ Sets up Tap::App.current for testing tasks.
98
94
 
99
95
  require 'tap/test/unit'
100
96
  class TapTestTest < Test::Unit::TestCase
101
97
  acts_as_tap_test
102
98
 
103
- def test_node
104
- n = app.node { "result" }
105
- assert_equal "result", n.call
99
+ def test_info
100
+ assert_equal 'state: 0 (READY) queue: 0', app.info
106
101
  end
107
102
  end
108
103
 
data/lib/tap/test.rb CHANGED
@@ -1,79 +1,85 @@
1
- require 'tap/root'
2
-
3
1
  module Tap
4
2
 
5
- # Tap::Test provides several convenience methods for including and
6
- # setting up Tap::Test modules. The manual use of this module looks
7
- # like this:
3
+ # Tap::Test provides several convenience methods for including and setting
4
+ # up Tap::Test modules. The manual use of this module looks like this:
8
5
  #
9
6
  # class SampleTest < Test::Unit::TestCase
10
7
  # extend Tap::Test
11
8
  # acts_as_tap_test
12
9
  # end
13
10
  #
14
- # The 'tap/test/unit' file performs this setup for Test::Unit
15
- # (ruby < 1.9) and Mini::Test (ruby >= 1.9); simply require it and
16
- # call the setup methods as necessary.
11
+ # The 'tap/test/unit' file performs this setup for Test::Unit (ruby < 1.9)
12
+ # and Mini::Test (ruby >= 1.9); simply require it and call the setup methods
13
+ # as necessary.
14
+ #
15
+ # require 'tap/test/unit'
16
+ # class SampleTest < Test::Unit::TestCase
17
+ # acts_as_tap_test
18
+ # end
17
19
  #
18
20
  module Test
19
- autoload(:SubsetTest, 'tap/test/subset_test')
20
- autoload(:FileTest, 'tap/test/file_test')
21
- autoload(:ShellTest, 'tap/test/shell_test')
22
- autoload(:TapTest, 'tap/test/tap_test')
23
- autoload(:Utils, 'tap/test/utils')
21
+ autoload :SubsetTest, 'tap/test/subset_test'
22
+ autoload :FileTest, 'tap/test/file_test'
23
+ autoload :ShellTest, 'tap/test/shell_test'
24
+ autoload :TapTest, 'tap/test/tap_test'
25
+ autoload :Utils, 'tap/test/utils'
24
26
 
25
27
  # Includes SubsetTest in the calling class.
26
28
  def acts_as_subset_test
27
29
  include Tap::Test::SubsetTest
28
30
  end
29
31
 
30
- # Includes FileTest in the calling class and instantiating class_test_root
31
- # (a Tap::Root). Options may be used to configure the class_test_root.
32
+ # Includes FileTest in the calling class and instantiates class_root.
33
+ # Options:
34
+ #
35
+ # :root:: Specifies the class_root. String roots are used to
36
+ # instantiate a new Tap::Root.
37
+ # :cleanup_dirs:: Specifies directories to cleanup under root.
32
38
  #
33
- # Note: by default acts_as_file_test determines a root directory
34
- # <em>based on the calling file</em>. Be sure to specify the root
35
- # directory manually if you call acts_as_file_test from a file that
36
- # isn't the test file.
39
+ # By default acts_as_file_test guesses a root directory using brittle
40
+ # logic that examines caller. Be sure to specify the root directory
41
+ # manually if you call acts_as_file_test from a file that isn't the test
42
+ # file, or via some proxy method.
37
43
  def acts_as_file_test(options={})
38
44
  include Tap::Test::FileTest
39
45
 
40
- options[:root] ||= test_root_dir
46
+ root = options[:root] || test_root_dir
47
+ root = Tap::Root.new(root) unless root.kind_of?(Tap::Root)
48
+ self.class_root = root
41
49
 
42
- if options.has_key?(:cleanup_dirs)
43
- self.cleanup_dirs = options.delete(:cleanup_dirs)
50
+ if cleanup_dirs = options[:cleanup_dirs]
51
+ self.cleanup_dirs = cleanup_dirs
44
52
  end
45
-
46
- self.class_test_root = Tap::Root.new(options)
47
53
  end
48
54
 
49
55
  # Includes ShellTest in the calling class. Options are set as the default
50
56
  # sh_test_options.
51
57
  def acts_as_shell_test(options=nil)
52
58
  include Tap::Test::ShellTest
53
- self.sh_test_options.merge!(options) if options
59
+ define_method(:sh_test_options) { super().merge(options) } unless options.nil?
54
60
  end
55
61
 
56
- # Includes TapTest in the calling class and calls acts_as_file_test with
57
- # the options.
62
+ # Includes TapTest in the calling class and calls acts_as_file_test. See
63
+ # acts_as_file_test for valid options.
58
64
  def acts_as_tap_test(options={})
59
65
  options[:root] ||= test_root_dir
60
66
  acts_as_file_test(options)
67
+
61
68
  include Tap::Test::TapTest
62
69
  end
63
70
 
64
71
  private
65
-
72
+
66
73
  # Infers the test root directory from the calling file.
67
- # 'some_class.rb' => 'some_class'
68
- # 'some_class_test.rb' => 'some_class'
74
+ # 'some_class_test.rb' => 'some_class_test'
69
75
  def test_root_dir # :nodoc:
70
76
  # caller[1] is considered the calling file (which should be the test case)
71
77
  # note that caller entries are like this:
72
78
  # ./path/to/file.rb:10
73
79
  # ./path/to/file.rb:10:in 'method'
74
-
80
+
75
81
  calling_file = caller[1].gsub(/:\d+(:in .*)?$/, "")
76
- calling_file.chomp(File.extname(calling_file)).chomp("_test")
82
+ calling_file.chomp(File.extname(calling_file))
77
83
  end
78
84
  end
79
85
  end
@@ -0,0 +1,23 @@
1
+ module Tap
2
+ module Test
3
+ class Env
4
+ def path(type)
5
+ [File.expand_path(type.to_s)]
6
+ end
7
+
8
+ def constant(const_str, type=nil)
9
+ return const_str if const_str.kind_of?(Module)
10
+
11
+ begin
12
+ current = Object
13
+ const_str.split(/::/).each do |const_name|
14
+ current = current.const_get(const_name)
15
+ end
16
+ current
17
+ rescue(NameError)
18
+ raise "uninitialized constant: #{const_str.inspect}"
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -4,59 +4,21 @@ require 'tap/test/utils'
4
4
  module Tap
5
5
  module Test
6
6
 
7
- # FileTest facilitates access and utilization of test-specific files and
8
- # directories. FileTest provides each test method with a Tap::Root
9
- # (method_root) specific for the method, and defines a new assertion
10
- # method (assert_files) to facilitate tests which involve the production
11
- # and/or modification of files.
12
- #
13
- # [file_test_doc_test.rb]
14
- # class FileTestDocTest < Test::Unit::TestCase
15
- # acts_as_file_test
16
- #
17
- # def test_something
18
- # # each test class has a class test root (ctr)
19
- # # and each test method has a method-specific
20
- # # root (method_root)
21
- #
22
- # ctr.root # => File.expand_path(__FILE__.chomp('_test.rb'))
23
- # method_root.root # => File.join(ctr.root, "/test_something")
24
- # method_root[:input] # => File.join(ctr.root, "/test_something/input")
25
- #
26
- # # files in the :output and :tmp directories are cleared
27
- # # before and after each test; this passes each time the
28
- # # test is run with no additional cleanup:
29
- #
30
- # assert !File.exists?(method_root[:tmp])
31
- #
32
- # tmp_file = method_root.prepare(:tmp, 'sample.txt') {|file| file << "content" }
33
- # assert_equal "content", File.read(tmp_file)
34
- #
35
- # # the assert_files method compares files produced
36
- # # by the block the expected files, ensuring they
37
- # # are the same (see the documentation for the
38
- # # simplest use of assert_files)
39
- #
40
- # expected_file = method_root.prepare(:expected, 'output.txt') {|file| file << 'expected output' }
41
- #
42
- # # passes
43
- # assert_files do
44
- # method_root.prepare(:output, 'output.txt') {|file| file << 'expected output' }
45
- # end
46
- # end
47
- # end
7
+ # FileTest simplifies testing of code that works with files. FileTest
8
+ # provides a method-specific Tap::Root (method_root) that expedites the
9
+ # creation and access of files, as well as a couple standard cleanup
10
+ # methods.
48
11
  #
49
12
  # ==== Cleanup
50
13
  #
51
- # By default the method_root directory is cleaned up at the end of the
52
- # test, making FileTest very conveient for creating temporary test files.
53
- # To prevent cleanup, either set the KEEP_OUTPUTS or KEEP_FAILURES ENV
54
- # variable to 'true'. The cleanup directories can be specified manually
55
- # using cleanup_dirs class variable:
14
+ # By default the entire method_root directory is cleaned up at the end of
15
+ # the test. To prevent cleanup, either set the KEEP_OUTPUTS or
16
+ # KEEP_FAILURES ENV variable to 'true'. The cleanup directories can be
17
+ # specified manually using cleanup_dirs class variable:
56
18
  #
57
19
  # class LimitedCleanupTest < Test::Unit::TestCase
58
20
  #
59
- # # only cleanup the method_root[:output] directory
21
+ # # only cleanup the output directory under root
60
22
  # acts_as_file_test :cleanup_dirs => [:output]
61
23
  # end
62
24
  #
@@ -66,46 +28,41 @@ module Tap
66
28
  # ==== Requirements
67
29
  #
68
30
  # FileTest requires that a method_name method is provided by the including
69
- # class, in order to properly set the directory for method_root.
31
+ # class, in order to properly set the directory for root.
70
32
  # Test::Unit::TestCase satisfies this requirement already.
71
33
  module FileTest
72
34
 
73
35
  def self.included(base) # :nodoc:
74
36
  super
75
37
  base.extend FileTest::ClassMethods
76
- base.cleanup_dirs = [:root]
77
38
  end
78
39
 
79
- # The test-method-specific Tap::Root which may be used to access test
80
- # files. method_root is a duplicate of ctr reconfigured so that
81
- # method_root.root is ctr[method_name.to_sym]
40
+ # The method-specific Tap::Root
82
41
  attr_reader :method_root
83
42
 
84
43
  # Sets up method_root and calls cleanup. Be sure to call super when
85
44
  # overriding this method.
86
45
  def setup
87
46
  super
88
- @method_root = ctr.dup.reconfigure(:root => ctr[method_name.to_sym])
47
+ @method_root = class_root.sub(method_name)
89
48
  cleanup
90
49
  end
91
50
 
92
- # Cleans up the method_root.root directory by removing the class
93
- # cleanup_dirs (by default :root, ie the method_root directory itself).
94
- # The root directory will be removed if it is empty.
51
+ # Cleans up the method_root directory by removing the cleanup_dirs
52
+ # specified for the class. (by default the entire method_root directory
53
+ # is removed). The method_root directory will be removed if it is empty.
95
54
  #
96
55
  # Override as necessary in subclasses.
97
56
  def cleanup
98
- self.class.cleanup_dirs.each do |dir|
99
- clear_dir(method_root[dir])
100
- end
101
- try_remove_dir(method_root.root)
57
+ cleanup_dirs = self.class.cleanup_dirs
58
+ cleanup_dirs.each {|dir| clear_dir(method_root.path(dir)) }
59
+
60
+ try_remove_dir(method_root.path)
102
61
  end
103
62
 
104
63
  # Calls cleanup unless flagged otherwise by an ENV variable (see above).
105
64
  # Be sure to call super when overriding this method.
106
65
  def teardown
107
- # check that method_root still exists (nil may
108
- # indicate setup was overridden without super)
109
66
  unless method_root
110
67
  raise "teardown failure: method_root is nil (does setup call super?)"
111
68
  end
@@ -119,188 +76,12 @@ module Tap
119
76
  end
120
77
  end
121
78
 
122
- try_remove_dir(ctr.root)
79
+ try_remove_dir(class_root.path)
123
80
  end
124
81
 
125
- # Convenience method to access the class_test_root.
126
- def ctr
127
- self.class.class_test_root or raise "setup failure: no class_test_root has been set for #{self.class}"
128
- end
129
-
130
- # Runs a file-based test that compares files created by the block with
131
- # files in an expected directory. The block receives files from the
132
- # input directory, and should return a list of files relative to the
133
- # output directory. Only the files returned by the block are compared;
134
- # additional files in the output directory are effectively ignored.
135
- #
136
- # === Example
137
- # Lets define a test that transforms input files into output files in a
138
- # trivial way, simply by replacing 'input' with 'output' in the file.
139
- #
140
- # class FileTestDocTest < Test::Unit::TestCase
141
- # acts_as_file_test
142
- #
143
- # def test_assert_files
144
- # assert_files do |input_files|
145
- # input_files.collect do |path|
146
- # input = File.read(path)
147
- # output_file = method_root.path(:output, File.basename(path))
148
- #
149
- # File.open(output_file, "w") do |f|
150
- # f << input.gsub(/input/, "output")
151
- # end
152
- #
153
- # output_file
154
- # end
155
- # end
156
- # end
157
- # end
158
- #
159
- # Now say you had some input and expected files for test_assert_files:
160
- #
161
- # file_test_doc/test_assert_files
162
- # |- expected
163
- # | |- one.txt
164
- # | `- two.txt
165
- # `- input
166
- # |- one.txt
167
- # `- two.txt
168
- #
169
- # [input/one.txt]
170
- # test input 1
171
- #
172
- # [input/two.txt]
173
- # test input 2
174
- #
175
- # [expected/one.txt]
176
- # test output 1
177
- #
178
- # [expected/two.txt]
179
- # test output 2
180
- #
181
- # When you run the test, the assert_files passes the input files to the
182
- # block. When the block completes, assert_files compares the output
183
- # files returned by the block with the files in the expected directory.
184
- # In this case, the files are equal and the test passes.
185
- #
186
- # Say you changed the content of one of the expected files:
187
- #
188
- # [expected/one.txt]
189
- # test flunk 1
190
- #
191
- # Now the test fails because the output files aren't equal to the
192
- # expected files. The test also fails if there are missing or extra
193
- # files.
194
- #
195
- # === Options
196
- # A variety of options adjust the behavior of assert_files:
197
- #
198
- # :input_dir specify the directory to glob for input files
199
- # (default method_root[:input])
200
- # :output_dir specify the output directory
201
- # (default method_root[:output])
202
- # :expected_dir specify the directory to glob for expected files
203
- # (default method_root[:expected])
204
- # :input_files directly specify the input files for the block
205
- # :expected_files directly specify the expected files for comparison
206
- # :include_input_directories specifies directories to be included in the
207
- # input_files array (by default dirs are excluded)
208
- # :include_expected_directories specifies directories to be included in the
209
- # expected-output file list comparison
210
- # (by default dirs are excluded)
211
- #
212
- # assert_files will fail if <tt>:expected_files</tt> was not specified
213
- # in the options and no files were found in <tt>:expected_dir</tt>. This
214
- # check tries to prevent silent false-positive results when you forget
215
- # to put expected files in their place.
216
- #
217
- # === File References
218
- #
219
- # Sometimes the same files will get used across multiple tests. To
220
- # allow separate management of test files and prevent duplication, file
221
- # references can be provided in place of test files. For instance, with
222
- # a test directory like:
223
- #
224
- # method_root
225
- # |- expected
226
- # | |- one.txt.ref
227
- # | `- two.txt.ref
228
- # |- input
229
- # | |- one.txt.ref
230
- # | `- two.txt.ref
231
- # `- ref
232
- # |- one.txt
233
- # `- two.txt
234
- #
235
- # The input and expected files (all references in this case) can be
236
- # dereferenced to the 'ref' paths like so:
237
- #
238
- # assert_files :reference_dir => method_root[:ref] do |input_files|
239
- # input_files # => ['method_root/ref/one.txt', 'method_root/ref/two.txt']
240
- #
241
- # input_files.collect do |input_file|
242
- # output_file = method_root.path(:output, File.basename(input_file)
243
- # FileUtils.cp(input_file, output_file)
244
- # output_file
245
- # end
246
- # end
247
- #
248
- # Dereferencing occurs relative to the input_dir/expected_dir
249
- # configurations; a reference_dir must be specified for dereferencing to
250
- # occur (see Utils.dereference for more details).
251
- #
252
- #--
253
- # TODO:
254
- # * add debugging information to indicate, for instance, when
255
- # dereferencing is going on.
256
- def assert_files(options={}, &block) # :yields: input_files
257
- transform_test(block, options) do |expected_file, output_file|
258
- unless FileUtils.cmp(expected_file, output_file)
259
- flunk "<#{expected_file}> not equal to\n<#{output_file}>"
260
- end
261
- end
262
- end
263
-
264
- # The default assert_files options
265
- def assert_files_options
266
- {
267
- :input_dir => method_root[:input],
268
- :output_dir => method_root[:output],
269
- :expected_dir => method_root[:expected],
270
-
271
- :input_files => nil,
272
- :expected_files => nil,
273
- :include_input_directories => false,
274
- :include_expected_directories => false,
275
-
276
- :reference_dir => nil,
277
- :reference_extname => '.ref'
278
- }
279
- end
280
-
281
- private
282
-
283
- # Yields to the input block for each pair of entries in the input
284
- # arrays. An error is raised if the input arrays do not have equal
285
- # numbers of entries.
286
- def each_pair(a, b, &block) # :yields: entry_a, entry_b,
287
- each_pair_with_index(a,b) do |entry_a, entry_b, index|
288
- yield(entry_a, entry_b)
289
- end
290
- end
291
-
292
- # Same as each_pair but yields the index of the entries as well.
293
- def each_pair_with_index(a, b, error_msg=nil, &block) # :yields: entry_a, entry_b, index
294
- a = [a] unless a.kind_of?(Array)
295
- b = [b] unless b.kind_of?(Array)
296
-
297
- unless a.length == b.length
298
- raise ArgumentError, (error_msg || "The input arrays must have an equal number of entries.")
299
- end
300
-
301
- 0.upto(a.length-1) do |index|
302
- yield(a[index], b[index], index)
303
- end
82
+ # Convenience method to access the class_root.
83
+ def class_root
84
+ self.class.class_root or raise "setup failure: no class_root has been set for #{self.class}"
304
85
  end
305
86
 
306
87
  # Attempts to recursively remove the specified method directory and all
@@ -310,80 +91,15 @@ module Tap
310
91
  FileUtils.rm_r(dir) if File.exists?(dir)
311
92
  end
312
93
 
313
- # Attempts to remove the specified directory. The root
314
- # will not be removed if the directory does not exist, or
315
- # is not empty.
94
+ # Attempts to remove the specified directory. The directory will not be
95
+ # removed unless fully empty (including hidden files).
316
96
  def try_remove_dir(dir)
317
- # Remove the directory if possible
318
97
  begin
319
- FileUtils.rmdir(dir) if File.exists?(dir) && Dir.glob(File.join(dir, "*")).empty?
98
+ FileUtils.rmdir(dir) if File.directory?(dir) && Dir.glob(File.join(dir, "*")).empty?
320
99
  rescue
321
100
  # rescue cases where there is a hidden file, for example .svn
322
101
  end
323
102
  end
324
-
325
- def transform_test(block, options={}) # :yields: expected_files, output_files
326
- options = assert_files_options.merge(options)
327
- input_dir = options[:input_dir]
328
- output_dir = options[:output_dir]
329
- expected_dir = options[:expected_dir]
330
-
331
- reference_dir = options[:reference_dir]
332
- reference_pattern = options[:reference_pattern]
333
-
334
- Utils.dereference([input_dir, expected_dir], reference_dir, reference_pattern || '**/*.ref') do
335
-
336
- # Get the input and expected files in this manner:
337
- # - look for manually specified files
338
- # - glob for files if none were specified
339
- # - expand paths and sort
340
- # - remove directories unless specified not to do so
341
- input_files, expected_files = [:input, :expected].collect do |key|
342
- files = options["#{key}_files".to_sym]
343
- if files.nil?
344
- pattern = File.join(options["#{key}_dir".to_sym], "**/*")
345
- files = Dir.glob(pattern)
346
- end
347
- files = [files].flatten.collect {|file| File.expand_path(file) }.sort
348
-
349
- unless options["include_#{key}_directories".to_sym]
350
- files.delete_if {|file| File.directory?(file)}
351
- end
352
-
353
- files
354
- end
355
-
356
- # check at least one expected file was found
357
- if expected_files.empty? && options[:expected_files] == nil
358
- flunk "No expected files specified."
359
- end
360
-
361
- # get output files from the block, expand and sort
362
- output_files = [*block.call(input_files)].collect do |output_file|
363
- File.expand_path(output_file)
364
- end.sort
365
-
366
- # check that the expected and output paths are the same
367
- translated_expected_files = expected_files.collect do |expected_file|
368
- Tap::Root::Utils.translate(expected_file, expected_dir, output_dir)
369
- end
370
- assert_equal translated_expected_files, output_files, "Missing, extra, or unexpected output files"
371
-
372
- # check that the expected and output file contents are equal
373
- errors = []
374
- each_pair(expected_files, output_files) do |expected_file, output_file|
375
- unless (File.directory?(expected_file) && File.directory?(output_file)) || FileUtils.cmp(expected_file, output_file)
376
- begin
377
- yield(expected_file, output_file)
378
- rescue
379
- errors << $!
380
- end
381
- end
382
- end
383
- flunk "File compare failed:\n" + errors.join("\n") unless errors.empty?
384
- end
385
- end
386
-
387
103
  end
388
104
  end
389
105
  end
@@ -1,3 +1,5 @@
1
+ require 'tmpdir'
2
+
1
3
  module Tap
2
4
  module Test
3
5
  module FileTest
@@ -5,12 +7,21 @@ module Tap
5
7
  # Class methods extending tests which include FileTest.
6
8
  module ClassMethods
7
9
 
8
- # The class-level test root (a Tap::Root)
9
- attr_accessor :class_test_root
10
+ # Sets the class_root
11
+ attr_writer :class_root
10
12
 
11
- # An array of directories to be cleaned up by cleanup
12
- attr_accessor :cleanup_dirs
13
+ # The class-level test root (a Tap::Root)
14
+ def class_root
15
+ @class_root ||= Root.new(Dir.tmpdir)
16
+ end
17
+
18
+ # Sets cleanup_dirs
19
+ attr_writer :cleanup_dirs
13
20
 
21
+ # An array of directories to be cleaned up by cleanup (default ['.'])
22
+ def cleanup_dirs
23
+ @cleanup_dirs ||= ['.']
24
+ end
14
25
  end
15
26
  end
16
27
  end
@@ -1,5 +1,5 @@
1
- require 'tap/test/shell_test/class_methods'
2
1
  require 'tap/test/shell_test/regexp_escape'
2
+ require 'tap/utils'
3
3
 
4
4
  module Tap
5
5
  module Test
@@ -40,11 +40,7 @@ module Tap
40
40
  # end
41
41
  #
42
42
  module ShellTest
43
-
44
- def self.included(base) # :nodoc:
45
- super
46
- base.extend ShellTest::ClassMethods
47
- end
43
+ include Tap::Utils
48
44
 
49
45
  # Sets up the ShellTest module. Be sure to call super if you override
50
46
  # setup in an including module.
@@ -60,7 +56,7 @@ module Tap
60
56
  verbose && verbose =~ /^true$/i ? true : false
61
57
  end
62
58
 
63
- # Returns true if the ENV variable 'QUIET' is true. When quiet,
59
+ # Returns true if the ENV variable 'QUIET' is true or nil. When quiet,
64
60
  # ShellTest does not print any extra information to $stdout.
65
61
  #
66
62
  # If 'VERBOSE' and 'QUIET' are both set, verbose wins.
@@ -68,42 +64,7 @@ module Tap
68
64
  return false if verbose?
69
65
 
70
66
  quiet = ENV['QUIET']
71
- quiet && quiet =~ /^true$/i ? true : false
72
- end
73
-
74
- # Sets the specified ENV variables and returns the *current* env.
75
- # If replace is true, current ENV variables are replaced; otherwise
76
- # the new env variables are simply added to the existing set.
77
- def set_env(env={}, replace=false)
78
- current_env = {}
79
- ENV.each_pair do |key, value|
80
- current_env[key] = value
81
- end
82
-
83
- ENV.clear if replace
84
-
85
- env.each_pair do |key, value|
86
- ENV[key] = value
87
- end if env
88
-
89
- current_env
90
- end
91
-
92
- # Sets the specified ENV variables for the duration of the block.
93
- # If replace is true, current ENV variables are replaced; otherwise
94
- # the new env variables are simply added to the existing set.
95
- #
96
- # Returns the block return.
97
- def with_env(env={}, replace=false)
98
- current_env = nil
99
- begin
100
- current_env = set_env(env, replace)
101
- yield
102
- ensure
103
- if current_env
104
- set_env(current_env, true)
105
- end
106
- end
67
+ quiet.nil? || quiet =~ /^true$/i ? true : false
107
68
  end
108
69
 
109
70
  # Executes the command using IO.popen and returns the stdout content.
@@ -212,12 +173,13 @@ module Tap
212
173
  def sh_test(cmd, options={})
213
174
  options = sh_test_options.merge(options)
214
175
 
215
- if cmd =~ /\A\s*?\n?(\s*)(.*?\n)(.*)\z/m
176
+ # strip indentiation if possible
177
+ if cmd =~ /\A(?:\s*?\n)?( *)(.*?\n)(.*)\z/m
216
178
  indent, cmd, expected = $1, $2, $3
217
179
  cmd.strip!
218
180
 
219
181
  if indent.length > 0 && options[:indents]
220
- expected.gsub!(/^\s{0,#{indent.length}}/, '')
182
+ expected.gsub!(/^ {0,#{indent.length}}/, '')
221
183
  end
222
184
  end
223
185
 
@@ -228,8 +190,13 @@ module Tap
228
190
  result
229
191
  end
230
192
 
193
+ # Similar to sh_test, but matches the output against each of the
194
+ # regexps. A hash of sh options can be provided as the last argument;
195
+ # it will be merged with the default sh_test_options.
196
+ #
197
+ # The output is yielded to the block, if given, for further validation.
198
+ # Returns the sh output.
231
199
  def sh_match(cmd, *regexps)
232
-
233
200
  options = regexps.last.kind_of?(Hash) ? regexps.pop : {}
234
201
  options = sh_test_options.merge(options)
235
202
  result = sh(cmd, options)
@@ -241,14 +208,54 @@ module Tap
241
208
  result
242
209
  end
243
210
 
244
- # Returns a hash of the default sh_test options. See
245
- # ShellTest::ClassMethods#sh_test_options.
211
+ # Returns a hash of default sh_test options.
246
212
  def sh_test_options
247
- self.class.sh_test_options
213
+ {
214
+ :cmd_pattern => '% ',
215
+ :cmd => '2>&1 ',
216
+ :indents => true,
217
+ :env => {
218
+ 'TAPFILE' => nil,
219
+ 'TAP_GEMS' => nil,
220
+ 'TAP_PATH' => nil,
221
+ 'TAPENV' => nil,
222
+ 'TAPRC' => nil,
223
+ 'TAP_DEBUG' => nil
224
+ },
225
+ :replace_env => false
226
+ }
248
227
  end
249
228
 
229
+ # Asserts whether or not the a and b strings are equal, with a more
230
+ # readable output than assert_equal for large strings (especially large
231
+ # strings with significant whitespace).
232
+ #
233
+ # One gotcha is that assert_output_equal lstrips indentation off of 'a',
234
+ # so that these all pass:
235
+ #
236
+ # assert_output_equal %q{
237
+ # line one
238
+ # line two
239
+ # }, "line one\nline two\n"
240
+ #
241
+ # assert_output_equal %q{
242
+ # line one
243
+ # line two
244
+ # }, "line one\nline two\n
245
+ #
246
+ # assert_output_equal %q{
247
+ # line one
248
+ # line two
249
+ # }, "line one\nline two\n"
250
+ #
251
+ # Use the assert_output_equal! method to prevent indentation stripping.
250
252
  def assert_output_equal(a, b, msg=nil)
251
- a = a[1..-1] if a[0] == ?\n
253
+ a = strip_indent(a)
254
+ assert_output_equal!(a, b, msg)
255
+ end
256
+
257
+ # Same as assert_output_equal but without indentation stripping.
258
+ def assert_output_equal!(a, b, msg=nil)
252
259
  if a == b
253
260
  assert true
254
261
  else
@@ -262,8 +269,40 @@ module Tap
262
269
  }
263
270
  end
264
271
  end
265
-
272
+
273
+ # Asserts whether or not b is like a (which should be a Regexp), and
274
+ # provides a more readable output in the case of a failure as compared
275
+ # with assert_match.
276
+ #
277
+ # If a is a string, then indentation is stripped off and it is turned
278
+ # into a RegexpEscape. Using that syntax, all these pass:
279
+ #
280
+ # assert_alike %q{
281
+ # the time is: :...:
282
+ # now!
283
+ # }, "the time is: #{Time.now}\nnow!\n"
284
+ #
285
+ # assert_alike %q{
286
+ # the time is: :...:
287
+ # now!
288
+ # }, "the time is: #{Time.now}\nnow!\n"
289
+ #
290
+ # assert_alike %q{
291
+ # the time is: :...:
292
+ # now!
293
+ # }, "the time is: #{Time.now}\nnow!\n"
294
+ #
295
+ # Use assert_alike! to prevent indentation stripping (conversion to a
296
+ # RegexpEscape is still in effect).
266
297
  def assert_alike(a, b, msg=nil)
298
+ a = strip_indent(a) if a.kind_of?(String)
299
+ assert_alike!(a, b, msg)
300
+ end
301
+
302
+ # Same as assert_alike but without indentation stripping.
303
+ def assert_alike!(a, b, msg=nil)
304
+ a = RegexpEscape.new(a) if a.kind_of?(String)
305
+
267
306
  if b =~ a
268
307
  assert true
269
308
  else
@@ -280,7 +319,21 @@ module Tap
280
319
 
281
320
  private
282
321
 
283
- def whitespace_escape(str)
322
+ # helper for stripping indentation off a string
323
+ def strip_indent(str) # :nodoc:
324
+ if str =~ /\A\s*?\n( *)(.*)\z/m
325
+ indent, str = $1, $2, $3
326
+
327
+ if indent.length > 0
328
+ str.gsub!(/^ {0,#{indent.length}}/, '')
329
+ end
330
+ end
331
+
332
+ str
333
+ end
334
+
335
+ # helper for formatting escaping whitespace into readable text
336
+ def whitespace_escape(str) # :nodoc:
284
337
  str.to_s.gsub(/\s/) do |match|
285
338
  case match
286
339
  when "\n" then "\\n\n"
@@ -5,37 +5,37 @@ module Tap
5
5
  module Test
6
6
 
7
7
  # SubsetTest provides methods to conditionally run tests.
8
- #
8
+ #
9
9
  # require 'tap/test'
10
10
  #
11
11
  # class Test::Unit::TestCase
12
12
  # # only true if running on windows
13
13
  # condition(:windows) { match_platform?('mswin') }
14
- #
14
+ #
15
15
  # # only true if running on anything but windows
16
16
  # condition(:non_windows) { match_platform?('non_mswin') }
17
17
  # end
18
18
  #
19
19
  # Here the WindowsOnlyTest will only run on a Windows platform. Conditions
20
- # like these may be targeted at specific tests when only some tests need
20
+ # like these may be targeted at specific tests when only some tests need
21
21
  # to be skipped.
22
- #
22
+ #
23
23
  # class RunOnlyAFewTest < Test::Unit::TestCase
24
24
  # include SubsetTest
25
- #
25
+ #
26
26
  # def test_runs_all_the_time
27
27
  # assert true
28
28
  # end
29
- #
29
+ #
30
30
  # def test_runs_only_if_non_windows_condition_is_true
31
31
  # condition_test(:non_windows) { assert true }
32
32
  # end
33
33
  # end
34
- #
34
+ #
35
35
  # def test_runs_only_when_ENV_variable_EXTENDED_is_true
36
36
  # extended_test { assert true }
37
37
  # end
38
- #
38
+ #
39
39
  # def test_runs_only_when_ENV_variable_BENCHMARK_is_true
40
40
  # benchmark_test do |x|
41
41
  # x.report("init speed") { 10000.times { Object.new } }
@@ -46,24 +46,10 @@ module Tap
46
46
  # subset_test('CUSTOM') { assert true }
47
47
  # end
48
48
  # end
49
- #
49
+ #
50
50
  # In the example, the ENV variables EXTENDED, BENCHMARK, and CUSTOM act as
51
- # flags to run specific tests. If you're running your test using Rake, ENV
52
- # variables can be set from the command line like so:
53
- #
54
- # % EXTENDED=true rake test
55
- # % BENCHMARK=true rake test
56
- #
57
- # Since tap and rap can run rake tasks as well, these are equivalent:
58
- #
59
- # % EXTENDED=true tap run test
60
- # % BENCHMARK=true rap test
61
- #
62
- # To run all tests that get switched using an ENV variable, set ALL=true.
63
- #
64
- # % ALL=true rap test
65
- #
66
- # See SubsetTest::ClassMethods for more information.
51
+ # flags to run specific tests. See SubsetTest::ClassMethods for more
52
+ # information.
67
53
  module SubsetTest
68
54
 
69
55
  def self.included(base) # :nodoc:
@@ -209,37 +195,6 @@ module Tap
209
195
  Benchmark.bm(length, &block)
210
196
  end
211
197
  end
212
-
213
- # Declares a subset_test for the ENV variable 'PROMPT'. When run, prompts
214
- # the user for each input specified in array. Inputs will then be passed
215
- # as a hash to the block. Prints 'p' unless run.
216
- #
217
- # def test_requiring_inputs
218
- # prompt_test(:a, :b, :c) {|a, b, c| ... }
219
- # end
220
- #
221
- # If run, the command line prompt will be like the following:
222
- #
223
- # test_requiring_inputs: Enter values or 'skip'
224
- # a: avalue
225
- # b: bvalue
226
- # c: cvalue
227
- #
228
- # The block recieves ['avalue', 'bvalue', 'cvalue'].
229
- def prompt_test(*keys, &block)
230
- subset_test("PROMPT", "p") do
231
- puts "\n#{name} -- Enter values or 'skip'."
232
-
233
- values = keys.collect do |key|
234
- print "#{key}: "
235
- value = gets.strip
236
- flunk "skipped test" if value =~ /skip/i
237
- value
238
- end
239
-
240
- yield(*values)
241
- end
242
- end
243
198
  end
244
199
  end
245
200
  end
@@ -1,10 +1,8 @@
1
1
  require 'tap/app'
2
+ require 'tap/test/env'
2
3
 
3
4
  module Tap
4
5
  module Test
5
-
6
- # Sets up and tears down Tap::App.instance. This prevents tests that modify
7
- # either from inadvertently conflicting with one another.
8
6
  module TapTest
9
7
 
10
8
  # The test specific app
@@ -12,21 +10,21 @@ module Tap
12
10
 
13
11
  def setup
14
12
  super
15
- Tap::App.instance = @app = Tap::App.new(app_config)
16
- end
17
-
18
- def env_config
19
- {:gems => :none, :root => @method_root || Dir.pwd}
20
- end
21
-
22
- def app_config
23
- {:debug => true, :quiet => true, :env => Tap::Env.new(env_config)}
13
+ @app = Tap::App.new({:debug => true}, {:env => Env.new})
14
+ @context = Tap::App.set_context(Tap::App::CURRENT => @app)
15
+ @desc = nil
16
+ @baseclass = '/tap/task'
17
+ @namespace = self.class
24
18
  end
25
19
 
26
20
  def teardown
27
- Tap::App.instance = nil
21
+ Tap::App.set_context(@context)
28
22
  super
29
23
  end
24
+
25
+ def signal(sig, args=[], &block)
26
+ app.call({'sig' => sig, 'args' => args}, &block)
27
+ end
30
28
  end
31
29
  end
32
30
  end
@@ -0,0 +1,24 @@
1
+ require 'tap/middleware'
2
+
3
+ module Tap
4
+ module Test
5
+ class Tracer < Middleware
6
+ attr_reader :stack
7
+ attr_reader :results
8
+ attr_reader :runlist
9
+
10
+ def initialize(stack)
11
+ @stack = stack
12
+ @results = {}
13
+ @runlist = []
14
+ end
15
+
16
+ def call(node, inputs=[])
17
+ runlist << node
18
+ result = stack.call(node, inputs)
19
+ (results[node] ||= []) << result
20
+ result
21
+ end
22
+ end
23
+ end
24
+ end
@@ -58,17 +58,19 @@ module Tap
58
58
  # # !> DereferenceError
59
59
  #
60
60
  def reference_map(source_dir, reference_dir, pattern='**/*.ref')
61
- Dir.glob(File.join(source_dir, pattern)).sort.collect do |source|
61
+ source_root = Root.new(source_dir)
62
+ reference_root = Root.new(reference_dir)
63
+ source_root.glob(pattern).sort.collect do |source|
62
64
  # use the path specified in the source file
63
65
  relative_path = File.read(source).gsub(/#.*$/, "").strip
64
66
 
65
67
  # use the relative filepath of the source file to the
66
68
  # source dir (minus the extname) if no path is specified
67
69
  if relative_path.empty?
68
- relative_path = Tap::Root::Utils.relative_path(source_dir, source).chomp(File.extname(source))
70
+ relative_path = source_root.rp(source).chomp(File.extname(source))
69
71
  end
70
72
 
71
- reference = File.join(reference_dir, relative_path)
73
+ reference = reference_root.path(relative_path)
72
74
 
73
75
  # raise an error if no reference file is found
74
76
  unless File.exists?(reference)
@@ -1,7 +1,7 @@
1
1
  module Tap
2
2
  module Test
3
3
  MAJOR = 0
4
- MINOR = 3
4
+ MINOR = 6
5
5
  TINY = 0
6
6
 
7
7
  VERSION="#{MAJOR}.#{MINOR}.#{TINY}"
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tap-test
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 6
8
+ - 0
9
+ version: 0.6.0
5
10
  platform: ruby
6
11
  authors:
7
12
  - Simon Chiang
@@ -9,19 +14,23 @@ autorequire:
9
14
  bindir: bin
10
15
  cert_chain: []
11
16
 
12
- date: 2009-12-19 00:00:00 -07:00
17
+ date: 2010-05-02 00:00:00 -06:00
13
18
  default_executable:
14
19
  dependencies:
15
20
  - !ruby/object:Gem::Dependency
16
21
  name: tap
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
20
24
  requirements:
21
25
  - - ">="
22
26
  - !ruby/object:Gem::Version
23
- version: 0.19.0
24
- version:
27
+ segments:
28
+ - 1
29
+ - 3
30
+ - 0
31
+ version: 1.3.0
32
+ type: :runtime
33
+ version_requirements: *id001
25
34
  description:
26
35
  email: simon.a.chiang@gmail.com
27
36
  executables: []
@@ -34,23 +43,23 @@ extra_rdoc_files:
34
43
  - MIT-LICENSE
35
44
  files:
36
45
  - lib/tap/test.rb
46
+ - lib/tap/test/env.rb
37
47
  - lib/tap/test/file_test.rb
38
48
  - lib/tap/test/file_test/class_methods.rb
39
49
  - lib/tap/test/shell_test.rb
40
- - lib/tap/test/shell_test/class_methods.rb
41
50
  - lib/tap/test/shell_test/regexp_escape.rb
42
51
  - lib/tap/test/subset_test.rb
43
52
  - lib/tap/test/subset_test/class_methods.rb
44
53
  - lib/tap/test/tap_test.rb
54
+ - lib/tap/test/tracer.rb
45
55
  - lib/tap/test/unit.rb
46
56
  - lib/tap/test/utils.rb
47
57
  - lib/tap/test/version.rb
48
- - tap.yml
49
58
  - History
50
59
  - README
51
60
  - MIT-LICENSE
52
61
  has_rdoc: true
53
- homepage: http://tap.rubyforge.org/tap-test/
62
+ homepage: http://tap.rubyforge.org/tap-test
54
63
  licenses: []
55
64
 
56
65
  post_install_message:
@@ -67,18 +76,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
67
76
  requirements:
68
77
  - - ">="
69
78
  - !ruby/object:Gem::Version
79
+ segments:
80
+ - 0
70
81
  version: "0"
71
- version:
72
82
  required_rubygems_version: !ruby/object:Gem::Requirement
73
83
  requirements:
74
84
  - - ">="
75
85
  - !ruby/object:Gem::Version
86
+ segments:
87
+ - 0
76
88
  version: "0"
77
- version:
78
89
  requirements: []
79
90
 
80
91
  rubyforge_project: tap
81
- rubygems_version: 1.3.5
92
+ rubygems_version: 1.3.6
82
93
  signing_key:
83
94
  specification_version: 3
84
95
  summary: Test modules for Tap
@@ -1,28 +0,0 @@
1
- module Tap
2
- module Test
3
- module ShellTest
4
- # Class methods extending tests which include ShellTest.
5
- module ClassMethods
6
-
7
- # Sets the default sh_test_options
8
- attr_writer :sh_test_options
9
-
10
- # Returns a hash of the default sh_test options.
11
- def sh_test_options
12
- @sh_test_options ||= {
13
- :cmd_pattern => '% ',
14
- :cmd => '2>&1 ',
15
- :indents => true
16
- }
17
- end
18
-
19
- private
20
-
21
- # helper to retrieve class constants
22
- def class_const(const_name) # :nodoc:
23
- const_defined?(const_name) ? const_get(const_name) : nil
24
- end
25
- end
26
- end
27
- end
28
- end
data/tap.yml DELETED
File without changes