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.
- data/bin/rap +112 -0
- data/bin/tap +21 -10
- data/cmd/destroy.rb +1 -1
- data/cmd/generate.rb +1 -1
- data/cmd/run.rb +4 -48
- data/cmd/server.rb +3 -1
- data/lib/tap/constants.rb +1 -1
- data/lib/tap/env.rb +37 -39
- data/lib/tap/exe.rb +59 -29
- data/lib/tap/generator/base.rb +1 -1
- data/lib/tap/generator/generators/config/templates/doc.erb +1 -1
- data/lib/tap/generator/generators/file_task/templates/test.erb +1 -1
- data/lib/tap/generator/generators/root/templates/README +0 -0
- data/lib/tap/generator/generators/root/templates/gemspec +3 -4
- data/lib/tap/generator/generators/root/templates/tapfile +3 -3
- data/lib/tap/parser.rb +35 -0
- data/lib/tap/patches/optparse/summarize.rb +62 -0
- data/lib/tap/root.rb +24 -18
- data/lib/tap/support/class_configuration.rb +1 -1
- data/lib/tap/support/configurable_class.rb +3 -1
- data/lib/tap/support/configuration.rb +19 -0
- data/lib/tap/support/constant.rb +14 -2
- data/lib/tap/support/declarations.rb +33 -39
- data/lib/tap/support/dependable.rb +21 -2
- data/lib/tap/support/gems.rb +4 -30
- data/lib/tap/support/gems/rack.rb +14 -11
- data/lib/tap/support/lazy_attributes.rb +1 -1
- data/lib/tap/support/lazydoc.rb +257 -340
- data/lib/tap/support/lazydoc/comment.rb +499 -0
- data/lib/tap/support/lazydoc/config.rb +17 -0
- data/lib/tap/support/lazydoc/declaration.rb +20 -0
- data/lib/tap/support/lazydoc/document.rb +118 -0
- data/lib/tap/support/lazydoc/method.rb +24 -0
- data/lib/tap/support/manifest.rb +33 -4
- data/lib/tap/support/validation.rb +56 -0
- data/lib/tap/task.rb +46 -44
- data/lib/tap/tasks/dump.rb +15 -10
- data/lib/tap/tasks/load.rb +25 -0
- data/lib/tap/tasks/rake.rb +2 -2
- data/lib/tap/test.rb +55 -36
- data/lib/tap/test/file_methods.rb +204 -178
- data/lib/tap/test/file_methods_class.rb +4 -18
- data/lib/tap/test/script_methods.rb +76 -90
- data/lib/tap/test/script_methods/regexp_escape.rb +92 -0
- data/lib/tap/test/script_methods/script_test.rb +4 -2
- data/lib/tap/test/subset_methods.rb +46 -49
- data/lib/tap/test/subset_methods_class.rb +17 -54
- data/lib/tap/test/tap_methods.rb +1 -5
- data/lib/tap/test/utils.rb +142 -32
- metadata +12 -3
- data/lib/tap/support/command_line.rb +0 -55
- 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
|
-
#
|
6
|
-
attr_accessor :
|
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
|
-
#{
|
22
|
-
======================== but was ========================
|
23
|
-
#{
|
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
|
-
#{
|
39
|
-
=========================================================
|
40
|
-
}
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
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
|
-
#
|
8
|
-
#
|
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
|
-
#
|
13
|
-
#
|
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.
|
31
|
-
#
|
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
|
61
|
-
# to run specific tests. If you're running your test using Rake, ENV
|
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
|
-
# %
|
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-
|
74
|
-
#
|
75
|
-
#
|
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
|
-
# %
|
73
|
+
# % rap test BenchMark=true
|
79
74
|
#
|
80
75
|
# # runs all tests
|
81
|
-
# %
|
76
|
+
# % rap test all=true
|
82
77
|
#
|
83
|
-
#
|
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
|
-
|
95
|
-
|
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
|
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
|
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
|
130
|
-
# If no conditons are explicitly set, only runs if
|
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
|
145
|
-
def condition_test(*
|
146
|
-
|
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
|
-
#
|
155
|
-
# -
|
156
|
-
# -
|
157
|
-
# -
|
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
|
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
|
180
|
-
#
|
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
|
-
# %
|
179
|
+
# % rap test all=true
|
184
180
|
#
|
185
181
|
# # custom subset tests
|
186
|
-
# %
|
182
|
+
# % rap test custom=true
|
187
183
|
#
|
188
|
-
# # just test_one
|
189
|
-
#
|
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
|