Module: Tap::Test::FileTest
- Includes:
- Assertions, EnvVars
- Defined in:
- lib/tap/test/file_test.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
See Test::Unit::TestCase and FileTestClass for more information.
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_alike(options = {}, &block) ⇒ Object
:yields: input_files.
-
#cleanup ⇒ Object
Cleans up the method_root.root directory by removing the class cleanup_dirs (by default :tmp and :output).
-
#ctr ⇒ Object
Convenience method to access the class_test_root.
-
#default_assert_files_options ⇒ Object
The default assert_files options.
-
#method_name_str ⇒ Object
Returns method_name as a string (Ruby 1.9 symbolizes method_name).
-
#setup ⇒ Object
Sets up method_root and calls cleanup.
-
#teardown ⇒ Object
Calls cleanup unless flagged otherwise by an ENV variable.
Methods included from Assertions
#assert_alike, #assert_output_equal
Methods included from EnvVars
Instance Attribute Details
Class Method Details
.included(base) ⇒ Object
:nodoc:
57 58 59 60 61 |
# File 'lib/tap/test/file_test.rb', line 57 def self.included(base) # :nodoc: super base.extend FileTestClass base.cleanup_dirs = [:output, :tmp] 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 |filepath|
input = File.read(filepath)
output_file = method_root.filepath(:output, File.basename(filepath))
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’ filepaths 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.filepath(: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).
Keeping Outputs
By default FileTest cleans up everything under method_root except the input and expected directories. For ease in debugging, ENV variable flags can be specified to prevent cleanup for all tests (KEEP_OUTPUTS) or just tests that fail (KEEP_FAILURES). These flags can be specified from the command line if you’re running the tests with rake or rap:
% rake test keep_outputs=true
% rap test keep_failures=true
– TODO:
-
add debugging information to indicate, for instance,
when dereferencing is going on.
263 264 265 266 267 268 269 |
# File 'lib/tap/test/file_test.rb', line 263 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_alike(options = {}, &block) ⇒ Object
:yields: input_files
271 272 273 274 275 276 277 |
# File 'lib/tap/test/file_test.rb', line 271 def assert_files_alike(={}, &block) # :yields: input_files transform_test(block, ) do |expected_file, output_file| regexp = RegexpEscape.new(File.read(expected_file)) str = File.read(output_file) assert_alike(regexp, str, "<#{expected_file}> not equal to\n<#{output_file}>") end end |
#cleanup ⇒ Object
Cleans up the method_root.root directory by removing the class cleanup_dirs (by default :tmp and :output). The root directory will also be removed if it is empty.
Override as necessary in subclasses.
86 87 88 89 90 91 |
# File 'lib/tap/test/file_test.rb', line 86 def cleanup self.class.cleanup_dirs.each do |dir| Utils.clear_dir(method_root[dir]) end Utils.try_remove_dir(method_root.root) end |
#ctr ⇒ Object
Convenience method to access the class_test_root.
64 65 66 |
# File 'lib/tap/test/file_test.rb', line 64 def ctr self.class.class_test_root end |
#default_assert_files_options ⇒ Object
The default assert_files options
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
# File 'lib/tap/test/file_test.rb', line 280 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 |
#method_name_str ⇒ Object
Returns method_name as a string (Ruby 1.9 symbolizes method_name)
122 123 124 |
# File 'lib/tap/test/file_test.rb', line 122 def method_name_str method_name.to_s end |
#setup ⇒ Object
Sets up method_root and calls cleanup. Be sure to call super when overriding this method.
75 76 77 78 79 |
# File 'lib/tap/test/file_test.rb', line 75 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. To prevent cleanup (when debugging for example), set the ‘KEEP_OUTPUTS’ or ‘KEEP_FAILURES’ ENV variables:
% rap test KEEP_OUTPUTS=true
% rap test KEEP_FAILURES=true
Cleanup is only suppressed for failing tests when KEEP_FAILURES is specified. Be sure to call super when overriding this method.
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/tap/test/file_test.rb', line 102 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" end # clear out the output folder if it exists, unless flagged otherwise unless env("KEEP_OUTPUTS") || (!passed? && env("KEEP_FAILURES")) begin cleanup rescue raise("cleanup failure: #{$!.}") end end Utils.try_remove_dir(ctr.root) end |