bahuvrihi-tap 0.10.4 → 0.10.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/bin/rap +112 -0
  2. data/bin/tap +21 -10
  3. data/cmd/destroy.rb +1 -1
  4. data/cmd/generate.rb +1 -1
  5. data/cmd/run.rb +4 -48
  6. data/cmd/server.rb +3 -1
  7. data/lib/tap/constants.rb +1 -1
  8. data/lib/tap/env.rb +37 -39
  9. data/lib/tap/exe.rb +59 -29
  10. data/lib/tap/generator/base.rb +1 -1
  11. data/lib/tap/generator/generators/config/templates/doc.erb +1 -1
  12. data/lib/tap/generator/generators/file_task/templates/test.erb +1 -1
  13. data/lib/tap/generator/generators/root/templates/README +0 -0
  14. data/lib/tap/generator/generators/root/templates/gemspec +3 -4
  15. data/lib/tap/generator/generators/root/templates/tapfile +3 -3
  16. data/lib/tap/parser.rb +35 -0
  17. data/lib/tap/patches/optparse/summarize.rb +62 -0
  18. data/lib/tap/root.rb +24 -18
  19. data/lib/tap/support/class_configuration.rb +1 -1
  20. data/lib/tap/support/configurable_class.rb +3 -1
  21. data/lib/tap/support/configuration.rb +19 -0
  22. data/lib/tap/support/constant.rb +14 -2
  23. data/lib/tap/support/declarations.rb +33 -39
  24. data/lib/tap/support/dependable.rb +21 -2
  25. data/lib/tap/support/gems.rb +4 -30
  26. data/lib/tap/support/gems/rack.rb +14 -11
  27. data/lib/tap/support/lazy_attributes.rb +1 -1
  28. data/lib/tap/support/lazydoc.rb +257 -340
  29. data/lib/tap/support/lazydoc/comment.rb +499 -0
  30. data/lib/tap/support/lazydoc/config.rb +17 -0
  31. data/lib/tap/support/lazydoc/declaration.rb +20 -0
  32. data/lib/tap/support/lazydoc/document.rb +118 -0
  33. data/lib/tap/support/lazydoc/method.rb +24 -0
  34. data/lib/tap/support/manifest.rb +33 -4
  35. data/lib/tap/support/validation.rb +56 -0
  36. data/lib/tap/task.rb +46 -44
  37. data/lib/tap/tasks/dump.rb +15 -10
  38. data/lib/tap/tasks/load.rb +25 -0
  39. data/lib/tap/tasks/rake.rb +2 -2
  40. data/lib/tap/test.rb +55 -36
  41. data/lib/tap/test/file_methods.rb +204 -178
  42. data/lib/tap/test/file_methods_class.rb +4 -18
  43. data/lib/tap/test/script_methods.rb +76 -90
  44. data/lib/tap/test/script_methods/regexp_escape.rb +92 -0
  45. data/lib/tap/test/script_methods/script_test.rb +4 -2
  46. data/lib/tap/test/subset_methods.rb +46 -49
  47. data/lib/tap/test/subset_methods_class.rb +17 -54
  48. data/lib/tap/test/tap_methods.rb +1 -5
  49. data/lib/tap/test/utils.rb +142 -32
  50. metadata +12 -3
  51. data/lib/tap/support/command_line.rb +0 -55
  52. data/lib/tap/support/comment.rb +0 -270
@@ -1,26 +1,12 @@
1
1
  module Tap
2
2
  module Test
3
+
4
+ # Class methods extending tests which include FileMethods.
3
5
  module FileMethodsClass
4
6
 
5
- # Access the test root structure (a Tap::Root)
6
- attr_accessor :trs
7
+ # The class-level test root (a Tap::Root).
8
+ attr_accessor :class_test_root
7
9
 
8
- # Infers the test root directory from the calling file. Ex:
9
- # 'some_class.rb' => 'some_class'
10
- # 'some_class_test.rb' => 'some_class'
11
- def file_test_root
12
- # the calling file is not the direct caller of +method_root+... this method is
13
- # only accessed from within another method call, hence the target caller is caller[1]
14
- # rather than caller[0].
15
-
16
- # caller[1] is considered the calling file (which should be the test case)
17
- # note that the output of calller.first is like:
18
- # ./path/to/file.rb:10
19
- # ./path/to/file.rb:10:in 'method'
20
- calling_file = caller[1].gsub(/:\d+(:in .*)?$/, "")
21
- calling_file.chomp!("#{File.extname(calling_file)}")
22
- calling_file.chomp("_test")
23
- end
24
10
  end
