tap-test 0.4.0 → 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/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