Module: Tap::Test::FileTest
- Defined in:
- lib/tap/test/file_test.rb,
lib/tap/test/file_test/class_methods.rb
Overview
FileTest facilitates access and utilization of test-specific files and directories. FileTest provides each test method with a Tap::Root (method_root) specific for the method, and defines a new assertion method (assert_files) to facilitate tests which involve the production and/or modification of files.
[file_test_doc_test.rb]
class FileTestDocTest < Test::Unit::TestCase
acts_as_file_test
def test_something
# each test class has a class test root (ctr)
# and each test method has a method-specific
# root (method_root)
ctr.root # => File.expand_path(__FILE__.chomp('_test.rb'))
method_root.root # => File.join(ctr.root, "/test_something")
method_root[:input] # => File.join(ctr.root, "/test_something/input")
# files in the :output and :tmp directories are cleared
# before and after each test; this passes each time the
# test is run with no additional cleanup:
assert !File.exists?(method_root[:tmp])
tmp_file = method_root.prepare(:tmp, 'sample.txt') {|file| file << "content" }
assert_equal "content", File.read(tmp_file)
# the assert_files method compares files produced
# by the block the expected files, ensuring they
# are the same (see the documentation for the
# simplest use of assert_files)
expected_file = method_root.prepare(:expected, 'output.txt') {|file| file << 'expected output' }
# passes
assert_files do
method_root.prepare(:output, 'output.txt') {|file| file << 'expected output' }
end
end
end
Cleanup
By default the method_root directory is cleaned up at the end of the test, making FileTest very conveient for creating temporary test files. To prevent cleanup, either set the KEEP_OUTPUTS or KEEP_FAILURES ENV variable to ‘true’. The cleanup directories can be specified manually using cleanup_dirs class variable:
class LimitedCleanupTest < Test::Unit::TestCase
# only cleanup the method_root[:output] directory
acts_as_file_test :cleanup_dirs => [:output]
end
This technique is useful when you want to keep certain static files under version control, for instance.
Requirements
FileTest requires that a method_name method is provided by the including class, in order to properly set the directory for method_root. Test::Unit::TestCase satisfies this requirement already.
Defined Under Namespace
Modules: ClassMethods
Instance Attribute Summary collapse
-
#method_root ⇒ Object
readonly
The test-method-specific Tap::Root which may be used to access test files.
Class Method Summary collapse
-
.included(base) ⇒ Object
:nodoc:.
Instance Method Summary collapse
-
#assert_files(options = {}, &block) ⇒ Object
Runs a file-based test that compares files created by the block with files in an expected directory.
-
#assert_files_options ⇒ Object
The default assert_files options.
-
#cleanup ⇒ Object
Cleans up the method_root.root directory by removing the class cleanup_dirs (by default :root, ie the method_root directory itself).
-
#ctr ⇒ Object
Convenience method to access the class_test_root.
-
#setup ⇒ Object
Sets up method_root and calls cleanup.
-
#teardown ⇒ Object
Calls cleanup unless flagged otherwise by an ENV variable (see above).
Instance Attribute Details
#method_root ⇒ Object (readonly)
The test-method-specific Tap::Root which may be used to access test files. method_root is a duplicate of ctr reconfigured so that method_root.root is ctr
82 83 84 |
# File 'lib/tap/test/file_test.rb', line 82 def method_root @method_root end |
Class Method Details
.included(base) ⇒ Object
:nodoc:
73 74 75 76 77 |
# File 'lib/tap/test/file_test.rb', line 73 def self.included(base) # :nodoc: super base.extend FileTest::ClassMethods base.cleanup_dirs = [:root] end |
Instance Method Details
#assert_files(options = {}, &block) ⇒ Object
Runs a file-based test that compares files created by the block with files in an expected directory. The block receives files from the input directory, and should return a list of files relative to the output directory. Only the files returned by the block are compared; additional files in the output directory are effectively ignored.
Example
Lets define a test that transforms input files into output files in a trivial way, simply by replacing ‘input’ with ‘output’ in the file.
class FileTestDocTest < Test::Unit::TestCase
acts_as_file_test
def test_assert_files
assert_files do |input_files|
input_files.collect do |path|
input = File.read(path)
output_file = method_root.path(:output, File.basename(path))
File.open(output_file, "w") do |f|
f << input.gsub(/input/, "output")
end
output_file
end
end
end
end
Now say you had some input and expected files for test_assert_files:
file_test_doc/test_assert_files
|- expected
| |- one.txt
| `- two.txt
`- input
|- one.txt
`- two.txt
[input/one.txt]
test input 1
[input/two.txt]
test input 2
[expected/one.txt]
test output 1
[expected/two.txt]
test output 2
When you run the test, the assert_files passes the input files to the block. When the block completes, assert_files compares the output files returned by the block with the files in the expected directory. In this case, the files are equal and the test passes.
Say you changed the content of one of the expected files:
[expected/one.txt]
test flunk 1
Now the test fails because the output files aren’t equal to the expected files. The test also fails if there are missing or extra files.
Options
A variety of options adjust the behavior of assert_files:
:input_dir specify the directory to glob for input files
(default method_root[:input])
:output_dir specify the output directory
(default method_root[:output])
:expected_dir specify the directory to glob for expected files
(default method_root[:expected])
:input_files directly specify the input files for the block
:expected_files directly specify the expected files for comparison
:include_input_directories specifies directories to be included in the
input_files array (by default dirs are excluded)
:include_expected_directories specifies directories to be included in the
expected-output file list comparison
(by default dirs are excluded)
assert_files will fail if :expected_files
was not specified in the options and no files were found in :expected_dir
. This check tries to prevent silent false-positive results when you forget to put expected files in their place.
File References
Sometimes the same files will get used across multiple tests. To allow separate management of test files and prevent duplication, file references can be provided in place of test files. For instance, with a test directory like:
method_root
|- expected
| |- one.txt.ref
| `- two.txt.ref
|- input
| |- one.txt.ref
| `- two.txt.ref
`- ref
|- one.txt
`- two.txt
The input and expected files (all references in this case) can be dereferenced to the ‘ref’ paths like so:
assert_files :reference_dir => method_root[:ref] do |input_files|
input_files # => ['method_root/ref/one.txt', 'method_root/ref/two.txt']
input_files.collect do |input_file|
output_file = method_root.path(:output, File.basename(input_file)
FileUtils.cp(input_file, output_file)
output_file
end
end
Dereferencing occurs relative to the input_dir/expected_dir configurations; a reference_dir must be specified for dereferencing to occur (see Utils.dereference for more details).
– TODO:
-
add debugging information to indicate, for instance, when dereferencing is going on.
256 257 258 259 260 261 262 |
# File 'lib/tap/test/file_test.rb', line 256 def assert_files(={}, &block) # :yields: input_files transform_test(block, ) do |expected_file, output_file| unless FileUtils.cmp(expected_file, output_file) flunk "<#{expected_file}> not equal to\n<#{output_file}>" end end end |
#assert_files_options ⇒ Object
The default assert_files options
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/tap/test/file_test.rb', line 265 def { :input_dir => method_root[:input], :output_dir => method_root[:output], :expected_dir => method_root[:expected], :input_files => nil, :expected_files => nil, :include_input_directories => false, :include_expected_directories => false, :reference_dir => nil, :reference_extname => '.ref' } end |
#cleanup ⇒ Object
Cleans up the method_root.root directory by removing the class cleanup_dirs (by default :root, ie the method_root directory itself). The root directory will be removed if it is empty.
Override as necessary in subclasses.
97 98 99 100 101 102 |
# File 'lib/tap/test/file_test.rb', line 97 def cleanup self.class.cleanup_dirs.each do |dir| clear_dir(method_root[dir]) end try_remove_dir(method_root.root) end |
#ctr ⇒ Object
Convenience method to access the class_test_root.
126 127 128 |
# File 'lib/tap/test/file_test.rb', line 126 def ctr self.class.class_test_root or raise "setup failure: no class_test_root has been set for #{self.class}" end |
#setup ⇒ Object
Sets up method_root and calls cleanup. Be sure to call super when overriding this method.
86 87 88 89 90 |
# File 'lib/tap/test/file_test.rb', line 86 def setup super @method_root = ctr.dup.reconfigure(:root => ctr[method_name.to_sym]) cleanup end |
#teardown ⇒ Object
Calls cleanup unless flagged otherwise by an ENV variable (see above). Be sure to call super when overriding this method.
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/tap/test/file_test.rb', line 106 def teardown # check that method_root still exists (nil may # indicate setup was overridden without super) unless method_root raise "teardown failure: method_root is nil (does setup call super?)" end # clear out the output folder if it exists, unless flagged otherwise unless ENV["KEEP_OUTPUTS"] == "true" || (!passed? && ENV["KEEP_FAILURES"] == "true") begin cleanup rescue raise("cleanup failure: #{$!.}") end end try_remove_dir(ctr.root) end |