25
11
  end
26
12
  end
@@ -1,90 +1,76 @@
1
- require 'tap/test/subset_methods'
2
- require 'tap/test/script_methods/script_test'
3
-
4
- module Tap
5
- module Test
6
- module ScriptMethods
7
-
8
- def self.included(base)
9
- super
10
- base.send(:include, Tap::Test::SubsetMethods)
11
- end
12
-
13
- def assert_output_equal(a, b, msg)
14
- a = a[1..-1] if a[0] == ?\n
15
- if a == b
16
- assert true
17
- else
18
- flunk %Q{
19
- #{msg}
20
- ==================== expected output ====================
21
- #{a.gsub(/\t/, "\\t").gsub(/\r\n/, "\\r\\n\n").gsub(/\n/, "\\n\n")}
22
- ======================== but was ========================
23
- #{b.gsub(/\t/, "\\t").gsub(/\r\n/, "\\r\\n\n").gsub(/\n/, "\\n\n")}
24
- =========================================================
25
- }
26
- end
27
- end
28
-
29
- def assert_alike(a, b, msg)
30
- if b =~ a
31
- assert true
32
- else
33
- flunk %Q{
34
- #{msg}
35
- ================= expected output like ==================
36
- #{a}
37
- ======================== but was ========================
38
- #{b.gsub(/\t/, "\\t").gsub(/\r\n/, "\\r\\n\n").gsub(/\n/, "\\n\n")}
39
- =========================================================
40
- }
41
- end
42
- end
43
-
44
- def with_argv(argv=[])
45
- current_argv = ARGV.dup
46
- begin
47
- ARGV.clear
48
- ARGV.concat(argv)
49
-
50
- yield
51
-
52
- ensure
53
- ARGV.clear
54
- ARGV.concat(current_argv)
55
- end
56
- end
57
-
58
- def default_command_path
59
- nil
60
- end
61
-
62
- def script_test(test_dir=method_root)
63
- subset_test("SCRIPT", "s") do
64
- cmd = ScriptTest.new(default_command_path)
65
- yield(cmd)
66
-
67
- Tap::Root.chdir(test_dir, true) do
68
- with_argv do
69
- puts "\n# == #{method_name}"
70
-
71
- cmd.run(env('stepwise')) do |expected, result, msg|
72
- case expected
73
- when String
74
- assert_output_equal(expected, result, msg)
75
- when Regexp
76
- assert_alike(expected, result, msg)
77
- end
78
- end
79
- end
80
- end
81
- end
82
- end
83
-
84
- end
85
- end
86
- end
87
-
88
-
89
-
90
-
1
+ require 'tap/test/subset_methods'
2
+ require 'tap/test/script_methods/script_test'
3
+
4
+ module Tap
5
+ module Test
6
+ module ScriptMethods
7
+
8
+ def self.included(base)
9
+ super
10
+ base.send(:include, Tap::Test::SubsetMethods)
11
+ end
12
+
13
+ def assert_output_equal(a, b, msg=nil)
14
+ a = a[1..-1] if a[0] == ?\n
15
+ if a == b
16
+ assert true
17
+ else
18
+ flunk %Q{
19
+ #{msg}
20
+ ==================== expected output ====================
21
+ #{Utils.whitespace_escape(a)}
22
+ ======================== but was ========================
23
+ #{Utils.whitespace_escape(b)}
24
+ =========================================================
25
+ }
26
+ end
27
+ end
28
+
29
+ def assert_alike(a, b, msg=nil)
30
+ if b =~ a
31
+ assert true
32
+ else
33
+ flunk %Q{
34
+ #{msg}
35
+ ================= expected output like ==================
36
+ #{a}
37
+ ======================== but was ========================
38
+ #{Utils.whitespace_escape(b)}
39
+ =========================================================
40
+ }
41
+ end
42
+ end
43
+
44
+ def default_command_path
45
+ nil
46
+ end
47
+
48
+ def script_test(test_dir=method_root.root)
49
+ subset_test("SCRIPT", "s") do
50
+ cmd = ScriptTest.new(default_command_path)
51
+ yield(cmd)
52
+
53
+ Tap::Root.chdir(test_dir, true) do
54
+ Utils.with_argv do
55
+ puts "\n# == #{method_name}"
56
+
57
+ cmd.run(env('stepwise')) do |expected, result, msg|
58
+ case expected
59
+ when String
60
+ assert_output_equal(expected, result, msg)
61
+ when Regexp
62
+ assert_alike(expected, result, msg)
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ end
71
+ end
72
+ end
73
+
74
+
75
+
76
+
@@ -0,0 +1,92 @@
1
+ require 'tap/test/utils'
2
+
3
+ module Tap
4
+ module Test
5
+ module ScriptMethods
6
+
7
+ # RegexpEscape is a subclass of regexp that escapes all but the text in a
8
+ # special escape sequence. This allows the creation of complex regexps
9
+ # to match, for instance, console output.
10
+ #
11
+ # The RegexpEscape.escape (or equivalently the quote) method does the
12
+ # work; all regexp-active characters are escaped except for characters
13
+ # enclosed by ':.' and '.:' delimiters.
14
+ #
15
+ # RegexpEscape.escape('reg[exp]+ chars. are(quoted)') # => 'reg\[exp\]\+\ chars\.\ are\(quoted\)'
16
+ # RegexpEscape.escape('these are not: :.a(b*)c.:') # => 'these\ are\ not:\ a(b*)c'
17
+ #
18
+ # In addition, all-period regexps are automatically upgraded to '.*?';
19
+ # use the '.{n}' notation to specify n arbitrary characters.
20
+ #
21
+ # RegexpEscape.escape('_:..:_:...:_:....:') # => '_.*?_.*?_.*?'
22
+ # RegexpEscape.escape(':..{1}.:') # => '.{1}'
23
+ #
24
+ # RegexpEscape instances are initialized using the escaped input string
25
+ # and format the original string upon to_s, to simplify their use in
26
+ # tests.
27
+ #
28
+ # r = RegexpEscape.new %q{
29
+ # a multiline
30
+ # :...:
31
+ # example}
32
+ #
33
+ # r =~ %q{
34
+ # a multiline
35
+ # matching
36
+ # example} # => true
37
+ #
38
+ # r !~ %q{
39
+ # a failing multiline
40
+ # example} # => true
41
+ #
42
+ # r.to_s
43
+ # # => %q{\n
44
+ # # a multiline\n
45
+ # # :...:\n
46
+ # # example}
47
+ #
48
+ class RegexpEscape < Regexp
49
+
50
+ # matches the escape sequence
51
+ ESCAPE_SEQUENCE = /:\..*?\.:/
52
+
53
+ class << self
54
+
55
+ # Escapes regexp-active characters in str, except for character
56
+ # delimited by ':.' and '.:'. See the class description for
57
+ # details.
58
+ def escape(str)
59
+ substituents = []
60
+ str.scan(ESCAPE_SEQUENCE) do
61
+ regexp_str = $&[2...-2]
62
+ regexp_str = ".*?" if regexp_str =~ /^\.*$/
63
+ substituents << regexp_str
64
+ end
65
+
66
+ splits = str.split(ESCAPE_SEQUENCE).collect do |split|
67
+ super(split)
68
+ end
69
+ splits << "" if splits.empty?
70
+ splits.zip(substituents).flatten.join
71
+ end
72
+
73
+ # Same as escape.
74
+ def quote(str)
75
+ escape(str)
76
+ end
77
+ end
78
+
79
+ def initialize(str)
80
+ super(RegexpEscape.escape(str))
81
+ @original_str = str
82
+ end
83
+
84
+ # Returns the original string for self, but with
85
+ # whitespace escaped as in Utils#whitespace_escape
86
+ def to_s
87
+ Utils.whitespace_escape(@original_str)
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -1,4 +1,5 @@
1
1
  require 'tap/support/shell_utils'
