Antwrap 0.5.0-java

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,12 @@
1
+ # antwrap
2
+ #
3
+ # Copyright Caleb Powell 2007
4
+ # Licensed under the LGPL, see the file COPYING in the distribution
5
+ #
6
+
7
+ https://rubyforge.org/projects/antwrap/
8
+
9
+ Questions?
10
+ Contact: caleb.powell@gmail.com
11
+
12
+ More documentation to come.
data/docs/index.html ADDED
@@ -0,0 +1,100 @@
1
+ <html><head><title>Antwrap - Invoke Ant tasks from your JRuby script!</title></head><body><ul>
2
+ <pre><li>Sample code of the Antwrap library looks like this;
3
+
4
+ <code lang="ruby">
5
+ #All options are optional. The defaults are as follows;
6
+ #{:name=&gt'', :basedir=&gt'.', :declarative=&gt true, :logger=&gt Logger.new(STDOUT), :loglevel=&gt Logger::DEBUG}
7
+ #so you can call AntProject.new() if you like.
8
+
9
+ @ant = AntProject.new({:name=&gt"FooProject",
10
+ :basedir=&gt current_dir,
11
+ :declarative=&gt true,
12
+ :logger=&gt Logger.new(STDOUT),
13
+ :loglevel=&gt Logger::DEBUG})
14
+
15
+ @ant.path(:id =&gt; "other.class.path"){
16
+ pathelement(:location =&gt; "classes")
17
+ pathelement(:location =&gt; "config")
18
+ }
19
+
20
+
21
+ @ant.path(:id =&gt; "common.class.path"){
22
+ fileset(:dir =&gt; "${common.dir}/lib"){
23
+ include(:name =&gt; "**/*.jar")
24
+ }
25
+ pathelement(:location =&gt; "${common.classes}")
26
+ }
27
+
28
+ @ant.javac(:srcdir =&gt; "test", :destdir =&gt; "classes"){
29
+ classpath(:refid =&gt; "common.class.path")
30
+ classpath(:refid =&gt; "foo.class.path")
31
+ }
32
+ </code>
33
+ </li>
34
+ </pre>
35
+
36
+ <pre><li>Alternatively, you can declare your Ant project to run in non-declarative mode, so that it only executes tasks
37
+ upon the invocation of the execute() method (this is a more Object Oriented approach, and may be useful in some
38
+ circumstances):
39
+
40
+ <code lang="ruby">
41
+ @ant = AntProject.new({:name=&gt"FooProject", :declarative=&gt false})
42
+
43
+ javac_task = @ant.javac(:srcdir =&gt; "test", :destdir =&gt; "classes"){
44
+ classpath(:refid =&gt; "common.class.path")
45
+ classpath(:refid =&gt; "foo.class.path")
46
+ }
47
+
48
+ javac_task.execute
49
+ </code>
50
+ </li>
51
+ </pre>
52
+
53
+ <pre><li>There are some reserved words that we have to work around. For example, Ant-Contrib tasks such as 'if' and 'else'
54
+ conflict with the Ruby reserved words. Under most circumstances, you won't need to use these tasks (indeed, the
55
+ awkwardness of conditional operations in Ant scripts is likely one of the reasons why you want to move to a build system
56
+ such as Rake). Nevertheless, there are that occasions demands it. Reserved words like this can be worked around by simply prepending an
57
+ underscore character ('_') to the task:
58
+
59
+ <code lang="ruby">
60
+ #This is an example of the Ant-Contrib tasks.
61
+ #note: I added an underscore to 'equals' even though it isn't a reserved word.
62
+ #This makes the code block more symmetrical (it's not required though). It also
63
+ #illustrates that you can apply an underscore to any task and it will be stripped by Antwrap.
64
+ @ant._if(){
65
+ _equals(:arg1 => "${bar}", :arg2 => "bar")
66
+ _then(){
67
+ echo(:message => "if 1 is equal")
68
+ }
69
+ _else(){
70
+ echo(:message => "if 1 is not equal")
71
+ }
72
+ }
73
+ </code>
74
+ </li>
75
+ </pre>
76
+
77
+ <pre><li>Content data is added via a 'pcdata' attribute:
78
+
79
+ <code lang="ruby">
80
+ @ant.echo(:pcdata =&gt; "&lt;foo&amp;bar&gt;")
81
+ </code>
82
+ </li>
83
+
84
+ <li>Antwrap includes a conversion script to take an existing Ant build file and convert it to a rake file. It will
85
+ convert each Ant Target into a JRake task. It will also convert each and every Any Task into an Antwrap method call.
86
+ Ant tasks that conflict with Ruby keywords are prepended with an
87
+ underscore (see above).
88
+
89
+ </li>
90
+ <li>Antwrap is a Beta release. I'd love any feedback you can provide on your experence with it.
91
+ There are no 3rd party jars required other than the Ant jar files in your JRuby Classpath.
92
+ </li></pre>
93
+
94
+ </ul>
95
+ Comments or Questions? <br>
96
+
97
+ Caleb Powell <br>
98
+ caleb.powell@gmail.com <br>
99
+
100
+ </body></html>
data/lib/antwrap.rb ADDED
@@ -0,0 +1,210 @@
1
+ # antwrap
2
+ #
3
+ # Copyright Caleb Powell 2007
4
+ #
5
+ # Licensed under the LGPL, see the file COPYING in the distribution
6
+ #
7
+
8
+ if(RUBY_PLATFORM == 'java')
9
+ require 'jruby_modules.rb'
10
+ else
11
+ require 'rjb_modules.rb'
12
+ end
13
+
14
+ class AntTask
15
+ private
16
+ @@task_stack = Array.new
17
+ attr_accessor(:unknown_element, :project, :taskname, :logger, :executed)
18
+
19
+ def create_unknown_element(project, taskname)
20
+
21
+ element = ApacheAnt::UnknownElement.new(taskname)
22
+ element.setProject(project)
23
+ element.setOwningTarget(ApacheAnt::Target.new())
24
+ element.setTaskName(taskname)
25
+
26
+ if(@project_wrapper.ant_version >= 1.6)
27
+ element.setTaskType(taskname)
28
+ element.setNamespace('')
29
+ element.setQName(taskname)
30
+ end
31
+
32
+ return element
33
+
34
+ end
35
+
36
+ def method_missing(sym, *args)
37
+ begin
38
+ @logger.debug("AntTask.method_missing sym[#{sym.to_s}]")
39
+ task = AntTask.new(sym.to_s, @project_wrapper, args[0], block_given? ? Proc.new : nil)
40
+ self.add(task)
41
+ rescue StandardError
42
+ @logger.error("AntTask.method_missing error:" + $!)
43
+ end
44
+ end
45
+
46
+ public
47
+ def initialize(taskname, antProject, attributes, proc)
48
+ taskname = taskname[1, taskname.length-1] if taskname[0,1] == "_"
49
+ @logger = antProject.logger
50
+ @taskname = taskname
51
+ @project_wrapper = antProject
52
+ @project = antProject.project()
53
+ @logger.debug(antProject.to_s)
54
+ @unknown_element = create_unknown_element(@project, taskname)
55
+ @logger.debug(to_s)
56
+
57
+ addAttributes(attributes)
58
+
59
+ if proc
60
+ # @logger.debug("task_stack.push #{taskname} >> #{@@task_stack}")
61
+ @@task_stack.push self
62
+
63
+ singleton_class = class << proc; self; end
64
+ singleton_class.module_eval{
65
+ def method_missing(m, *a, &proc)
66
+ @@task_stack.last().send(m, *a, &proc)
67
+ end
68
+ }
69
+ proc.instance_eval &proc
70
+ @@task_stack.pop
71
+ end
72
+
73
+ end
74
+
75
+
76
+ # Sets each attribute on the AntTask instance.
77
+ # :attributes - is a Hash.
78
+ def addAttributes(attributes)
79
+
80
+ return if attributes == nil
81
+
82
+ wrapper = ApacheAnt::RuntimeConfigurable.new(@unknown_element, @unknown_element.getTaskName());
83
+ outer_func = lambda{ |key, val, tfunc| key == 'pcdata' ? wrapper.addText(val) : tfunc.call(key, val) }
84
+
85
+ if(@project_wrapper.ant_version >= 1.6)
86
+ attributes.each do |key, val|
87
+ outer_func.call(key.to_s, val, lambda{|k,v| wrapper.setAttribute(k, val)})
88
+ end
89
+ else
90
+ @unknown_element.setRuntimeConfigurableWrapper(wrapper)
91
+ attribute_list = org.xml.sax.helpers.AttributeListImpl.new()
92
+ attributes.each do |key, val|
93
+ outer_func.call(key.to_s, val, lambda{|k,v| attribute_list.addAttribute(k, 'CDATA', v)})
94
+ end
95
+ wrapper.setAttributes(attribute_list)
96
+ end
97
+
98
+ end
99
+
100
+ #Add <em>child</em> as a child of this task.
101
+ def add(child)
102
+ # @logger.debug("adding child[#{child.taskname()}] to [#{@taskname}]")
103
+ @unknown_element.addChild(child.getUnknownElement())
104
+ @unknown_element.getRuntimeConfigurableWrapper().addChild(child.getUnknownElement().getRuntimeConfigurableWrapper())
105
+ end
106
+
107
+ def getUnknownElement
108
+ return @unknown_element
109
+ end
110
+ #Invokes the AntTask.
111
+ def execute
112
+ @unknown_element.maybeConfigure
113
+ @unknown_element.execute
114
+ @executed = true
115
+ end
116
+
117
+ def to_s
118
+ return self.class.name + "[#{@taskname}]"
119
+ end
120
+
121
+ end
122
+
123
+ class AntProject
124
+ require 'logger'
125
+ attr :project, false
126
+ attr :version, false
127
+ attr :ant_version, true
128
+ attr :declarative, true
129
+ attr :logger, true
130
+
131
+ # Create an AntProject. Parameters are specified via a hash:
132
+ # :name=><em>project_name</em>
133
+ # -A String indicating the name of this project. Corresponds to the
134
+ # 'name' attrbute on an Ant project.
135
+ # :basedir=><em>project_basedir</em>
136
+ # -A String indicating the basedir of this project. Corresponds to the 'basedir' attribute
137
+ # on an Ant project.
138
+ # :declarative=><em>declarative_mode</em>
139
+ # -A boolean value indicating wether Ant tasks created by this project instance should
140
+ # have their execute() method invoked during their creation. For example, with
141
+ # the option :declarative=>true the following task would execute;
142
+ # @antProject.echo(:message => "An Echo Task")
143
+ # However, with the option :declarative=>false, the programmer is required to execute the
144
+ # task explicitly;
145
+ # echoTask = @antProject.echo(:message => "An Echo Task")
146
+ # echoTask.execute()
147
+ # Default value is <em>true</em>.
148
+ # :logger=><em>Logger</em>
149
+ # -A Logger instance. Defaults to Logger.new(STDOUT)
150
+ # :loglevel=><em>The level to set the logger to</em>
151
+ # -Defaults to Logger::ERROR
152
+ def initialize(options=Hash.new)
153
+ @project= ApacheAnt::Project.new
154
+ @project.setName(options[:name] || '')
155
+ @project.setDefault('')
156
+ @project.setBasedir(options[:basedir] || '.')
157
+ @project.init
158
+ self.declarative= options[:declarative] || true
159
+ default_logger = ApacheAnt::DefaultLogger.new
160
+ default_logger.setMessageOutputLevel(2)
161
+ default_logger.setOutputPrintStream(options[:outputstr] || JavaLang::System.out)
162
+ default_logger.setErrorPrintStream(options[:errorstr] || JavaLang::System.err)
163
+ default_logger.setEmacsMode(false)
164
+ @project.addBuildListener(default_logger)
165
+ @version = ApacheAnt::Main.getAntVersion
166
+ @ant_version = @version[/\d\.\d\.\d/].to_f
167
+ @logger = options[:logger] || Logger.new(STDOUT)
168
+ @logger.level = options[:loglevel] || Logger::ERROR
169
+ @logger.debug(@version)
170
+ end
171
+
172
+ def create_task(taskname, attributes, proc)
173
+ @logger.debug("AntProject.create_task.taskname = " + taskname)
174
+ @logger.debug("AntProject.create_task.attributes = " + attributes.to_s)
175
+
176
+ task = AntTask.new(taskname, self, attributes, proc)
177
+ task.execute if declarative
178
+ return task
179
+ end
180
+
181
+ def method_missing(sym, *args)
182
+ begin
183
+ @logger.debug("AntProject.method_missing sym[#{sym.to_s}]")
184
+ return create_task(sym.to_s, args[0], block_given? ? Proc.new : nil)
185
+ rescue
186
+ @logger.error("Error instantiating task[#{sym.to_s}]" + $!)
187
+ end
188
+ end
189
+
190
+ #The Ant Project's name. Default is ''.
191
+ def name()
192
+ return @project.getName
193
+ end
194
+
195
+ #The Ant Project's basedir. Default is '.'.
196
+ def basedir()
197
+ return @project.getBaseDir().getAbsolutePath();
198
+ end
199
+
200
+ def to_s
201
+ return self.class.name + "[#{@project.getName()}]"
202
+ end
203
+
204
+ #This method invokes create_task. It is here to prevent conflicts wth the JRuby library
205
+ #over the 'java' symbol.
206
+ def java(attributes=Hash.new)
207
+ create_task('java', attributes, (block_given? ? Proc.new : nil))
208
+ end
209
+
210
+ end
@@ -0,0 +1,14 @@
1
+ module ApacheAnt
2
+ require 'java'
3
+ include_class "org.apache.tools.ant.DefaultLogger"
4
+ include_class "org.apache.tools.ant.Main"
5
+ include_class "org.apache.tools.ant.Project"
6
+ include_class "org.apache.tools.ant.RuntimeConfigurable"
7
+ include_class "org.apache.tools.ant.Target"
8
+ include_class "org.apache.tools.ant.UnknownElement"
9
+ end
10
+
11
+ module JavaLang
12
+ require 'java'
13
+ include_class "java.lang.System"
14
+ end
@@ -0,0 +1,16 @@
1
+ module ApacheAnt
2
+ require 'rubygems'
3
+ require 'rjb'
4
+ DefaultLogger = Rjb::import("org.apache.tools.ant.DefaultLogger")
5
+ Main = Rjb::import("org.apache.tools.ant.Main")
6
+ Project = Rjb::import("org.apache.tools.ant.Project")
7
+ RuntimeConfigurable = Rjb::import("org.apache.tools.ant.RuntimeConfigurable")
8
+ Target = Rjb::import("org.apache.tools.ant.Target")
9
+ UnknownElement = Rjb::import("org.apache.tools.ant.UnknownElement")
10
+ end
11
+
12
+ module JavaLang
13
+ require 'rubygems'
14
+ require 'rjb'
15
+ System = Rjb::import("java.lang.System")
16
+ end
@@ -0,0 +1,3 @@
1
+ Manifest-Version: 1.0
2
+ Created-By: 1.5.0_06 (Apple Computer, Inc.)
3
+
@@ -0,0 +1,260 @@
1
+ # antwrap
2
+ #
3
+ # Copyright Caleb Powell 2007
4
+ #
5
+ # Licensed under the LGPL, see the file COPYING in the distribution
6
+ #
7
+ require 'test/unit'
8
+ require 'fileutils'
9
+ $LOAD_PATH.push(ENV['PWD'] + '/lib')
10
+ require 'antwrap'
11
+ require 'logger'
12
+ #class TestStream < java.io.PrintStream
13
+ # attr_reader :last_line
14
+ #
15
+ # def initialise(out)
16
+ # self.super(out)
17
+ # end
18
+ #
19
+ # def println(s)
20
+ # puts "s"
21
+ # @last_line = s
22
+ # self.super(s)
23
+ # end
24
+ #
25
+ # def print(s)
26
+ # puts "s"
27
+ # @last_line = s
28
+ # self.super(s)
29
+ # end
30
+ #end
31
+ class TestAntwrap < Test::Unit::TestCase
32
+
33
+ def setup
34
+ @current_dir = ENV['PWD']
35
+ @ant_proj_props = {:name=>"testProject", :basedir=>@current_dir, :declarative=>true,
36
+ :logger=>Logger.new(STDOUT), :loglevel=>Logger::DEBUG}
37
+ @ant = AntProject.new(@ant_proj_props)
38
+ assert(@ant_proj_props[:name] == @ant.name())
39
+
40
+ assert(@ant_proj_props[:basedir] == @ant.basedir())
41
+ assert(@ant_proj_props[:declarative] == @ant.declarative())
42
+
43
+ @output_dir = @current_dir + '/test/output'
44
+ @resource_dir = @current_dir + '/test/test-resources'
45
+
46
+ if File.exists?(@output_dir)
47
+ FileUtils.remove_dir(@output_dir)
48
+ end
49
+ FileUtils.mkdir(@output_dir, :mode => 0775)
50
+ end
51
+
52
+ def test_antproject_init
53
+ @ant_proj_props = {:name=>"testProject", :declarative=>true,
54
+ :logger=>Logger.new(STDOUT), :loglevel=>Logger::ERROR}
55
+ ant_proj = AntProject.new(@ant_proj_props)
56
+ assert(@ant_proj_props[:name] == ant_proj.name())
57
+ assert(@current_dir == ant_proj.basedir())
58
+ assert(@ant_proj_props[:declarative] == ant_proj.declarative())
59
+ assert(@ant_proj_props[:logger] == ant_proj.logger())
60
+ end
61
+
62
+ def test_unzip_task
63
+ assert_absent @output_dir + '/parent/FooBarParent.class'
64
+ task = @ant.unzip(:src => @resource_dir + '/parent.jar',
65
+ :dest => @output_dir)
66
+
67
+ assert_exists @output_dir + '/parent/FooBarParent.class'
68
+ end
69
+
70
+ def test_copyanddelete_task
71
+ file = @output_dir + '/foo.txt'
72
+ assert_absent file
73
+ @ant.copy(:file => @resource_dir + '/foo.txt',
74
+ :todir => @output_dir)
75
+ assert_exists file
76
+
77
+ @ant.delete(:file => file)
78
+ assert_absent file
79
+ end
80
+
81
+ def test_javac_task
82
+ FileUtils.mkdir(@output_dir + '/classes', :mode => 0775)
83
+
84
+ assert_absent @output_dir + '/classes/foo/bar/FooBar.class'
85
+
86
+ @ant.javac(:srcdir => @resource_dir + '/src',
87
+ :destdir => @output_dir + '/classes',
88
+ :debug => 'on',
89
+ :verbose => 'no',
90
+ :fork => 'no',
91
+ :failonerror => 'yes',
92
+ :includes => 'foo/bar/**',
93
+ :excludes => 'foo/bar/baz/**',
94
+ :classpath => @resource_dir + '/parent.jar')
95
+
96
+ assert_exists @output_dir + '/classes/foo/bar/FooBar.class'
97
+ assert_absent @output_dir + '/classes/foo/bar/baz/FooBarBaz.class'
98
+ end
99
+
100
+ def test_javac_task_with_property
101
+ FileUtils.mkdir(@output_dir + '/classes', :mode => 0775)
102
+
103
+ assert_absent @output_dir + '/classes/foo/bar/FooBar.class'
104
+ @ant.property(:name => 'pattern', :value => '**/*.jar')
105
+ @ant.property(:name => 'resource_dir', :value => @resource_dir)
106
+ @ant.path(:id => 'common.class.path'){
107
+ fileset(:dir => '${resource_dir}'){
108
+ include(:name => '${pattern}')
109
+ }
110
+ }
111
+
112
+ @ant.javac(:srcdir => @resource_dir + '/src',
113
+ :destdir => @output_dir + '/classes',
114
+ :debug => 'on',
115
+ :verbose => 'yes',
116
+ :fork => 'no',
117
+ :failonerror => 'yes',
118
+ :includes => 'foo/bar/**',
119
+ :excludes => 'foo/bar/baz/**',
120
+ :classpathref => 'common.class.path')
121
+
122
+ assert_exists @output_dir + '/classes/foo/bar/FooBar.class'
123
+ assert_absent @output_dir + '/classes/foo/bar/baz/FooBarBaz.class'
124
+ end
125
+
126
+ def test_jar_task
127
+ assert_absent @output_dir + '/Foo.jar'
128
+ @ant.property(:name => 'outputdir', :value => @output_dir)
129
+ @ant.property(:name => 'destfile', :value => '${outputdir}/Foo.jar')
130
+ @ant.jar( :destfile => "${destfile}",
131
+ :basedir => @resource_dir + '/src',
132
+ :duplicate => 'preserve')
133
+
134
+ assert_exists @output_dir + '/Foo.jar'
135
+ end
136
+
137
+ def test_java_task
138
+
139
+ return if @ant.ant_version < 1.7
140
+
141
+ FileUtils.mkdir(@output_dir + '/classes', :mode => 0775)
142
+ @ant.javac(:srcdir => @resource_dir + '/src',
143
+ :destdir => @output_dir + '/classes',
144
+ :debug => 'on',
145
+ :verbose => 'no',
146
+ :fork => 'no',
147
+ :failonerror => 'yes',
148
+ :includes => 'foo/bar/**',
149
+ :excludes => 'foo/bar/baz/**',
150
+ :classpath => @resource_dir + '/parent.jar')
151
+
152
+ @ant.property(:name => 'output_dir', :value => @output_dir)
153
+ @ant.property(:name => 'resource_dir', :value =>@resource_dir)
154
+ @ant.java(:classname => 'foo.bar.FooBar', :fork => 'false') {
155
+ arg(:value => 'argOne')
156
+ classpath(){
157
+ pathelement(:location => '${output_dir}/classes')
158
+ pathelement(:location => '${resource_dir}/parent.jar')
159
+ }
160
+ arg(:value => 'argTwo')
161
+ jvmarg(:value => 'client')
162
+ sysproperty(:key=> 'antwrap', :value => 'coolio')
163
+ }
164
+ end
165
+
166
+ def test_echo_task
167
+ # stream = TestStream.new(java.lang.System.out)
168
+ #
169
+ # @ant = AntProject.new({:name=>"testProject", :basedir=>@current_dir, :declarative=>true,
170
+ # :logger=>Logger.new(STDOUT), :loglevel=>Logger::DEBUG, :outputstr => stream})
171
+ msg = "Antwrap is running an Echo task"
172
+ @ant.echo(:message => msg, :level => 'info')
173
+ # assert(stream.last_line, stream.last_line == msg)
174
+
175
+ @ant.echo(:pcdata => "<foo&bar>")
176
+ end
177
+
178
+ def test_mkdir_task
179
+ dir = @output_dir + '/foo'
180
+
181
+ assert_absent dir
182
+
183
+ @ant.mkdir(:dir => dir)
184
+
185
+ assert_exists dir
186
+ end
187
+
188
+ def test_mkdir_task_with_property
189
+ dir = @output_dir + '/foo'
190
+
191
+ assert_absent dir
192
+
193
+ @ant.property(:name => 'outputProperty', :value => dir)
194
+ @ant.mkdir(:dir => "${outputProperty}")
195
+
196
+ assert_exists dir
197
+ end
198
+
199
+ def test_macrodef_task
200
+
201
+ return if @ant.ant_version < 1.6
202
+
203
+ dir = @output_dir + '/foo'
204
+
205
+ assert_absent dir
206
+
207
+ @ant.macrodef(:name => 'testmacrodef'){
208
+ attribute(:name => 'destination')
209
+ sequential(){
210
+ echo(:message => "Creating @{destination}")
211
+ _mkdir(:dir => "@{destination}")
212
+ }
213
+ }
214
+ @ant.testmacrodef(:destination => dir)
215
+ assert_exists dir
216
+ end
217
+
218
+ def test_cdata
219
+ @ant.echo(:pcdata => "Foobar &amp; <><><>")
220
+ end
221
+
222
+ def test_ant_contrib
223
+
224
+ return if @ant.ant_version < 1.6
225
+
226
+ @ant.taskdef(:resource => "net/sf/antcontrib/antlib.xml")
227
+
228
+ @ant.property(:name => "bar", :value => "bar")
229
+ @ant._if(){
230
+ _equals(:arg1 => "${bar}", :arg2 => "bar")
231
+ _then(){
232
+ echo(:message => "if 1 is equal")
233
+ }
234
+ _else(){
235
+ echo(:message => "if 1 is not equal")
236
+ }
237
+ }
238
+
239
+ @ant.property(:name => "baz", :value => "foo")
240
+ @ant._if(){
241
+ _equals(:arg1 => "${baz}", :arg2 => "bar")
242
+ _then(){
243
+ echo(:message => "if 2 is equal")
244
+ }
245
+ _else(){
246
+ echo(:message => "if 2 is not equal")
247
+ }
248
+ }
249
+
250
+ end
251
+
252
+ private
253
+ def assert_exists(file_path)
254
+ assert(File.exists?(file_path), "Does not exist[#{file_path}]")
255
+ end
256
+
257
+ def assert_absent(file_path)
258
+ assert(!File.exists?(file_path), "Should not exist[#{file_path}]")
259
+ end
260
+ end