bahuvrihi-tap 0.10.6 → 0.10.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/bin/rap +13 -5
  2. data/lib/tap.rb +0 -4
  3. data/lib/tap/app.rb +10 -138
  4. data/lib/tap/constants.rb +1 -1
  5. data/lib/tap/declarations.rb +201 -0
  6. data/lib/tap/env.rb +10 -2
  7. data/lib/tap/exe.rb +2 -2
  8. data/lib/tap/generator/generators/root/templates/Rakefile +1 -0
  9. data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +1 -1
  10. data/lib/tap/spec.rb +38 -63
  11. data/lib/tap/spec/adapter.rb +8 -31
  12. data/lib/tap/spec/inheritable_class_test_root.rb +9 -0
  13. data/lib/tap/support/audit.rb +0 -2
  14. data/lib/tap/support/combinator.rb +83 -31
  15. data/lib/tap/support/configurable_class.rb +7 -7
  16. data/lib/tap/support/{dependable.rb → dependencies.rb} +9 -7
  17. data/lib/tap/support/executable.rb +226 -19
  18. data/lib/tap/support/gems/rake.rb +6 -3
  19. data/lib/tap/support/join.rb +87 -0
  20. data/lib/tap/support/joins.rb +13 -0
  21. data/lib/tap/support/joins/fork.rb +18 -0
  22. data/lib/tap/support/joins/merge.rb +20 -0
  23. data/lib/tap/support/joins/sequence.rb +21 -0
  24. data/lib/tap/support/joins/switch.rb +23 -0
  25. data/lib/tap/support/joins/sync_merge.rb +57 -0
  26. data/lib/tap/support/lazydoc/document.rb +10 -0
  27. data/lib/tap/support/node.rb +58 -0
  28. data/lib/tap/support/parser.rb +379 -0
  29. data/lib/tap/support/schema.rb +350 -0
  30. data/lib/tap/support/tdoc.rb +5 -0
  31. data/lib/tap/support/validation.rb +2 -0
  32. data/lib/tap/task.rb +26 -61
  33. data/lib/tap/test.rb +9 -82
  34. data/lib/tap/test/assertions.rb +38 -0
  35. data/lib/tap/test/extensions.rb +78 -0
  36. data/lib/tap/test/{file_methods.rb → file_test.rb} +64 -37
  37. data/lib/tap/test/{file_methods_class.rb → file_test_class.rb} +2 -2
  38. data/lib/tap/test/regexp_escape.rb +87 -0
  39. data/lib/tap/test/script_test.rb +46 -0
  40. data/lib/tap/test/script_tester.rb +109 -0
  41. data/lib/tap/test/{subset_methods.rb → subset_test.rb} +9 -9
  42. data/lib/tap/test/{subset_methods_class.rb → subset_test_class.rb} +22 -14
  43. data/lib/tap/test/{tap_methods.rb → tap_test.rb} +43 -6
  44. data/lib/tap/test/utils.rb +6 -3
  45. metadata +27 -24
  46. data/lib/tap/parser.rb +0 -619
  47. data/lib/tap/spec/file_methods.rb +0 -16
  48. data/lib/tap/spec/file_methods_class.rb +0 -13
  49. data/lib/tap/spec/subset_methods.rb +0 -14
  50. data/lib/tap/support/batchable.rb +0 -47
  51. data/lib/tap/support/batchable_class.rb +0 -107
  52. data/lib/tap/support/declarations.rb +0 -131
  53. data/lib/tap/support/lazydoc/declaration.rb +0 -20
  54. data/lib/tap/support/parsers/base.rb +0 -81
  55. data/lib/tap/support/parsers/server.rb +0 -113
  56. data/lib/tap/test/script_methods.rb +0 -75
  57. data/lib/tap/test/script_methods/regexp_escape.rb +0 -94
  58. data/lib/tap/test/script_methods/script_test.rb +0 -109
  59. data/lib/tap/workflow.rb +0 -161