2
+ require 'tap/test/script_methods/regexp_escape'
2
3
 
3
4
  module Tap
4
5
  module Test
@@ -47,10 +48,11 @@ module Tap
47
48
  def time(msg, command)
48
49
  commands << [command, msg, nil, nil]
49
50
  end
50
-
51
- def check(msg, command, &validation)
51
+
52
+ def check(msg, command, use_regexp_escapes=true, &validation)
52
53
  new_commands = split(command)
53
54
  new_commands.each_with_index do |(cmd, expected), i|
55
+ expected = RegexpEscape.new(expected) if expected && use_regexp_escapes
54
56
  commands << [cmd, (new_commands.length > 1 ? "#{msg} (#{i})" : msg), expected, validation]
55
57
  end
56
58
  end
@@ -4,17 +4,11 @@ require 'tap/test/subset_methods_class'
4
4
  module Tap
5
5
  module Test
6
6
 
7
- # Ideally you always run all of your tests and they all run and pass everywhere. In
8
- # practice it's useful to suppress the execution of some tests -- long running tests,
9
- # tests specific for a given platform, or tests that depend on some condition, such
10
- # as the version of some optional third-party software your code interacts with.
7
+ # SubsetMethods provides methods to conditionally run tests, or to skip a
8
+ # test suite entirely.
11
9
  #
