tap-test 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,160 @@
1
+ require 'tap/root'
2
+ require 'fileutils'
3
+ require 'tempfile'
4
+ require 'tap/support/templater'
5
+
6
+ module Tap
7
+
8
+ module Test
9
+ module Utils
10
+ module_function
11
+
12
+ # Generates an array of [source, reference] pairs mapping source
13
+ # files to reference files under the source and reference dirs,
14
+ # respectively. Only files under source dir matching the pattern
15
+ # will be mapped. Mappings are either (in this order):
16
+ #
17
+ # - the path under reference_dir contained in the source file
18
+ # - a direct translation of the source file from the source to
19
+ # the reference dir, minus the extname
20
+ #
21
+ # Notes:
22
+ # - Source files may contain comments but should otherwise
23
+ # consist only of indentation (which is stripped) and
24
+ # the reference path.
25
+ # - If a mapped path cannot be found, dereference raises
26
+ # a DereferenceError.
27
+ #
28
+ # === example
29
+ #
30
+ # root
31
+ # |- input
32
+ # | |- dir.ref
33
+ # | |- ignored.txt
34
+ # | |- one.txt.ref
35
+ # | `- two.txt.ref
36
+ # `- ref
37
+ # |- dir
38
+ # |- one.txt
39
+ # `- path
40
+ # `- to
41
+ # `- two.txt
42
+ #
43
+ # The 'two.txt.ref' file contains a reference path:
44
+ #
45
+ # File.read('/root/input/two.txt.ref') # => 'path/to/two.txt'
46
+ #
47
+ # Now:
48
+ #
49
+ # reference_map('/root/input', '/root/ref')
50
+ # # => [
51
+ # # ['/root/input/dir.ref', '/root/ref/dir'],
52
+ # # ['/root/input/one.txt.ref', '/root/ref/one.txt'],
53
+ # # ['/root/input/two.txt.ref', '/root/ref/path/to/two.txt']]
54
+ #
55
+ # And since no path matches 'ignored.txt':
56
+ #
57
+ # reference_map('/root/input', '/root/ref', '**/*.txt')
58
+ # # !> DereferenceError
59
+ #
60
+ def reference_map(source_dir, reference_dir, pattern='**/*.ref')
61
+ Dir.glob(File.join(source_dir, pattern)).sort.collect do |source|
62
+ # use the path specified in the source file
63
+ relative_path = File.read(source).gsub(/#.*$/, "").strip
64
+
65
+ # use the relative filepath of the source file to the
66
+ # source dir (minus the extname) if no path is specified
67
+ if relative_path.empty?
68
+ relative_path = Tap::Root::Utils.relative_path(source_dir, source).chomp(File.extname(source))
69
+ end
70
+
71
+ reference = File.join(reference_dir, relative_path)
72
+
73
+ # raise an error if no reference file is found
74
+ unless File.exists?(reference)
75
+ raise DereferenceError, "no reference found for: #{source}"
76
+ end
77
+
78
+ [source, reference]
79
+ end
80
+ end
81
+
82
+ # Dereferences source files with reference files for the duration
83
+ # of the block. The mappings of source to reference files are
84
+ # determined using reference_map; dereferenced files are at the
85
+ # same location as the source files, but with the '.ref' extname
86
+ # removed.
87
+ #
88
+ # Notes:
89
+ # - The reference extname is implicitly specified in pattern;
90
+ # the final extname of the source file is removed during
91
+ # dereferencing regardless of what it is.
92
+ #
93
+ def dereference(source_dirs, reference_dir, pattern='**/*.ref', tempdir=Dir::tmpdir)
94
+ mapped_paths = []
95
+ begin
96
+ [*source_dirs].each do |source_dir|
97
+ reference_map(source_dir, reference_dir, pattern).each do |source, reference|
98
+
99
+ # move the source file to a temporary location
100
+ tempfile = Tempfile.new(File.basename(source), tempdir)
101
+ tempfile.close
102
+ FileUtils.mv(source, tempfile.path)
103
+
104
+ # copy the reference to the target
105
+ target = source.chomp(File.extname(source))
106
+ FileUtils.cp_r(reference, target)
107
+
108
+ mapped_paths << [target, source, tempfile]
109
+ end
110
+ end unless reference_dir == nil
111
+
112
+ yield
113
+
114
+ ensure
115
+ mapped_paths.each do |target, source, tempfile|
116
+ # remove the target and restore the original source file
117
+ FileUtils.rm_r(target) if File.exists?(target)
118
+ FileUtils.mv(tempfile.path, source)
119
+ end
120
+ end
121
+ end
122
+
123
+ # Uses a Tap::Support::Templater to template and replace the contents of path,
124
+ # for the duration of the block. The attributes will be available in the
125
+ # template context.
126
+ def template(paths, attributes={}, tempdir=Dir::tmpdir)
127
+ mapped_paths = []
128
+ begin
129
+ [*paths].each do |path|
130
+ # move the source file to a temporary location
131
+ tempfile = Tempfile.new(File.basename(path), tempdir)
132
+ tempfile.close
133
+ FileUtils.cp(path, tempfile.path)
134
+
135
+ # template the source file
136
+ content = File.read(path)
137
+ File.open(path, "wb") do |file|
138
+ file << Support::Templater.new(content, attributes).build
139
+ end
140
+
141
+ mapped_paths << [path, tempfile]
142
+ end
143
+
144
+ yield
145
+
146
+ ensure
147
+ mapped_paths.each do |path, tempfile|
148
+ # restore the original source file
149
+ FileUtils.rm(path) if File.exists?(path)
150
+ FileUtils.mv(tempfile.path, path)
151
+ end
152
+ end
153
+ end
154
+
155
+ # Raised when no reference can be found for a reference path.
156
+ class DereferenceError < StandardError
157
+ end
158
+ end
159
+ end
160
+ end
data/lib/tap/test.rb ADDED
@@ -0,0 +1,74 @@
1
+ require 'tap/root'
2
+
3
+ module Tap
4
+
5
+ # Tap::Test provides several convenience methods for including and
6
+ # setting up Tap::Test modules. The manual use of this module looks
7
+ # like this:
8
+ #
9
+ # class SampleTest < Test::Unit::TestCase
10
+ # extend Tap::Test
11
+ # acts_as_tap_test
12
+ # end
13
+ #
14
+ # The 'tap/test/unit' file performs this setup for Test::Unit
15
+ # (ruby < 1.9) and Mini::Test (ruby >= 1.9); simply require it and
16
+ # call the setup methods as necessary.
17
+ #
18
+ module Test
19
+ autoload(:SubsetTest, 'tap/test/subset_test')
20
+ autoload(:FileTest, 'tap/test/file_test')
21
+ autoload(:ShellTest, 'tap/test/shell_test')
22
+ autoload(:TapTest, 'tap/test/tap_test')
23
+ autoload(:Utils, 'tap/test/utils')
24
+
25
+ # Includes SubsetTest in the calling class.
26
+ def acts_as_subset_test
27
+ include Tap::Test::SubsetTest
28
+ end
29
+
30
+ # Includes FileTest in the calling class and instantiating class_test_root
31
+ # (a Tap::Root). Options may be used to configure the class_test_root.
32
+ #
33
+ # Note: by default acts_as_file_test determines a root directory
34
+ # <em>based on the calling file</em>. Be sure to specify the root
35
+ # directory manually if you call acts_as_file_test from a file that
36
+ # isn't the test file.
37
+ def acts_as_file_test(options={})
38
+ include Tap::Test::FileTest
39
+
40
+ options[:root] ||= test_root_dir
41
+ self.class_test_root = Tap::Root.new(options)
42
+ end
43
+
44
+ # Includes ShellTest in the calling class. Options are set as the default
45
+ # sh_test_options.
46
+ def acts_as_shell_test(options=nil)
47
+ include Tap::Test::ShellTest
48
+ self.sh_test_options = options
49
+ end
50
+
51
+ # Includes TapTest in the calling class and calls acts_as_file_test with
52
+ # the options.
53
+ def acts_as_tap_test(options={})
54
+ options[:root] ||= test_root_dir
55
+ acts_as_file_test(options)
56
+ include Tap::Test::TapTest
57
+ end
58
+
59
+ private
60
+
61
+ # Infers the test root directory from the calling file.
62
+ # 'some_class.rb' => 'some_class'
63
+ # 'some_class_test.rb' => 'some_class'
64
+ def test_root_dir # :nodoc:
65
+ # caller[1] is considered the calling file (which should be the test case)
66
+ # note that caller entries are like this:
67
+ # ./path/to/file.rb:10
68
+ # ./path/to/file.rb:10:in 'method'
69
+
70
+ calling_file = caller[1].gsub(/:\d+(:in .*)?$/, "")
71
+ calling_file.chomp(File.extname(calling_file)).chomp("_test")
72
+ end
73
+ end
74
+ end
data/tap.yml ADDED
File without changes
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tap-test
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Simon Chiang
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-05-25 00:00:00 -06:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: tap
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.17.0
24
+ version:
25
+ description:
26
+ email: simon.a.chiang@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - History
33
+ - README
34
+ - MIT-LICENSE
35
+ files:
36
+ - lib/tap/test.rb
37
+ - lib/tap/test/file_test.rb
38
+ - lib/tap/test/file_test/class_methods.rb
39
+ - lib/tap/test/shell_test.rb
40
+ - lib/tap/test/shell_test/class_methods.rb
41
+ - lib/tap/test/subset_test.rb
42
+ - lib/tap/test/subset_test/class_methods.rb
43
+ - lib/tap/test/tap_test.rb
44
+ - lib/tap/test/unit.rb
45
+ - lib/tap/test/utils.rb
46
+ - tap.yml
47
+ - History
48
+ - README
49
+ - MIT-LICENSE
50
+ has_rdoc: true
51
+ homepage: http://tap.rubyforge.org/tap-test/
52
+ post_install_message:
53
+ rdoc_options:
54
+ - --main
55
+ - README
56
+ - -S
57
+ - -N
58
+ - --title
59
+ - Tap-Test
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ version:
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: "0"
73
+ version:
74
+ requirements: []
75
+
76
+ rubyforge_project: tap
77
+ rubygems_version: 1.3.1
78
+ signing_key:
79
+ specification_version: 2
80
+ summary: Test modules for Tap
81
+ test_files: []
82
+