data/lib/tap/test.rb CHANGED
@@ -1,20 +1,26 @@
1
1
  require 'test/unit'
2
2
  $:.unshift File.expand_path("#{File.dirname(__FILE__)}/..")
3
+ require 'tap/test/extensions'
3
4
 
4
5
  module Test # :nodoc:
5
6
  module Unit # :nodoc:
6
7
 
7
8
  # Methods extending TestCase. For more information see:
8
- # - Tap::Test::SubsetMethods
9
- # - Tap::Test::FileMethods
10
- # - Tap::Test::TapMethods
9
+ # - Tap::Test::SubsetTest
10
+ # - Tap::Test::FileTest
11
+ # - Tap::Test::TapTest
11
12
  #
12
13
  #--
13
14
  #See the TestTutorial for more information.
14
15
  class TestCase
16
+ extend Tap::Test::Extensions
17
+
15
18
  class << self
19
+ alias tap_original_test_case_inherited inherited
16
20
 
17
21
  def inherited(child)
22
+ super
23
+ tap_original_test_case_inherited(child)
18
24
  child.instance_variable_set(:@skip_messages, [])
19
25
  child.instance_variable_set(:@run_test_suite, true)
20
26
  end
@@ -52,86 +58,7 @@ module Test # :nodoc:
52
58
  Test::Unit::TestSuite.new(name)
53
59
  end
54
60
  end
55
-
56
- # Causes a TestCase to act as a file test, by including FileMethods and
57
- # instantiating class_test_root (a Tap::Root). The root and directories
58
- # used by class_test_root may be specified as options.
59
- #
60
- # Note: by default acts_as_file_test determines a root directory
61
- # <em>based on the calling file</em>. Be sure to specify the root
62
- # directory manually if you call acts_as_file_test from a file that
63
- # isn't the test file.
64
- def acts_as_file_test(options={})
65
- include Tap::Test::FileMethods
66
-
67
- options = {
68
- :root => test_root_dir,
69
- :directories => {
70
- :input => 'input',
71
- :output => 'output',
72
- :expected => 'expected'}
73
- }.merge(options)
74
-
75
- self.class_test_root = Tap::Root.new(options[:root], options[:directories])
76
- end
77
-
78
- # Causes a unit test to act as a tap test -- resulting in the following:
79
- # - setup using acts_as_file_test
80
- # - inclusion of Tap::Test::SubsetMethods
81
- # - inclusion of Tap::Test::InstanceMethods
82
- #
83
- # Note: by default acts_as_tap_test determines a root directory
84
- # <em>based on the calling file</em>. Be sure to specify the root
85
- # directory manually if you call acts_as_file_test from a file that
86
- # isn't the test file.
87
- def acts_as_tap_test(options={})
88
- include Tap::Test::SubsetMethods
89
- include Tap::Test::FileMethods
90
- include Tap::Test::TapMethods
91
-
92
- acts_as_file_test({:root => test_root_dir}.merge(options))
93
- end
94
-
95
- def acts_as_script_test(options={})
96
- include Tap::Test::FileMethods
97
- include Tap::Test::ScriptMethods
98
-
99
- acts_as_file_test({:root => test_root_dir}.merge(options))
100
- end
101
-
102
- private
103
-
104
- # Infers the test root directory from the calling file.
105
- # 'some_class.rb' => 'some_class'
106
- # 'some_class_test.rb' => 'some_class'
107
- def test_root_dir # :nodoc:
108
- # caller[1] is considered the calling file (which should be the test case)
109
- # note that the output of calller.first is like:
110
- # ./path/to/file.rb:10
111
- # ./path/to/file.rb:10:in 'method'
112
- calling_file = caller[1].gsub(/:\d+(:in .*)?$/, "")
113
- calling_file.chomp(File.extname(calling_file)).chomp("_test")
114
- end
115
-
116
61
  end
117
62
  end
118
63
  end
119
64
  end