12
- # SubsetMethods extends TestCase with methods for defining conditions that can be
13
- # used to conditionally perform some action, or skip a test suite entirely. When
14
- # you include SubsetMethods within a specific TestCase, additional methods are
15
- # made available for filtering tests.
16
- #
17
- # require 'tap/test/subset_methods'
10
+ # require 'tap/test'
11
+ #
18
12
  # class Test::Unit::TestCase
19
13
  # # only true if running on windows
20
14
  # condition(:windows) { match_platform?('mswin') }
@@ -27,8 +21,9 @@ module Tap
27
21
  # skip_test unless satisfied?(:windows)
28
22
  # end
29
23
  #
30
- # WindowsOnlyTest will only run on a Windows platform. These conditions can be used
31
- # in specific tests, when only some tests need to be skipped.
24
+ # Here the WindowsOnlyTest will only run on a Windows platform. Conditions
25
+ # like these may be targeted at specific tests when only some tests need
26
+ # to be skipped.
32
27
  #
33
28
  # class RunOnlyAFewTest < Test::Unit::TestCase
34
29
  # include SubsetMethods
@@ -57,32 +52,31 @@ module Tap
57
52
  # end
58
53
  # end
59
54
  #
60
- # In the example, the ENV variables EXTENDED, BENCHMARK, and CUSTOM act as flags
61
- # to run specific tests. If you're running your test using Rake, ENV variables
62
- # can be set from the command line like so:
55
+ # In the example, the ENV variables EXTENDED, BENCHMARK, and CUSTOM act as
56
+ # flags to run specific tests. If you're running your test using Rake, ENV
57
+ # variables can be set from the command line like so:
63
58
  #
64
59
  # % rake test EXTENDED=true
65
60
  # % rake test BENCHMARK=true
66
61
  #
67
- # Since tap can run rake tasks as well, these are equivalent:
62
+ # Since tap and rap can run rake tasks as well, these are equivalent:
68
63
  #
69
64
  # % tap run test EXTENDED=true
70
- # % tap run test BENCHMARK=true
65
+ # % rap test BENCHMARK=true
71
66
  #
72
67
  # In so far as SubsetMethods is concerned, the environment variables are
73
- # case-insensitive. As in the example, additional ENV-variable-dependent
74
- # tests can be defined using the subset_test method. To run all tests that
75
- # get switched using an environment variable, set ALL=true.
68
+ # case-insensitive. As in the example, additional ENV-based tests can be
69
+ # defined using the subset_test method. To run all tests that get switched
70
+ # using an ENV variable, set ALL=true.
76
71
  #
77
72
  # # also runs benchmark tests
78
- # % tap run test BenchMark=true
73
+ # % rap test BenchMark=true
79
74
  #
80
75
  # # runs all tests
81
- # % tap run test all=true
76
+ # % rap test all=true
82
77
  #
83
- # === Class Methods
84
- #
85
- # See {Test::Unit::TestCase}[link:classes/Test/Unit/TestCase.html] for documentation of the class methods added by SubsetMethods
78
+ # See {Test::Unit::TestCase}[link:classes/Test/Unit/TestCase.html] and
79
+ # SubsetMethodsClass for more information.
86
80
  module SubsetMethods
