tap-test 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|