120
-
121
- module Tap
122
-
123
- # Modules facilitating testing. TapMethods are specific to
124
- # Tap, but SubsetMethods and FileMethods are more general in
125
- # their utility.
126
- module Test
127
- autoload(:SubsetMethods, 'tap/test/subset_methods')
128
- autoload(:FileMethods, 'tap/test/file_methods')
129
- autoload(:TapMethods, 'tap/test/tap_methods')
130
- autoload(:ScriptMethods, 'tap/test/script_methods')
131
- autoload(:Utils, 'tap/test/utils')
132
- end
133
- end
134
-
135
-
136
-
137
-
@@ -0,0 +1,38 @@
1
+ require 'tap/test/utils'
2
+
3
+ module Tap
4
+ module Test
5
+ module Assertions
6
+ def assert_output_equal(a, b, msg=nil)
7
+ a = a[1..-1] if a[0] == ?\n
8
+ if a == b
9
+ assert true
10
+ else
11
+ flunk %Q{
12
+ #{msg}
13
+ ==================== expected output ====================
14
+ #{Utils.whitespace_escape(a)}
15
+ ======================== but was ========================
16
+ #{Utils.whitespace_escape(b)}
17
+ =========================================================
18
+ }
19
+ end
20
+ end
21
+
22
+ def assert_alike(a, b, msg=nil)
23
+ if b =~ a
24
+ assert true
25
+ else
26
+ flunk %Q{
27
+ #{msg}
28
+ ================= expected output like ==================
29
+ #{Utils.whitespace_escape(a)}
30
+ ======================== but was ========================
31
+ #{Utils.whitespace_escape(b)}
32
+ =========================================================
33
+ }
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,78 @@
1
+ module Tap
2
+
3
+ # Modules facilitating testing. TapTest are specific to
4
+ # Tap, but SubsetTest and FileTest are more general in
5
+ # their utility.
6
+ module Test
7
+ autoload(:SubsetTest, 'tap/test/subset_test')
8
+ autoload(:FileTest, 'tap/test/file_test')
9
+ autoload(:TapTest, 'tap/test/tap_test')
10
+ autoload(:ScriptTest, 'tap/test/script_test')
11
+
12
+ module Extensions
13
+ def acts_as_subset_test
14
+ include Tap::Test::SubsetTest
15
+ end
16
+
17
+ # Causes a TestCase to act as a file test, by including FileTest and
18
+ # instantiating class_test_root (a Tap::Root). The root and directories
19
+ # used by class_test_root may be specified as options.
20
+ #
21
+ # Note: by default acts_as_file_test determines a root directory
22
+ # <em>based on the calling file</em>. Be sure to specify the root
23
+ # directory manually if you call acts_as_file_test from a file that
24
+ # isn't the test file.
25
+ def acts_as_file_test(options={})
26
+ include Tap::Test::FileTest
27
+
28
+ options = {
29
+ :root => test_root_dir,
30
+ :directories => {
31
+ :input => 'input',
32
+ :output => 'output',
33
+ :expected => 'expected'}
34
+ }.merge(options)
35
+
36
+ self.class_test_root = Tap::Root.new(options[:root], options[:directories])
37
+ end
38
+
39
+ # Causes a unit test to act as a tap test -- resulting in the following:
40
+ # - setup using acts_as_file_test
41
+ # - inclusion of Tap::Test::SubsetTest
42
+ # - inclusion of Tap::Test::InstanceMethods
43
+ #
44
+ # Note: by default acts_as_tap_test determines a root directory
45
+ # <em>based on the calling file</em>. Be sure to specify the root
46
+ # directory manually if you call acts_as_file_test from a file that
47
+ # isn't the test file.
48
+ def acts_as_tap_test(options={})
49
+ acts_as_subset_test
50
+ acts_as_file_test({:root => test_root_dir}.merge(options))
51
+
52
+ include Tap::Test::TapTest
53
+ end
54
+
55
+ def acts_as_script_test(options={})
56
+ acts_as_file_test({:root => test_root_dir}.merge(options))
57
+
58
+ include Tap::Test::ScriptTest
59
+ end
60
+
61
+ private
62
+
63
+ # Infers the test root directory from the calling file.
64
+ # 'some_class.rb' => 'some_class'
65
+ # 'some_class_test.rb' => 'some_class'
66
+ def test_root_dir # :nodoc:
67
+ # caller[1] is considered the calling file (which should be the test case)
68
+ # note that caller entries are like this:
69
+ # ./path/to/file.rb:10
70
+ # ./path/to/file.rb:10:in 'method'
71
+
72
+ calling_file = caller[1].gsub(/:\d+(:in .*)?$/, "")
73
+ calling_file.chomp(File.extname(calling_file)).chomp("_test")
74
+ end
75
+ end
76
+ end
77
+ end
78
+
@@ -1,19 +1,19 @@
1
- require 'tap/test/utils'
2
1
  require 'tap/test/env_vars'
