tap 0.11.1 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History +35 -1
- data/MIT-LICENSE +1 -1
- data/README +16 -15
- data/bin/tap +1 -1
- data/cmd/console.rb +4 -3
- data/cmd/manifest.rb +2 -2
- data/cmd/run.rb +12 -15
- data/doc/Class Reference +120 -117
- data/doc/Command Reference +27 -27
- data/doc/Syntax Reference +55 -111
- data/doc/Tutorial +69 -26
- data/lib/tap.rb +3 -8
- data/lib/tap/app.rb +122 -146
- data/lib/tap/constants.rb +2 -2
- data/lib/tap/env.rb +178 -252
- data/lib/tap/exe.rb +67 -30
- data/lib/tap/file_task.rb +224 -411
- data/lib/tap/generator/arguments.rb +13 -0
- data/lib/tap/generator/base.rb +112 -30
- data/lib/tap/generator/destroy.rb +36 -13
- data/lib/tap/generator/generate.rb +69 -48
- data/lib/tap/generator/generators/command/templates/command.erb +3 -3
- data/lib/tap/generator/generators/config/config_generator.rb +82 -10
- data/lib/tap/generator/generators/generator/generator_generator.rb +16 -6
- data/lib/tap/generator/generators/generator/templates/task.erb +2 -2
- data/lib/tap/generator/generators/generator/templates/test.erb +26 -0
- data/lib/tap/generator/generators/root/root_generator.rb +24 -13
- data/lib/tap/generator/generators/root/templates/Rakefile +4 -4
- data/lib/tap/generator/generators/root/templates/{tapfile → Rapfile} +6 -6
- data/lib/tap/generator/generators/root/templates/gemspec +0 -1
- data/lib/tap/generator/generators/task/task_generator.rb +3 -3
- data/lib/tap/generator/generators/task/templates/test.erb +1 -1
- data/lib/tap/generator/manifest.rb +7 -1
- data/lib/tap/generator/preview.rb +76 -0
- data/lib/tap/root.rb +222 -156
- data/lib/tap/spec.rb +41 -0
- data/lib/tap/support/aggregator.rb +25 -28
- data/lib/tap/support/audit.rb +278 -357
- data/lib/tap/support/constant.rb +2 -1
- data/lib/tap/support/constant_manifest.rb +28 -25
- data/lib/tap/support/dependency.rb +1 -1
- data/lib/tap/support/executable.rb +52 -183
- data/lib/tap/support/executable_queue.rb +50 -20
- data/lib/tap/support/gems.rb +1 -1
- data/lib/tap/support/intern.rb +0 -6
- data/lib/tap/support/join.rb +49 -83
- data/lib/tap/support/joins.rb +0 -3
- data/lib/tap/support/joins/switch.rb +13 -11
- data/lib/tap/support/joins/sync_merge.rb +25 -50
- data/lib/tap/support/manifest.rb +1 -0
- data/lib/tap/support/node.rb +140 -20
- data/lib/tap/support/parser.rb +56 -42
- data/lib/tap/support/schema.rb +183 -157
- data/lib/tap/support/templater.rb +9 -1
- data/lib/tap/support/versions.rb +39 -0
- data/lib/tap/task.rb +150 -177
- data/lib/tap/tasks/dump.rb +4 -4
- data/lib/tap/tasks/load.rb +29 -29
- data/lib/tap/test.rb +66 -53
- data/lib/tap/test/env_vars.rb +3 -3
- data/lib/tap/test/extensions.rb +11 -17
- data/lib/tap/test/file_test.rb +74 -132
- data/lib/tap/test/file_test_class.rb +4 -1
- data/lib/tap/test/regexp_escape.rb +2 -2
- data/lib/tap/test/script_test.rb +2 -2
- data/lib/tap/test/subset_test.rb +6 -6
- data/lib/tap/test/tap_test.rb +28 -154
- metadata +30 -51
- data/bin/rap +0 -118
- data/cgi/run.rb +0 -97
- data/lib/tap/declarations.rb +0 -229
- data/lib/tap/generator/generators/config/templates/doc.erb +0 -12
- data/lib/tap/generator/generators/config/templates/nodoc.erb +0 -8
- data/lib/tap/generator/generators/file_task/file_task_generator.rb +0 -27
- data/lib/tap/generator/generators/file_task/templates/file.txt +0 -11
- data/lib/tap/generator/generators/file_task/templates/result.yml +0 -6
- data/lib/tap/generator/generators/file_task/templates/task.erb +0 -33
- data/lib/tap/generator/generators/file_task/templates/test.erb +0 -29
- data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +0 -5
- data/lib/tap/patches/optparse/summarize.rb +0 -62
- data/lib/tap/support/assignments.rb +0 -173
- data/lib/tap/support/class_configuration.rb +0 -182
- data/lib/tap/support/combinator.rb +0 -125
- data/lib/tap/support/configurable.rb +0 -113
- data/lib/tap/support/configurable_class.rb +0 -271
- data/lib/tap/support/configuration.rb +0 -170
- data/lib/tap/support/gems/rake.rb +0 -111
- data/lib/tap/support/instance_configuration.rb +0 -173
- data/lib/tap/support/joins/fork.rb +0 -19
- data/lib/tap/support/joins/merge.rb +0 -22
- data/lib/tap/support/joins/sequence.rb +0 -21
- data/lib/tap/support/lazy_attributes.rb +0 -45
- data/lib/tap/support/lazydoc.rb +0 -386
- data/lib/tap/support/lazydoc/comment.rb +0 -503
- data/lib/tap/support/lazydoc/config.rb +0 -17
- data/lib/tap/support/lazydoc/definition.rb +0 -36
- data/lib/tap/support/lazydoc/document.rb +0 -152
- data/lib/tap/support/lazydoc/method.rb +0 -24
- data/lib/tap/support/tdoc.rb +0 -409
- data/lib/tap/support/tdoc/tdoc_html_generator.rb +0 -38
- data/lib/tap/support/tdoc/tdoc_html_template.rb +0 -42
- data/lib/tap/support/validation.rb +0 -479
- data/lib/tap/tasks/rake.rb +0 -57
data/lib/tap/tasks/dump.rb
CHANGED
@@ -11,9 +11,9 @@ module Tap
|
|
11
11
|
#
|
12
12
|
# % tap run -- [tasks] --+ dump FILEPATH
|
13
13
|
#
|
14
|
-
# See
|
14
|
+
# See Load for more details.
|
15
15
|
class Dump < Tap::FileTask
|
16
|
-
|
16
|
+
|
17
17
|
config :date_format, '%Y-%m-%d %H:%M:%S' # the date format
|
18
18
|
config :audit, true, &c.switch # include the audit trails
|
19
19
|
config :date, true, &c.switch # include a date
|
@@ -41,8 +41,8 @@ module Tap
|
|
41
41
|
app.aggregator.to_hash.each_pair do |src, _results|
|
42
42
|
next if filter && src.to_s !~ filter
|
43
43
|
|
44
|
-
results["#{src} (#{src.object_id})"] = _results.collect {|_audit| _audit.
|
45
|
-
_results.each {|_audit| trails << _audit.
|
44
|
+
results["#{src} (#{src.object_id})"] = _results.collect {|_audit| _audit.value }
|
45
|
+
_results.each {|_audit| trails << _audit.dump }
|
46
46
|
end
|
47
47
|
|
48
48
|
if audit
|
data/lib/tap/tasks/load.rb
CHANGED
@@ -1,27 +1,27 @@
|
|
1
|
-
module Tap
|
2
|
-
module Tasks
|
3
|
-
# :startdoc::manifest the default load task
|
4
|
-
#
|
5
|
-
# Load YAML-formatted data, as may be produced using Tap::Dump,
|
6
|
-
# and makes this data available for other tasks. Load is often
|
7
|
-
# used as a gateway task to other tasks.
|
8
|
-
#
|
9
|
-
# % tap run -- load FILEPATH --: [task]
|
1
|
+
module Tap
|
2
|
+
module Tasks
|
3
|
+
# :startdoc::manifest the default load task
|
10
4
|
#
|
11
|
-
# Load
|
12
|
-
#
|
13
|
-
#
|
5
|
+
# Load YAML-formatted data, as may be produced using Dump, and makes this
|
6
|
+
# data available for other tasks. Load is often used as a gateway task
|
7
|
+
# to other tasks.
|
8
|
+
#
|
9
|
+
# % tap run -- load FILEPATH --: [task]
|
10
|
+
#
|
11
|
+
# Load can select items from Hash or Array objects using one or more keys
|
12
|
+
# when only a subset is desired. By default items are selected using [].
|
13
|
+
# For more flexible selection, use match.
|
14
14
|
#
|
15
|
-
# Match converts each of the keys to a Regexp. For hashes, all
|
16
|
-
#
|
17
|
-
#
|
15
|
+
# Match converts each of the keys to a Regexp. For hashes, all values
|
16
|
+
# with a matching key will be selected. For arrays, any item matching
|
17
|
+
# a regexp will be selected.
|
18
18
|
#
|
19
|
-
# Use the flags to flatten, compact, sort (etc) results before
|
20
|
-
#
|
19
|
+
# Use the flags to flatten, compact, sort (etc) results before passing
|
20
|
+
# them on to the next task.
|
21
21
|
class Load < Tap::Task
|
22
22
|
|
23
23
|
config :match, false, :short => :m, &c.switch # match keys
|
24
|
-
config :flatten, false, :short => :f, &c.switch # flatten results
|
24
|
+
config :flatten, false, :short => :f, &c.switch # flatten results
|
25
25
|
config :compact, false, :short => :c, &c.switch # compact results
|
26
26
|
config :unique, false, :short => :u, &c.switch # uniq results
|
27
27
|
config :sort, false, :short => :s, &c.switch # sort results
|
@@ -54,13 +54,13 @@ module Tap
|
|
54
54
|
#
|
55
55
|
def process(input, *keys)
|
56
56
|
|
57
|
-
# load the input
|
58
|
-
obj = case input
|
57
|
+
# load the input
|
58
|
+
obj = case input
|
59
59
|
when StringIO, IO
|
60
|
-
YAML.load(input.read)
|
61
|
-
else
|
62
|
-
log :load, input
|
63
|
-
YAML.load_file(input)
|
60
|
+
YAML.load(input.read)
|
61
|
+
else
|
62
|
+
log :load, input
|
63
|
+
YAML.load_file(input)
|
64
64
|
end
|
65
65
|
|
66
66
|
# select results by key
|
@@ -87,7 +87,7 @@ module Tap
|
|
87
87
|
#puts results.inspect
|
88
88
|
#end
|
89
89
|
|
90
|
-
results
|
90
|
+
results
|
91
91
|
end
|
92
92
|
|
93
93
|
protected
|
@@ -106,7 +106,7 @@ module Tap
|
|
106
106
|
else
|
107
107
|
raise ArgumentError, "cannot match keys from a #{obj.class}"
|
108
108
|
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
data/lib/tap/test.rb
CHANGED
@@ -1,64 +1,77 @@
|
|
1
|
-
require 'test/unit'
|
2
1
|
$:.unshift File.expand_path("#{File.dirname(__FILE__)}/..")
|
3
2
|
require 'tap/test/extensions'
|
3
|
+
require 'test/unit'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
class TestCase
|
16
|
-
extend Tap::Test::Extensions
|
17
|
-
|
18
|
-
class << self
|
19
|
-
alias tap_original_test_case_inherited inherited
|
20
|
-
|
21
|
-
def inherited(child)
|
22
|
-
super
|
23
|
-
tap_original_test_case_inherited(child)
|
24
|
-
child.instance_variable_set(:@skip_messages, [])
|
25
|
-
child.instance_variable_set(:@run_test_suite, true)
|
26
|
-
end
|
27
|
-
|
28
|
-
# Indicates when the test suite should be run or skipped.
|
29
|
-
attr_accessor :run_test_suite
|
30
|
-
|
31
|
-
# An array of messages printed when a test is skipped
|
32
|
-
# by setting run_test_suite to false.
|
33
|
-
attr_reader :skip_messages
|
5
|
+
# :stopdoc:
|
6
|
+
# Methods extending TestCase. For more information see:
|
7
|
+
# - Tap::Test::SubsetTest
|
8
|
+
# - Tap::Test::FileTest
|
9
|
+
# - Tap::Test::TapTest
|
10
|
+
#
|
11
|
+
#--
|
12
|
+
#See the TestTutorial for more information.
|
13
|
+
class Test::Unit::TestCase
|
14
|
+
extend Tap::Test::Extensions
|
34
15
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
16
|
+
class << self
|
17
|
+
# Causes a test suite to be skipped. If a message is given, it will
|
18
|
+
# print and notify the user the test suite has been skipped.
|
19
|
+
def skip_test(msg=nil)
|
20
|
+
@@test_suites.delete(self)
|
21
|
+
puts "Skipping #{self}#{msg.empty? ? '' : ': ' + msg}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
39
25
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
26
|
+
class Test::Unit::TestCase
|
27
|
+
class << self
|
28
|
+
alias tap_original_test_case_inherited inherited
|
29
|
+
|
30
|
+
def inherited(child)
|
31
|
+
super
|
32
|
+
tap_original_test_case_inherited(child)
|
33
|
+
child.instance_variable_set(:@skip_messages, [])
|
34
|
+
child.instance_variable_set(:@run_test_suite, true)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Indicates when the test suite should be run or skipped.
|
38
|
+
attr_accessor :run_test_suite
|
39
|
+
|
40
|
+
# An array of messages printed when a test is skipped
|
41
|
+
# by setting run_test_suite to false.
|
42
|
+
attr_reader :skip_messages
|
43
|
+
|
44
|
+
undef_method :skip_test
|
45
|
+
|
46
|
+
def skip_test(msg=nil)
|
47
|
+
self.run_test_suite = false
|
48
|
+
skip_messages << msg
|
49
|
+
end
|
50
|
+
|
51
|
+
alias :original_suite :suite
|
44
52
|
|
45
|
-
|
53
|
+
# Modifies the default suite method to skip the suit unless
|
54
|
+
# run_test_suite is true. If the test is skipped, the skip_messages
|
55
|
+
# will be printed along with the default 'Skipping <Test>' message.
|
56
|
+
def suite # :nodoc:
|
57
|
+
if run_test_suite
|
58
|
+
original_suite
|
59
|
+
else
|
60
|
+
skip_message = skip_messages.compact.join(', ')
|
61
|
+
puts "Skipping #{name}#{skip_message.empty? ? '' : ': ' + skip_message}"
|
46
62
|
|
47
|
-
#
|
48
|
-
|
49
|
-
# will be printed along with the default 'Skipping <Test>' message.
|
50
|
-
def suite # :nodoc:
|
51
|
-
if run_test_suite
|
52
|
-
original_suite
|
53
|
-
else
|
54
|
-
skip_message = skip_messages.compact.join(', ')
|
55
|
-
puts "Skipping #{name}#{skip_message.empty? ? '' : ': ' + skip_message}"
|
56
|
-
|
57
|
-
# return an empty test suite of the appropriate name
|
58
|
-
Test::Unit::TestSuite.new(name)
|
59
|
-
end
|
60
|
-
end
|
63
|
+
# return an empty test suite of the appropriate name
|
64
|
+
Test::Unit::TestSuite.new(name)
|
61
65
|
end
|
62
66
|
end
|
63
67
|
end
|
68
|
+
end unless Object.const_defined?(:MiniTest)
|
69
|
+
|
70
|
+
if Object.const_defined?(:MiniTest)
|
71
|
+
# MiniTest renames method_name name, so it has to be added back here.
|
72
|
+
class MiniTest::Unit::TestCase
|
73
|
+
undef_method :method_name if method_defined?(:method_name)
|
74
|
+
alias method_name name
|
75
|
+
end
|
64
76
|
end
|
77
|
+
# :startdoc:
|
data/lib/tap/test/env_vars.rb
CHANGED
@@ -6,10 +6,10 @@ module Tap
|
|
6
6
|
|
7
7
|
# Access to the case-insensitive ENV variables. Raises an error
|
8
8
|
# if multiple case-insensitive values are defined in ENV.
|
9
|
-
def
|
9
|
+
def env_var(type)
|
10
10
|
type = type.downcase
|
11
11
|
|
12
|
-
# ruby 1.9 returns a hash instead of an array
|
12
|
+
# ENV.select in ruby 1.9 returns a hash instead of an array
|
13
13
|
selected = ENV.select {|key, value| key.downcase == type}.to_a
|
14
14
|
|
15
15
|
case selected.length
|
@@ -22,7 +22,7 @@ module Tap
|
|
22
22
|
|
23
23
|
# Returns true if the env_var(var) is set and matches /^true$/i
|
24
24
|
def env_true?(var)
|
25
|
-
(
|
25
|
+
(env_var(var) && env_var(var) =~ /^true$/i) ? true : false
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
data/lib/tap/test/extensions.rb
CHANGED
@@ -1,8 +1,4 @@
|
|
1
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
2
|
module Test
|
7
3
|
autoload(:SubsetTest, 'tap/test/subset_test')
|
8
4
|
autoload(:FileTest, 'tap/test/file_test')
|
@@ -16,8 +12,8 @@ module Tap
|
|
16
12
|
end
|
17
13
|
|
18
14
|
# Causes a TestCase to act as a file test, by including FileTest and
|
19
|
-
# instantiating class_test_root (a Tap::Root). The root
|
20
|
-
# used by class_test_root may be specified as options.
|
15
|
+
# instantiating class_test_root (a Tap::Root). The root, relative_paths,
|
16
|
+
# and absolute_paths used by class_test_root may be specified as options.
|
21
17
|
#
|
22
18
|
# Note: by default acts_as_file_test determines a root directory
|
23
19
|
# <em>based on the calling file</em>. Be sure to specify the root
|
@@ -26,15 +22,10 @@ module Tap
|
|
26
22
|
def acts_as_file_test(options={})
|
27
23
|
include Tap::Test::FileTest
|
28
24
|
|
29
|
-
|
30
|
-
:root
|
31
|
-
:
|
32
|
-
|
33
|
-
:output => 'output',
|
34
|
-
:expected => 'expected'}
|
35
|
-
}.merge(options)
|
36
|
-
|
37
|
-
self.class_test_root = Tap::Root.new(options[:root], options[:directories])
|
25
|
+
self.class_test_root = Tap::Root.new(
|
26
|
+
options[:root] || test_root_dir,
|
27
|
+
options[:relative_paths] || {},
|
28
|
+
options[:absolute_paths] || {})
|
38
29
|
end
|
39
30
|
|
40
31
|
# Causes a unit test to act as a tap test -- resulting in the following:
|
@@ -47,14 +38,17 @@ module Tap
|
|
47
38
|
# directory manually if you call acts_as_file_test from a file that
|
48
39
|
# isn't the test file.
|
49
40
|
def acts_as_tap_test(options={})
|
41
|
+
options[:root] ||= test_root_dir
|
42
|
+
|
50
43
|
acts_as_subset_test
|
51
|
-
acts_as_file_test(
|
44
|
+
acts_as_file_test(options)
|
52
45
|
|
53
46
|
include Tap::Test::TapTest
|
54
47
|
end
|
55
48
|
|
56
49
|
def acts_as_script_test(options={})
|
57
|
-
|
50
|
+
options[:root] ||= test_root_dir
|
51
|
+
acts_as_file_test(options)
|
58
52
|
|
59
53
|
include Tap::Test::ScriptTest
|
60
54
|
end
|
data/lib/tap/test/file_test.rb
CHANGED
@@ -7,7 +7,7 @@ module Tap
|
|
7
7
|
module Test
|
8
8
|
|
9
9
|
# FileTest facilitates access and utilization of test-specific files and
|
10
|
-
# directories. FileTest provides each test method
|
10
|
+
# directories. FileTest provides each test method 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.
|
@@ -25,32 +25,25 @@ module Tap
|
|
25
25
|
# method_root.root # => File.join(ctr.root, "/test_something")
|
26
26
|
# method_root[:input] # => File.join(ctr.root, "/test_something/input")
|
27
27
|
#
|
28
|
-
# # files in the output
|
29
|
-
# # and after each test; this passes each time the
|
28
|
+
# # files in the :output and :tmp directories are cleared
|
29
|
+
# # before and after each test; this passes each time the
|
30
30
|
# # test is run with no additional cleanup:
|
31
31
|
#
|
32
|
-
#
|
33
|
-
# assert !File.exists?(output_file)
|
32
|
+
# assert !File.exists?(method_root[:tmp])
|
34
33
|
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
# assert File.exists?(output_file)
|
34
|
+
# tmp_file = method_root.prepare(:tmp, 'sample.txt') {|file| file << "content" }
|
35
|
+
# assert_equal "content", File.read(tmp_file)
|
39
36
|
#
|
40
37
|
# # the assert_files method compares files produced
|
41
38
|
# # by the block the expected files, ensuring they
|
42
39
|
# # are the same (see the documentation for the
|
43
40
|
# # simplest use of assert_files)
|
44
41
|
#
|
45
|
-
# expected_file = method_root.
|
46
|
-
# File.open(expected_file, 'w') {|file| file << 'expected output' }
|
42
|
+
# expected_file = method_root.prepare(:expected, 'output.txt') {|file| file << 'expected output' }
|
47
43
|
#
|
48
44
|
# # passes
|
49
45
|
# assert_files do
|
50
|
-
#
|
51
|
-
# File.open(output_file, 'w') {|file| file << 'expected output' }
|
52
|
-
#
|
53
|
-
# output_file
|
46
|
+
# method_root.prepare(:output, 'output.txt') {|file| file << 'expected output' }
|
54
47
|
# end
|
55
48
|
# end
|
56
49
|
# end
|
@@ -61,136 +54,89 @@ module Tap
|
|
61
54
|
include Tap::Test::EnvVars
|
62
55
|
include Tap::Test::Assertions
|
63
56
|
|
64
|
-
def self.included(base)
|
57
|
+
def self.included(base) # :nodoc:
|
65
58
|
super
|
66
59
|
base.extend FileTestClass
|
60
|
+
base.cleanup_dirs = [:output, :tmp]
|
67
61
|
end
|
68
62
|
|
69
63
|
# Convenience method to access the class_test_root.
|
70
64
|
def ctr
|
71
|
-
self.class.class_test_root
|
72
|
-
end
|
73
|
-
|
74
|
-
# Creates the method_root.directories.
|
75
|
-
def make_test_directories
|
76
|
-
method_root.directories.values.each do |dir|
|
77
|
-
FileUtils.mkdir_p( method_root[dir] )
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
# Attempts to remove the method_root.directories, method_root.root,
|
82
|
-
# and ctr.root. Any given directory will not be removed unless empty.
|
83
|
-
def cleanup_test_directories
|
84
|
-
method_root.directories.values.each do |dir|
|
85
|
-
Utils.try_remove_dir(method_root[dir])
|
86
|
-
end
|
87
|
-
|
88
|
-
Utils.try_remove_dir(method_root.root)
|
89
|
-
Utils.try_remove_dir(ctr.root)
|
65
|
+
self.class.class_test_root or raise "setup failure: no class_test_root has been set for #{self.class}"
|
90
66
|
end
|
91
67
|
|
92
68
|
# The test-method-specific Tap::Root which may be used to
|
93
69
|
# access test files. method_root is a duplicate of ctr
|
94
|
-
# reconfigured so that method_root.root is ctr[
|
70
|
+
# reconfigured so that method_root.root is ctr[method_name.to_sym]
|
95
71
|
attr_reader :method_root
|
96
72
|
|
97
|
-
#
|
98
|
-
#
|
99
|
-
# directory.
|
100
|
-
attr_reader :method_tempfiles
|
101
|
-
|
102
|
-
# Sets up method_root and attempts to cleanup any left overs from a
|
103
|
-
# previous test (ie by deleting method_root[:output] and calling
|
104
|
-
# cleanup_test_directories). Be sure to call super when overriding
|
105
|
-
# this method.
|
73
|
+
# Sets up method_root and calls cleanup. Be sure to call super when
|
74
|
+
# overriding this method.
|
106
75
|
def setup
|
107
76
|
super
|
108
77
|
@method_root = ctr.dup.reconfigure(:root => ctr[method_name.to_sym])
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
78
|
+
cleanup
|
79
|
+
end
|
80
|
+
|
81
|
+
# Cleans up the method_root.root directory by removing the class
|
82
|
+
# cleanup_dirs (by default :tmp and :output). The root directory
|
83
|
+
# will also be removed if it is empty.
|
84
|
+
#
|
85
|
+
# Override as necessary in subclasses.
|
86
|
+
def cleanup
|
87
|
+
self.class.cleanup_dirs.each do |dir|
|
88
|
+
Utils.clear_dir(method_root[dir])
|
89
|
+
end
|
90
|
+
Utils.try_remove_dir(method_root.root)
|
113
91
|
end
|
114
92
|
|
115
|
-
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
# for failing tests, set the 'KEEP_OUTPUTS' or 'KEEP_FAILURES' ENV
|
119
|
-
# variables:
|
93
|
+
# Calls cleanup unless flagged otherwise by an ENV variable. To prevent
|
94
|
+
# cleanup (when debugging for example), set the 'KEEP_OUTPUTS' or
|
95
|
+
# 'KEEP_FAILURES' ENV variables:
|
120
96
|
#
|
121
97
|
# % rap test KEEP_OUTPUTS=true
|
122
98
|
# % rap test KEEP_FAILURES=true
|
123
99
|
#
|
124
|
-
#
|
100
|
+
# Cleanup is only suppressed for failing tests when KEEP_FAILURES is
|
101
|
+
# specified. Be sure to call super when overriding this method.
|
125
102
|
def teardown
|
126
103
|
# check that method_root still exists (nil may
|
127
104
|
# indicate setup was overridden without super)
|
128
105
|
unless method_root
|
129
|
-
raise "teardown failure: method_root is nil"
|
106
|
+
raise "teardown failure: method_root is nil (check a class_test_root has been set and ensure setup calls super)"
|
130
107
|
end
|
131
108
|
|
132
109
|
# clear out the output folder if it exists, unless flagged otherwise
|
133
|
-
unless
|
110
|
+
unless env_var("KEEP_OUTPUTS") || (!passed? && env_var("KEEP_FAILURES"))
|
134
111
|
begin
|
135
|
-
|
112
|
+
cleanup
|
136
113
|
rescue
|
137
|
-
raise("
|
114
|
+
raise("cleanup failure: #{$!.message}")
|
138
115
|
end
|
139
116
|
end
|
140
117
|
|
141
|
-
|
118
|
+
Utils.try_remove_dir(ctr.root)
|
142
119
|
end
|
143
120
|
|
144
121
|
# Returns method_name as a string (Ruby 1.9 symbolizes method_name)
|
145
122
|
def method_name_str
|
146
123
|
method_name.to_s
|
147
124
|
end
|
148
|
-
|
149
|
-
# Generates a temporary filepath formatted like "output_dir\filename.n.ext"
|
150
|
-
# where n is a counter that ensures the filepath is unique and non-existant
|
151
|
-
# (specificaly n is equal to the number of method_tempfiles generated
|
152
|
-
# by the current test, incremented as necessary to achieve a non-existant
|
153
|
-
# filepath).
|
154
|
-
#
|
155
|
-
# Unlike Tempfile, method_tempfile does not create the filepath unless a
|
156
|
-
# block is given, in which case an open File will be passed to the block.
|
157
|
-
# In addition, method_tempfiles are only cleaned up indirectly when the
|
158
|
-
# output directory is removed by teardown; this is both convenient for
|
159
|
-
# testing (when you may want a the file to persist, so you can debug it)
|
160
|
-
# and less enforcing than Tempfile.
|
161
|
-
#
|
162
|
-
# Notes:
|
163
|
-
# - by default filename is the calling method
|
164
|
-
# - the extension is chomped off the end of the filename
|
165
|
-
# - the directory for the file will be created if it does not exist
|
166
|
-
# - like all files in the output directory, tempfiles will be deleted by
|
167
|
-
# the default +teardown+ method
|
168
|
-
def method_tempfile(filename=method_name_str, &block)
|
169
|
-
ext = File.extname(filename)
|
170
|
-
basename = filename.chomp(ext)
|
171
|
-
path = next_indexed_path(method_root.filepath(:output, basename), method_tempfiles.length, ext)
|
172
|
-
dirname = File.dirname(path)
|
173
|
-
|
174
|
-
method_tempfiles << path
|
175
|
-
FileUtils.mkdir_p(dirname) unless File.exists?(dirname)
|
176
|
-
File.open(path, "w", &block) if block_given?
|
177
|
-
path
|
178
|
-
end
|
179
125
|
|
180
|
-
#
|
181
|
-
#
|
182
|
-
#
|
183
|
-
#
|
184
|
-
# are effectively ignored.
|
126
|
+
# Runs a file-based test that compares files created by the block with
|
127
|
+
# files in an expected directory. The block receives files from the
|
128
|
+
# input directory, and should return a list of files relative to the
|
129
|
+
# output directory. Only the files returned by the block are compared;
|
130
|
+
# additional files in the output directory are effectively ignored.
|
185
131
|
#
|
186
132
|
# === Example
|
187
|
-
# Lets define a test that transforms input files into output files in a
|
188
|
-
# way, simply by replacing 'input' with 'output' in the file.
|
133
|
+
# Lets define a test that transforms input files into output files in a
|
134
|
+
# trivial way, simply by replacing 'input' with 'output' in the file.
|
189
135
|
#
|
190
136
|
# class FileTestDocTest < Test::Unit::TestCase
|
191
137
|
# acts_as_file_test
|
192
138
|
#
|
193
|
-
# def
|
139
|
+
# def test_assert_files
|
194
140
|
# assert_files do |input_files|
|
195
141
|
# input_files.collect do |filepath|
|
196
142
|
# input = File.read(filepath)
|
@@ -206,9 +152,9 @@ module Tap
|
|
206
152
|
# end
|
207
153
|
# end
|
208
154
|
#
|
209
|
-
# Now say you had some input and expected files for
|
155
|
+
# Now say you had some input and expected files for test_assert_files:
|
210
156
|
#
|
211
|
-
# file_test_doc/
|
157
|
+
# file_test_doc/test_assert_files
|
212
158
|
# |- expected
|
213
159
|
# | |- one.txt
|
214
160
|
# | `- two.txt
|
@@ -229,20 +175,21 @@ module Tap
|
|
229
175
|
# test output 2
|
230
176
|
#
|
231
177
|
# When you run the test, the assert_files passes the input files to the
|
232
|
-
# block. When the block completes, assert_files compares the output
|
233
|
-
# returned by the block with the files in the expected directory.
|
234
|
-
# case, the files are equal and the test passes.
|
178
|
+
# block. When the block completes, assert_files compares the output
|
179
|
+
# files returned by the block with the files in the expected directory.
|
180
|
+
# In this case, the files are equal and the test passes.
|
235
181
|
#
|
236
182
|
# Say you changed the content of one of the expected files:
|
237
183
|
#
|
238
184
|
# [expected/one.txt]
|
239
185
|
# test flunk 1
|
240
186
|
#
|
241
|
-
# Now the test fails because the output files aren't equal to the
|
242
|
-
# files. The test
|
187
|
+
# Now the test fails because the output files aren't equal to the
|
188
|
+
# expected files. The test also fails if there are missing or extra
|
189
|
+
# files.
|
243
190
|
#
|
244
191
|
# === Options
|
245
|
-
# A variety of options
|
192
|
+
# A variety of options adjust the behavior of assert_files:
|
246
193
|
#
|
247
194
|
# :input_dir specify the directory to glob for input files
|
248
195
|
# (default method_root[:input])
|
@@ -258,15 +205,17 @@ module Tap
|
|
258
205
|
# expected-output file list comparison
|
259
206
|
# (by default dirs are excluded)
|
260
207
|
#
|
261
|
-
# assert_files will fail if <tt>:expected_files</tt> was not specified
|
262
|
-
# options and no files were found in <tt>:expected_dir</tt>. This
|
263
|
-
# to prevent silent false-positive results when you forget to
|
264
|
-
# in their place.
|
208
|
+
# assert_files will fail if <tt>:expected_files</tt> was not specified
|
209
|
+
# in the options and no files were found in <tt>:expected_dir</tt>. This
|
210
|
+
# check tries to prevent silent false-positive results when you forget to
|
211
|
+
# put expected files in their place.
|
265
212
|
#
|
266
213
|
# === File References
|
267
|
-
#
|
268
|
-
#
|
269
|
-
#
|
214
|
+
#
|
215
|
+
# Sometimes the same files will get used across multiple tests. To allow
|
216
|
+
# separate management of test files and prevent duplication, file
|
217
|
+
# references can be provided in place of test files. For instance, with a
|
218
|
+
# test directory like:
|
270
219
|
#
|
271
220
|
# method_root
|
272
221
|
# |- expected
|
@@ -279,8 +228,8 @@ module Tap
|
|
279
228
|
# |- one.txt
|
280
229
|
# `- two.txt
|
281
230
|
#
|
282
|
-
# The input and expected files (all references in this case) can be
|
283
|
-
# to the 'ref' filepaths like so:
|
231
|
+
# The input and expected files (all references in this case) can be
|
232
|
+
# dereferenced to the 'ref' filepaths like so:
|
284
233
|
#
|
285
234
|
# assert_files :reference_dir => method_root[:ref] do |input_files|
|
286
235
|
# input_files # => ['method_root/ref/one.txt', 'method_root/ref/two.txt']
|
@@ -292,16 +241,17 @@ module Tap
|
|
292
241
|
# end
|
293
242
|
# end
|
294
243
|
#
|
295
|
-
# Dereferencing occurs relative to the input_dir/expected_dir
|
296
|
-
# reference_dir must be specified for dereferencing to
|
297
|
-
# for more details).
|
244
|
+
# Dereferencing occurs relative to the input_dir/expected_dir
|
245
|
+
# configurations; a reference_dir must be specified for dereferencing to
|
246
|
+
# occur (see Utils.dereference for more details).
|
298
247
|
#
|
299
248
|
# === Keeping Outputs
|
300
|
-
#
|
301
|
-
#
|
302
|
-
#
|
303
|
-
#
|
304
|
-
#
|
249
|
+
#
|
250
|
+
# By default FileTest cleans up everything under method_root except the
|
251
|
+
# input and expected directories. For ease in debugging, ENV variable
|
252
|
+
# flags can be specified to prevent cleanup for all tests (KEEP_OUTPUTS)
|
253
|
+
# or just tests that fail (KEEP_FAILURES). These flags can be specified
|
254
|
+
# from the command line if you're running the tests with rake or rap:
|
305
255
|
#
|
306
256
|
# % rake test keep_outputs=true
|
307
257
|
# % rap test keep_failures=true
|
@@ -346,8 +296,6 @@ module Tap
|
|
346
296
|
private
|
347
297
|
|
348
298
|
def transform_test(block, options={}) # :yields: expected_files, output_files
|
349
|
-
make_test_directories
|
350
|
-
|
351
299
|
options = default_assert_files_options.merge(options)
|
352
300
|
input_dir = options[:input_dir]
|
353
301
|
output_dir = options[:output_dir]
|
@@ -409,12 +357,6 @@ module Tap
|
|
409
357
|
end
|
410
358
|
end
|
411
359
|
|
412
|
-
# utility method for method_tempfile; increments index until the
|
413
|
-
# path base.indexext does not exist.
|
414
|
-
def next_indexed_path(base, index, ext) # :nodoc:
|
415
|
-
path = sprintf('%s.%d%s', base, index, ext)
|
416
|
-
File.exists?(path) ? next_indexed_path(base, index + 1, ext) : path
|
417
|
-
end
|
418
360
|
end
|
419
361
|
end
|
420
362
|
end
|