tap-test 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History +5 -0
- data/MIT-LICENSE +22 -0
- data/README +123 -0
- data/lib/tap/test/file_test/class_methods.rb +17 -0
- data/lib/tap/test/file_test.rb +387 -0
- data/lib/tap/test/shell_test/class_methods.rb +24 -0
- data/lib/tap/test/shell_test.rb +208 -0
- data/lib/tap/test/subset_test/class_methods.rb +97 -0
- data/lib/tap/test/subset_test.rb +245 -0
- data/lib/tap/test/tap_test.rb +22 -0
- data/lib/tap/test/unit.rb +83 -0
- data/lib/tap/test/utils.rb +160 -0
- data/lib/tap/test.rb +74 -0
- data/tap.yml +0 -0
- metadata +82 -0
data/History
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2009, Regents of the University of Colorado.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
= {Tap Test}[http://tap.rubyforge.org/tap-test]
|
2
|
+
|
3
|
+
test v. to reveal the strengths or capabilities of something
|
4
|
+
|
5
|
+
Test modules for Tap.
|
6
|
+
|
7
|
+
== Description
|
8
|
+
|
9
|
+
Provides test modules to simplify testing of common Tap tasks, especially
|
10
|
+
tasks that require interaction with files. Modules are also provided to test
|
11
|
+
the shell behavior of executables and to define conditions for tests (ex
|
12
|
+
*nix/windows only). Tap-Test is not a testing framework. By default Tap-Test
|
13
|
+
integrates with Test::Unit and Mini::Test, but it is possible to include the
|
14
|
+
test modules into other test frameworks.
|
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
|
+
* Website[http://tap.rubyforge.org]
|
21
|
+
* Lighthouse[http://bahuvrihi.lighthouseapp.com/projects/9908-tap-task-application/tickets]
|
22
|
+
* Github[http://github.com/bahuvrihi/tap/tree/master]
|
23
|
+
* {Google Group}[http://groups.google.com/group/ruby-on-tap]
|
24
|
+
|
25
|
+
== Usage
|
26
|
+
|
27
|
+
The Tap-Test modules are small and targeted. More complete examples can be
|
28
|
+
found in the documentation, these are intended to show the point of each
|
29
|
+
module. To enable a module in Test::Unit or Mini::Test, require
|
30
|
+
'tap/test/unit' and simply call the acts_as_x_test method. Multiple modules
|
31
|
+
can be overlaid.
|
32
|
+
|
33
|
+
==== {FileTest}[link:classes/Tap/Test/FileTest.html] (acts_as_file_test)
|
34
|
+
|
35
|
+
Sets up a test-specific method_root for working with temporary files. Better
|
36
|
+
in most cases than using Tempfile because you can flag temporary files to be
|
37
|
+
saved on a failure (using ENV['KEEP_OUTPUTS']='true'). Also provides a new
|
38
|
+
assertion to test that all the files in an expected directory are equal to
|
39
|
+
those in an output directory.
|
40
|
+
|
41
|
+
require 'tap/test/unit'
|
42
|
+
class FileTestTest < Test::Unit::TestCase
|
43
|
+
acts_as_file_test
|
44
|
+
|
45
|
+
def test_method_root
|
46
|
+
assert_equal "test_method_root", File.basename(method_root.root)
|
47
|
+
|
48
|
+
path = method_root.prepare(:tmp, 'file.txt') {|io| io << 'content' }
|
49
|
+
assert_equal "content", File.read(path)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
==== {ShellTest}[link:classes/Tap/Test/ShellTest.html] (acts_as_shell_test)
|
54
|
+
|
55
|
+
Simple testing of shell commands.
|
56
|
+
|
57
|
+
require 'tap/test/unit'
|
58
|
+
class ShellTestTest < Test::Unit::TestCase
|
59
|
+
acts_as_shell_test :cmd_pattern => '% alias', :cmd => 'echo'
|
60
|
+
|
61
|
+
def test_echo
|
62
|
+
assert_equal "goodnight moon", sh("echo goodnight moon").strip
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_echo_with_an_alias
|
66
|
+
sh_test %q{
|
67
|
+
% alias goodnight moon
|
68
|
+
goodnight moon
|
69
|
+
}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
==== {SubsetTest}[link:classes/Tap/Test/SubsetTest.html] (acts_as_subset_test)
|
74
|
+
|
75
|
+
Allows in-file subsetting of tests into groups. Easy to get carried away with
|
76
|
+
this one, but handy, especially for platform-specific tests. Turn on a subset
|
77
|
+
or all tests using an ENV variable (ex ENV['ALL']='true').
|
78
|
+
|
79
|
+
require 'tap/test/unit'
|
80
|
+
class SubsetTestTest < Test::Unit::TestCase
|
81
|
+
acts_as_subset_test
|
82
|
+
|
83
|
+
condition(:windows) { match_platform?('mswin') }
|
84
|
+
|
85
|
+
def test_something_for_windows_only
|
86
|
+
condition_test(:windows) do
|
87
|
+
# ...
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_something_that_takes_forever
|
92
|
+
extended_test do
|
93
|
+
# ...
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
==== {TapTest}[link:classes/Tap/Test/TapTest.html] (acts_as_tap_test)
|
99
|
+
|
100
|
+
Sets up Tap::App.instance for testing tasks.
|
101
|
+
|
102
|
+
require 'tap/test/unit'
|
103
|
+
class TapTestTest < Test::Unit::TestCase
|
104
|
+
acts_as_tap_test
|
105
|
+
|
106
|
+
def test_task
|
107
|
+
t = Tap::Task.intern {|task| "result" }
|
108
|
+
assert_equal "result", t.process
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
== Installation
|
113
|
+
|
114
|
+
Tap-Test is available as a gem on RubyForge[http://rubyforge.org/projects/tap]. Use:
|
115
|
+
|
116
|
+
% gem install tap-test
|
117
|
+
|
118
|
+
== Info
|
119
|
+
|
120
|
+
Copyright (c) 2009, Regents of the University of Colorado.
|
121
|
+
Developer:: {Simon Chiang}[http://bahuvrihi.wordpress.com], {Biomolecular Structure Program}[http://biomol.uchsc.edu/], {Hansen Lab}[http://hsc-proteomics.uchsc.edu/hansenlab/]
|
122
|
+
Support:: CU Denver School of Medicine Deans Academic Enrichment Fund
|
123
|
+
License:: {MIT-Style}[link:files/MIT-LICENSE.html]
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Tap
|
2
|
+
module Test
|
3
|
+
module FileTest
|
4
|
+
|
5
|
+
# Class methods extending tests which include FileTest.
|
6
|
+
module ClassMethods
|
7
|
+
|
8
|
+
# The class-level test root (a Tap::Root)
|
9
|
+
attr_accessor :class_test_root
|
10
|
+
|
11
|
+
# An array of directories to be cleaned up by cleanup
|
12
|
+
attr_accessor :cleanup_dirs
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,387 @@
|
|
1
|
+
require 'tap/test/file_test/class_methods'
|
2
|
+
require 'tap/test/utils'
|
3
|
+
|
4
|
+
module Tap
|
5
|
+
module Test
|
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 method
|
10
|
+
# (assert_files) to facilitate tests which involve the production and/or
|
11
|
+
# 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
|
48
|
+
#
|
49
|
+
# FileTest requires that a method_name method is provided by the including
|
50
|
+
# class, in order to properly set the directory for method_root.
|
51
|
+
module FileTest
|
52
|
+
|
53
|
+
def self.included(base) # :nodoc:
|
54
|
+
super
|
55
|
+
base.extend FileTest::ClassMethods
|
56
|
+
base.cleanup_dirs = [:output, :tmp]
|
57
|
+
end
|
58
|
+
|
59
|
+
# The test-method-specific Tap::Root which may be used to
|
60
|
+
# access test files. method_root is a duplicate of ctr
|
61
|
+
# reconfigured so that method_root.root is ctr[method_name.to_sym]
|
62
|
+
attr_reader :method_root
|
63
|
+
|
64
|
+
# Sets up method_root and calls cleanup. Be sure to call super when
|
65
|
+
# overriding this method.
|
66
|
+
def setup
|
67
|
+
super
|
68
|
+
@method_root = ctr.dup.reconfigure(:root => ctr[method_name.to_sym])
|
69
|
+
cleanup
|
70
|
+
end
|
71
|
+
|
72
|
+
# Cleans up the method_root.root directory by removing the class
|
73
|
+
# cleanup_dirs (by default :tmp and :output). The root directory
|
74
|
+
# will also be removed if it is empty.
|
75
|
+
#
|
76
|
+
# Override as necessary in subclasses.
|
77
|
+
def cleanup
|
78
|
+
self.class.cleanup_dirs.each do |dir|
|
79
|
+
clear_dir(method_root[dir])
|
80
|
+
end
|
81
|
+
try_remove_dir(method_root.root)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Calls cleanup unless flagged otherwise by an ENV variable. To prevent
|
85
|
+
# cleanup (when debugging for example), set the 'KEEP_OUTPUTS' or
|
86
|
+
# 'KEEP_FAILURES' ENV variables:
|
87
|
+
#
|
88
|
+
# % rap test KEEP_OUTPUTS=true
|
89
|
+
# % rap test KEEP_FAILURES=true
|
90
|
+
#
|
91
|
+
# Cleanup is only suppressed for failing tests when KEEP_FAILURES is
|
92
|
+
# specified. Be sure to call super when overriding this method.
|
93
|
+
def teardown
|
94
|
+
# check that method_root still exists (nil may
|
95
|
+
# indicate setup was overridden without super)
|
96
|
+
unless method_root
|
97
|
+
raise "teardown failure: method_root is nil (does setup call super?)"
|
98
|
+
end
|
99
|
+
|
100
|
+
# clear out the output folder if it exists, unless flagged otherwise
|
101
|
+
unless ENV["KEEP_OUTPUTS"] == "true" || (!passed? && ENV["KEEP_FAILURES"] == "true")
|
102
|
+
begin
|
103
|
+
cleanup
|
104
|
+
rescue
|
105
|
+
raise("cleanup failure: #{$!.message}")
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
try_remove_dir(ctr.root)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Convenience method to access the class_test_root.
|
113
|
+
def ctr
|
114
|
+
self.class.class_test_root or raise "setup failure: no class_test_root has been set for #{self.class}"
|
115
|
+
end
|
116
|
+
|
117
|
+
# Runs a file-based test that compares files created by the block with
|
118
|
+
# files in an expected directory. The block receives files from the
|
119
|
+
# input directory, and should return a list of files relative to the
|
120
|
+
# output directory. Only the files returned by the block are compared;
|
121
|
+
# additional files in the output directory are effectively ignored.
|
122
|
+
#
|
123
|
+
# === Example
|
124
|
+
# Lets define a test that transforms input files into output files in a
|
125
|
+
# trivial way, simply by replacing 'input' with 'output' in the file.
|
126
|
+
#
|
127
|
+
# class FileTestDocTest < Test::Unit::TestCase
|
128
|
+
# acts_as_file_test
|
129
|
+
#
|
130
|
+
# def test_assert_files
|
131
|
+
# assert_files do |input_files|
|
132
|
+
# input_files.collect do |path|
|
133
|
+
# input = File.read(path)
|
134
|
+
# output_file = method_root.path(:output, File.basename(path))
|
135
|
+
#
|
136
|
+
# File.open(output_file, "w") do |f|
|
137
|
+
# f << input.gsub(/input/, "output")
|
138
|
+
# end
|
139
|
+
#
|
140
|
+
# output_file
|
141
|
+
# end
|
142
|
+
# end
|
143
|
+
# end
|
144
|
+
# end
|
145
|
+
#
|
146
|
+
# Now say you had some input and expected files for test_assert_files:
|
147
|
+
#
|
148
|
+
# file_test_doc/test_assert_files
|
149
|
+
# |- expected
|
150
|
+
# | |- one.txt
|
151
|
+
# | `- two.txt
|
152
|
+
# `- input
|
153
|
+
# |- one.txt
|
154
|
+
# `- two.txt
|
155
|
+
#
|
156
|
+
# [input/one.txt]
|
157
|
+
# test input 1
|
158
|
+
#
|
159
|
+
# [input/two.txt]
|
160
|
+
# test input 2
|
161
|
+
#
|
162
|
+
# [expected/one.txt]
|
163
|
+
# test output 1
|
164
|
+
#
|
165
|
+
# [expected/two.txt]
|
166
|
+
# test output 2
|
167
|
+
#
|
168
|
+
# When you run the test, the assert_files passes the input files to the
|
169
|
+
# block. When the block completes, assert_files compares the output
|
170
|
+
# files returned by the block with the files in the expected directory.
|
171
|
+
# In this case, the files are equal and the test passes.
|
172
|
+
#
|
173
|
+
# Say you changed the content of one of the expected files:
|
174
|
+
#
|
175
|
+
# [expected/one.txt]
|
176
|
+
# test flunk 1
|
177
|
+
#
|
178
|
+
# Now the test fails because the output files aren't equal to the
|
179
|
+
# expected files. The test also fails if there are missing or extra
|
180
|
+
# files.
|
181
|
+
#
|
182
|
+
# === Options
|
183
|
+
# A variety of options adjust the behavior of assert_files:
|
184
|
+
#
|
185
|
+
# :input_dir specify the directory to glob for input files
|
186
|
+
# (default method_root[:input])
|
187
|
+
# :output_dir specify the output directory
|
188
|
+
# (default method_root[:output])
|
189
|
+
# :expected_dir specify the directory to glob for expected files
|
190
|
+
# (default method_root[:expected])
|
191
|
+
# :input_files directly specify the input files for the block
|
192
|
+
# :expected_files directly specify the expected files for comparison
|
193
|
+
# :include_input_directories specifies directories to be included in the
|
194
|
+
# input_files array (by default dirs are excluded)
|
195
|
+
# :include_expected_directories specifies directories to be included in the
|
196
|
+
# expected-output file list comparison
|
197
|
+
# (by default dirs are excluded)
|
198
|
+
#
|
199
|
+
# assert_files will fail if <tt>:expected_files</tt> was not specified
|
200
|
+
# in the options and no files were found in <tt>:expected_dir</tt>. This
|
201
|
+
# check tries to prevent silent false-positive results when you forget to
|
202
|
+
# put expected files in their place.
|
203
|
+
#
|
204
|
+
# === File References
|
205
|
+
#
|
206
|
+
# Sometimes the same files will get used across multiple tests. To allow
|
207
|
+
# separate management of test files and prevent duplication, file
|
208
|
+
# references can be provided in place of test files. For instance, with a
|
209
|
+
# test directory like:
|
210
|
+
#
|
211
|
+
# method_root
|
212
|
+
# |- expected
|
213
|
+
# | |- one.txt.ref
|
214
|
+
# | `- two.txt.ref
|
215
|
+
# |- input
|
216
|
+
# | |- one.txt.ref
|
217
|
+
# | `- two.txt.ref
|
218
|
+
# `- ref
|
219
|
+
# |- one.txt
|
220
|
+
# `- two.txt
|
221
|
+
#
|
222
|
+
# The input and expected files (all references in this case) can be
|
223
|
+
# dereferenced to the 'ref' paths like so:
|
224
|
+
#
|
225
|
+
# assert_files :reference_dir => method_root[:ref] do |input_files|
|
226
|
+
# input_files # => ['method_root/ref/one.txt', 'method_root/ref/two.txt']
|
227
|
+
#
|
228
|
+
# input_files.collect do |input_file|
|
229
|
+
# output_file = method_root.path(:output, File.basename(input_file)
|
230
|
+
# FileUtils.cp(input_file, output_file)
|
231
|
+
# output_file
|
232
|
+
# end
|
233
|
+
# end
|
234
|
+
#
|
235
|
+
# Dereferencing occurs relative to the input_dir/expected_dir
|
236
|
+
# configurations; a reference_dir must be specified for dereferencing to
|
237
|
+
# occur (see Utils.dereference for more details).
|
238
|
+
#
|
239
|
+
# === Keeping Outputs
|
240
|
+
#
|
241
|
+
# By default FileTest cleans up everything under method_root except the
|
242
|
+
# input and expected directories. For ease in debugging, ENV variable
|
243
|
+
# flags can be specified to prevent cleanup for all tests (KEEP_OUTPUTS)
|
244
|
+
# or just tests that fail (KEEP_FAILURES). These flags can be specified
|
245
|
+
# from the command line if you're running the tests with rake or rap:
|
246
|
+
#
|
247
|
+
# % rake test keep_outputs=true
|
248
|
+
# % rap test keep_failures=true
|
249
|
+
#
|
250
|
+
#--
|
251
|
+
# TODO:
|
252
|
+
# * add debugging information to indicate, for instance,
|
253
|
+
# when dereferencing is going on.
|
254
|
+
def assert_files(options={}, &block) # :yields: input_files
|
255
|
+
transform_test(block, options) do |expected_file, output_file|
|
256
|
+
unless FileUtils.cmp(expected_file, output_file)
|
257
|
+
flunk "<#{expected_file}> not equal to\n<#{output_file}>"
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
# The default assert_files options
|
263
|
+
def assert_files_options
|
264
|
+
{
|
265
|
+
:input_dir => method_root[:input],
|
266
|
+
:output_dir => method_root[:output],
|
267
|
+
:expected_dir => method_root[:expected],
|
268
|
+
|
269
|
+
:input_files => nil,
|
270
|
+
:expected_files => nil,
|
271
|
+
:include_input_directories => false,
|
272
|
+
:include_expected_directories => false,
|
273
|
+
|
274
|
+
:reference_dir => nil,
|
275
|
+
:reference_extname => '.ref'
|
276
|
+
}
|
277
|
+
end
|
278
|
+
|
279
|
+
private
|
280
|
+
|
281
|
+
# Yields to the input block for each pair of entries in the input
|
282
|
+
# arrays. An error is raised if the input arrays do not have equal
|
283
|
+
# numbers of entries.
|
284
|
+
def each_pair(a, b, &block) # :yields: entry_a, entry_b,
|
285
|
+
each_pair_with_index(a,b) do |entry_a, entry_b, index|
|
286
|
+
yield(entry_a, entry_b)
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
# Same as each_pair but yields the index of the entries as well.
|
291
|
+
def each_pair_with_index(a, b, error_msg=nil, &block) # :yields: entry_a, entry_b, index
|
292
|
+
a = [a] unless a.kind_of?(Array)
|
293
|
+
b = [b] unless b.kind_of?(Array)
|
294
|
+
|
295
|
+
unless a.length == b.length
|
296
|
+
raise ArgumentError, (error_msg || "The input arrays must have an equal number of entries.")
|
297
|
+
end
|
298
|
+
|
299
|
+
0.upto(a.length-1) do |index|
|
300
|
+
yield(a[index], b[index], index)
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
# Attempts to recursively remove the specified method directory and all
|
305
|
+
# files within it. Raises an error if the removal does not succeed.
|
306
|
+
def clear_dir(dir)
|
307
|
+
# clear out the folder if it exists
|
308
|
+
FileUtils.rm_r(dir) if File.exists?(dir)
|
309
|
+
end
|
310
|
+
|
311
|
+
# Attempts to remove the specified directory. The root
|
312
|
+
# will not be removed if the directory does not exist, or
|
313
|
+
# is not empty.
|
314
|
+
def try_remove_dir(dir)
|
315
|
+
# Remove the directory if possible
|
316
|
+
begin
|
317
|
+
FileUtils.rmdir(dir) if File.exists?(dir) && Dir.glob(File.join(dir, "*")).empty?
|
318
|
+
rescue
|
319
|
+
# rescue cases where there is a hidden file, for example .svn
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
def transform_test(block, options={}) # :yields: expected_files, output_files
|
324
|
+
options = assert_files_options.merge(options)
|
325
|
+
input_dir = options[:input_dir]
|
326
|
+
output_dir = options[:output_dir]
|
327
|
+
expected_dir = options[:expected_dir]
|
328
|
+
|
329
|
+
reference_dir = options[:reference_dir]
|
330
|
+
reference_pattern = options[:reference_pattern]
|
331
|
+
|
332
|
+
Utils.dereference([input_dir, expected_dir], reference_dir, reference_pattern || '**/*.ref') do
|
333
|
+
|
334
|
+
# Get the input and expected files in this manner:
|
335
|
+
# - look for manually specified files
|
336
|
+
# - glob for files if none were specified
|
337
|
+
# - expand paths and sort
|
338
|
+
# - remove directories unless specified not to do so
|
339
|
+
input_files, expected_files = [:input, :expected].collect do |key|
|
340
|
+
files = options["#{key}_files".to_sym]
|
341
|
+
if files.nil?
|
342
|
+
pattern = File.join(options["#{key}_dir".to_sym], "**/*")
|
343
|
+
files = Dir.glob(pattern)
|
344
|
+
end
|
345
|
+
files = [files].flatten.collect {|file| File.expand_path(file) }.sort
|
346
|
+
|
347
|
+
unless options["include_#{key}_directories".to_sym]
|
348
|
+
files.delete_if {|file| File.directory?(file)}
|
349
|
+
end
|
350
|
+
|
351
|
+
files
|
352
|
+
end
|
353
|
+
|
354
|
+
# check at least one expected file was found
|
355
|
+
if expected_files.empty? && options[:expected_files] == nil
|
356
|
+
flunk "No expected files specified."
|
357
|
+
end
|
358
|
+
|
359
|
+
# get output files from the block, expand and sort
|
360
|
+
output_files = [*block.call(input_files)].collect do |output_file|
|
361
|
+
File.expand_path(output_file)
|
362
|
+
end.sort
|
363
|
+
|
364
|
+
# check that the expected and output paths are the same
|
365
|
+
translated_expected_files = expected_files.collect do |expected_file|
|
366
|
+
Tap::Root::Utils.translate(expected_file, expected_dir, output_dir)
|
367
|
+
end
|
368
|
+
assert_equal translated_expected_files, output_files, "Missing, extra, or unexpected output files"
|
369
|
+
|
370
|
+
# check that the expected and output file contents are equal
|
371
|
+
errors = []
|
372
|
+
each_pair(expected_files, output_files) do |expected_file, output_file|
|
373
|
+
unless (File.directory?(expected_file) && File.directory?(output_file)) || FileUtils.cmp(expected_file, output_file)
|
374
|
+
begin
|
375
|
+
yield(expected_file, output_file)
|
376
|
+
rescue
|
377
|
+
errors << $!
|
378
|
+
end
|
379
|
+
end
|
380
|
+
end
|
381
|
+
flunk "File compare failed:\n" + errors.join("\n") unless errors.empty?
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
end
|
386
|
+
end
|
387
|
+
end
|
@@ -0,0 +1,24 @@
|
|
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
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
# helper to retrieve class constants
|
18
|
+
def class_const(const_name) # :nodoc:
|
19
|
+
const_defined?(const_name) ? const_get(const_name) : nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|