3
- require 'tap/test/file_methods_class'
2
+ require 'tap/test/assertions'
3
+ require 'tap/test/regexp_escape'
4
+ require 'tap/test/file_test_class'
4
5
 
5
6
  module Tap
6
7
  module Test
7
8
 
8
-
9
- # FileMethods facilitates access and utilization of test-specific files and
10
- # directories. FileMethods provides each test method is setup with a Tap::Root
9
+ # FileTest facilitates access and utilization of test-specific files and
10
+ # directories. FileTest provides each test method is setup with a Tap::Root
11
11
  # (method_root) specific for the method, and defines a new assertion method
12
12
  # (assert_files) to facilitate tests which involve the production and/or
13
13
  # modification of files.
14
14
  #
15
- # [file_methods_doc_test.rb]
16
- # class FileMethodsDocTest < Test::Unit::TestCase
15
+ # [file_test_doc_test.rb]
16
+ # class FileTestDocTest < Test::Unit::TestCase
17
17
  # acts_as_file_test
18
18
  #
19
19
  # def test_something
@@ -56,13 +56,14 @@ module Tap
56
56
  # end
57
57
  #
58
58
  # See {Test::Unit::TestCase}[link:classes/Test/Unit/TestCase.html] and
59
- # FileMethodsClass for more information.
60
- module FileMethods
59
+ # FileTestClass for more information.
60
+ module FileTest
61
61
  include Tap::Test::EnvVars
62
+ include Tap::Test::Assertions
62
63
 
63
64
  def self.included(base)
64
65
  super
65
- base.extend FileMethodsClass
66
+ base.extend FileTestClass
66
67
  end
67
68
 
68
69
  # Convenience method to access the class_test_root.
@@ -121,13 +122,19 @@ module Tap
121
122
  # % rap test KEEP_FAILURES=true
122
123
  #
123
124
  # Be sure to call super when overriding this method.
124
- def teardown
125
+ def teardown
126
+ # check that method_root still exists (nil may
127
+ # indicate setup was overridden without super)
128
+ unless method_root
129
+ raise "teardown failure: method_root is nil"
130
+ end
131
+
125
132
  # clear out the output folder if it exists, unless flagged otherwise
126
133
  unless env("KEEP_OUTPUTS") || (!@test_passed && env("KEEP_FAILURES"))
127
134
  begin
128
135
  Utils.clear_dir(method_root[:output])
129
136
  rescue
130
- raise("teardown failure: could not remove output files")
137
+ raise("teardown failure: could not remove output files (#{$!.message})")
131
138
  end
132
139
  end
133
140
 
@@ -180,7 +187,7 @@ module Tap
180
187
  # Lets define a test that transforms input files into output files in a trivial
181
188
  # way, simply by replacing 'input' with 'output' in the file.
182
189
  #
183
- # class FileMethodsDocTest < Test::Unit::TestCase
190
+ # class FileTestDocTest < Test::Unit::TestCase
184
191
  # acts_as_file_test