87
81
  include Tap::Test::EnvVars
88
82
 
@@ -90,12 +84,14 @@ module Tap
90
84
  super
91
85
  base.extend SubsetMethodsClass
92
86
  end
93
-
94
- def satisfied?(*conditions)
95
- self.class.satisfied?(*conditions)
87
+
88
+ # Returns true if the specified conditions are satisfied.
89
+ def satisfied?(*condition_names)
90
+ self.class.satisfied?(*condition_names)
96
91
  end
97
92
 
98
- # Returns true if the subset type or 'ALL' is specified in ENV
93
+ # Returns true if the subset type (ex 'BENCHMARK') or 'ALL' is
94
+ # specified in ENV.
99
95
  def run_subset?(type)
100
96
  self.class.run_subset?(type)
101
97
  end
@@ -117,7 +113,7 @@ module Tap
117
113
  # platform_test('mswin') { ... }
118
114
  # end
119
115
  #
120
- # See TestCase#match_platform? for matching details.
116
+ # See SubsetMethodsClass#match_platform? for matching details.
121
117
  def platform_test(*platforms)
122
118
  if self.class.match_platform?(*platforms)
123
119
  yield
@@ -126,9 +122,9 @@ module Tap
126
122
  end
127
123
  end
128
124
 
129
- # Conditonal test. Only runs if the named conditions are satisfied.
130
- # If no conditons are explicitly set, only runs if all conditions
131
- # are satisfied.
125
+ # Conditonal test. Only runs if the specified conditions are satisfied.
126
+ # If no conditons are explicitly set, condition_test only runs if ALL
127
+ # conditions for the test are satisfied.
132
128
  #
133
129
  # condition(:is_true) { true }
134
130
  # condition(:is_false) { false }
@@ -141,23 +137,23 @@ module Tap
141
137
  # condition_test { # does not run }
142
138
  # end
143
139
  #
144
- # See TestCase#condition for more details.
145
- def condition_test(*conditions)
146
- unsatisfied_conditions = self.class.unsatisfied_conditions(*conditions)
147
- if unsatisfied_conditions.empty?
140
+ # See SubsetMethodsClass#condition for more details.
141
+ def condition_test(*condition_names)
142
+ if self.class.unsatisfied_conditions(*condition_names).empty?
148
143
  yield
149
144
  else
150
145
  print ' '
151
146
  end
152
147
  end
153
148
 
154
- # Basic method for a subset test. The provided block will run if:
155
- # - The subset type is specified in ENV
156
- # - The subset 'ALL' is specified in ENV
157
- # - The test method name matches the regexp provided in the <TYPE>_TEST ENV variable
149
+ # Defines a subset test. The provided block will only run if:
150
+ # - the subset type is specified in ENV
151
+ # - the subset 'ALL' is specified in ENV
152
+ # - the test method name matches the regexp provided in the
153
+ # <TYPE>_TEST ENV variable
158
154
  #
159
- # Otherwise the block will be skipped and +skip+ will be printed in the test output.
160
- # By default skip is the first letter of +type+.
155
+ # Otherwise the block will be skipped and +skip+ will be printed in the
156
+ # test output. By default skip is the first letter of +type+.
161
157
  #
162
158
  # For example, with these methods:
163
159
  #
@@ -176,17 +172,18 @@ module Tap
176
172
  # ENV['CUSTOM_TEST']=test_one test_one
177
173
  # ENV['CUSTOM']=nil no tests get run
178
174
  #
179
- # If you're running your tests with Rake, ENV variables can be set from the
180
- # command line, so you might use these command line statements:
175
+ # If you're running your tests with rake (or rap), ENV variables may be
176
+ # set from the command line.
181
177
  #
182
178
  # # all tests
183
- # % rake test all=true
179
+ # % rap test all=true
184
180
  #
185
181
  # # custom subset tests
186
- # % rake test custom=true
182
+ # % rap test custom=true
187
183
  #
188
- # # just test_one
189
- # % rake test custom_test=test_one
184
+ # # just test_one (it is the only test
185
+ # # matching the '.est_on.' pattern)
186
+ # % rap test custom_test=.est_on.
190
187
  #
191
188
  def subset_test(type, skip=type[0..0].downcase)
192
189
  type = type.upcase