185
192
  #
186
193
  # def test_sub
@@ -201,7 +208,7 @@ module Tap
201
208
  #
202
209
  # Now say you had some input and expected files for the 'test_sub' method:
203
210
  #
204
- # file_methods_doc/test_sub
211
+ # file_test_doc/test_sub
205
212
  # |- expected
206
213
  # | |- one.txt
207
214
  # | `- two.txt
@@ -290,7 +297,7 @@ module Tap
290
297
  # for more details).
291
298
  #
292
299
  # === Keeping Outputs
293
- # By default FileMethods sets teardown to cleans up the output directory. For
300
+ # By default FileTest sets teardown to cleans up the output directory. For
294
301
  # ease in debugging, ENV variable flags can be specified to keep all output
295
302
  # files (KEEP_OUTPUTS) or to keep the output files for just the tests that fail
296
303
  # (KEEP_FAILURES). These flags can be specified from the command line if you're
@@ -303,7 +310,42 @@ module Tap
303
310
  # TODO:
304
311
  # * add debugging information to indicate, for instance,
305
312
  # when dereferencing is going on.
306
- def assert_files(options={}) # :yields: input_files
313
+ def assert_files(options={}, &block) # :yields: input_files
314
+ transform_test(block, options) do |expected_file, output_file|
315
+ unless FileUtils.cmp(expected_file, output_file)
316
+ flunk "<#{expected_file}> not equal to\n<#{output_file}>"
317
+ end
318
+ end
319
+ end
320
+
321
+ def assert_files_alike(options={}, &block) # :yields: input_files
322
+ transform_test(block, options) do |expected_file, output_file|
323
+ regexp = RegexpEscape.new(File.read(expected_file))
324
+ str = File.read(output_file)
325
+ assert_alike(regexp, str, "<#{expected_file}> not equal to\n<#{output_file}>")
326
+ end
327
+ end
328
+
329
+ # The default assert_files options
330
+ def default_assert_files_options
331
+ {
332
+ :input_dir => method_root[:input],
333
+ :output_dir => method_root[:output],
334
+ :expected_dir => method_root[:expected],
335
+
336
+ :input_files => nil,
337
+ :expected_files => nil,
338
+ :include_input_directories => false,
339
+ :include_expected_directories => false,
340
+
341
+ :reference_dir => nil,
342
+ :reference_extname => '.ref'
343
+ }
344
+ end
345
+
346
+ private
347
+
348
+ def transform_test(block, options={}) # :yields: expected_files, output_files
307
349
  make_test_directories
308
350
 
309
351
  options = default_assert_files_options.merge(options)
@@ -342,7 +384,7 @@ module Tap
342
384
  end
343
385
 
344
386
  # get output files from the block, expand and sort
345
- output_files = [yield(input_files)].flatten.collect do |output_file|
387
+ output_files = [block.call(input_files)].flatten.collect do |output_file|
346
388
  File.expand_path(output_file)
347
389
  end.sort
348
390
 
@@ -356,32 +398,17 @@ module Tap
356
398
  errors = []
357
399
  Utils.each_pair(expected_files, output_files) do |expected_file, output_file|
358
400
  unless (File.directory?(expected_file) && File.directory?(output_file)) || FileUtils.cmp(expected_file, output_file)
359
- errors << "<#{expected_file}> not equal to\n<#{output_file}>"
401
+ begin
402
+ yield(expected_file, output_file)
403
+ rescue
404
+ errors << $!
405
+ end
360
406
  end
361
407
  end
362
408
  flunk "File compare failed:\n" + errors.join("\n") unless errors.empty?
363
409
  end
364
410
  end
365
411
 
366
- # The default assert_files options
367
- def default_assert_files_options
368
- {
369
- :input_dir => method_root[:input],
370
- :output_dir => method_root[:output],
371
- :expected_dir => method_root[:expected],
372
-
373
- :input_files => nil,
374
- :expected_files => nil,
375
- :include_input_directories => false,
376
- :include_expected_directories => false,
377
-
378
- :reference_dir => nil,
379
- :reference_extname => '.ref'
380
- }
381
- end
382
-
383
- private
384
-
385
412
  # utility method for method_tempfile; increments index until the
386
413
  # path base.indexext does not exist.
387
414
  def next_indexed_path(base, index, ext) # :nodoc:
@@ -1,8 +1,8 @@
1
1
  module Tap
2
2
  module Test
3
3
 
4
- # Class methods extending tests which include FileMethods.
5
- module FileMethodsClass
4
+ # Class methods extending tests which include FileTest.
5
+ module FileTestClass
6
6
 
7
7
  # The class-level test root (a Tap::Root).
8
8
  attr_accessor :class_test_root
@@ -0,0 +1,87 @@
1
+ require 'tap/test/utils'
2
+
3
+ module Tap
4
+ module Test
5
+
6
+ # RegexpEscape is a subclass of regexp that escapes all but the text in a
7
+ # special escape sequence. This allows the creation of complex regexps
8
+ # to match, for instance, console output.
9
+ #
10
+ # The RegexpEscape.escape (or equivalently the quote) method does the
11
+ # work; all regexp-active characters are escaped except for characters
12
+ # enclosed by ':.' and '.:' delimiters.
13
+ #
14
+ # RegexpEscape.escape('reg[exp]+ chars. are(quoted)') # => 'reg\[exp\]\+\ chars\.\ are\(quoted\)'
15
+ # RegexpEscape.escape('these are not: :.a(b*)c.:') # => 'these\ are\ not:\ a(b*)c'
16
+ #
17
+ # In addition, all-period regexps are automatically upgraded to '.*?';
18
+ # use the '.{n}' notation to specify n arbitrary characters.
19
+ #
20
+ # RegexpEscape.escape('_:..:_:...:_:....:') # => '_.*?_.*?_.*?'
21
+ # RegexpEscape.escape(':..{1}.:') # => '.{1}'
22
+ #
23
+ # RegexpEscape instances are initialized using the escaped input string
24
+ # and return the original string upon to_s.
25
+ #
26
+ # str = %q{
27
+ # a multiline
28
+ # :...:
29
+ # example}
30
+ # r = RegexpEscape.new(str)
31
+ #
32
+ # r =~ %q{
33
+ # a multiline
34
+ # matching
35
+ # example} # => true
36
+ #
37
+ # r !~ %q{
38
+ # a failing multiline
39
+ # example} # => true
40
+ #
41
+ # r.to_s # => str
42
+ #
43
+ class RegexpEscape < Regexp
44
+
45
+ # matches the escape sequence
46
+ ESCAPE_SEQUENCE = /:\..*?\.:/
47
+
48
+ class << self
49
+
50
+ # Escapes regexp-active characters in str, except for character
51
+ # delimited by ':.' and '.:'. See the class description for
52
+ # details.
53
+ def escape(str)
54
+ substituents = []
55
+ str.scan(ESCAPE_SEQUENCE) do
56
+ regexp_str = $&[2...-2]
57
+ regexp_str = ".*?" if regexp_str =~ /^\.*$/
58
+ substituents << regexp_str
59
+ end
60
+ substituents << ""
61
+
62
+ splits = str.split(ESCAPE_SEQUENCE).collect do |split|
63
+ super(split)
64
+ end
65
+ splits << "" if splits.empty?
66
+
67
+ splits.zip(substituents).to_a.flatten.join
68
+ end
69
+
70
+ # Same as escape.
71
+ def quote(str)
72
+ escape(str)
73
+ end
74
+ end
75
+
76
+ def initialize(str)
77
+ super(RegexpEscape.escape(str))
78
+ @original_str = str
79
+ end
80
+
81
+ # Returns the original string for self
82
+ def to_s
83
+ @original_str
84
+ end
85
+ end
86
+ end
87
+ end