buildr 0.18.0 → 0.19.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/java/test.rb CHANGED
@@ -1,175 +1,308 @@
1
+ require "core/build"
2
+ require "java/compile"
3
+
1
4
  module Buildr
5
+ module Java
2
6
 
3
- class JUnitTask < Rake::Task
4
-
5
- attr_accessor :classpath
6
-
7
- def initialize(*args)
8
- super
9
- @classpath = []
10
- @paths = []
11
- @include = []
12
- @exclude = []
13
- enhance do |task|
14
- if test_cases.empty?
15
- puts "#{name}: No tests to run"
16
- else
17
- passed, failed = Java.junit(test_cases, :classpath=>classpath)
18
- fail "#{name}: The following tests failed:\n#{failed.join("\n")}" unless failed.empty?
19
- end
20
- end
21
- end
7
+ # The JUnit task executes JUnit test cases.
8
+ #
9
+ # The task requires one or more paths that contain the test cases (see #from),
10
+ # in addition to any classpath dependencies (see #with). From the test case
11
+ # directories it picks all classes that match the inclusion pattern and none
12
+ # that match the exclusion pattern and executes these in order. See #include
13
+ # for more information.
14
+ class JUnitTask < Rake::Task
22
15
 
23
- def from(*files)
24
- @paths += files
25
- self
26
- end
16
+ attr_accessor :classpath
27
17
 
28
- def include(*files)
29
- @include += files
30
- self
31
- end
18
+ def initialize(*args) #:nodoc:
19
+ super
20
+ @classpath = []
21
+ @paths = []
22
+ @include = []
23
+ @exclude = []
24
+ enhance do |task|
25
+ unless test_cases.empty?
26
+ puts "Running tests in #{name}" if verbose
27
+ passed, failed = Java.junit(test_cases, :classpath=>classpath + @paths)
28
+ fail "The following tests failed:\n#{failed.join("\n")}" unless failed.empty?
29
+ end
30
+ end
31
+ end
32
32
 
33
- def exclude(*files)
34
- @exclude += files
35
- self
36
- end
33
+ # :call-seq:
34
+ # include(*classes) => self
35
+ #
36
+ # Include only the specified test cases. Unless specified, the default is to include
37
+ # all test cases. This method accepts multiple arguments and returns self.
38
+ #
39
+ # Test cases are specified using the fully qualified class name. You can also use file-like
40
+ # patterns (glob) to specify collection of classes. For example:
41
+ # test.include "com.example.FirstTest"
42
+ # test.include "com.example.*"
43
+ # test.include "com.example.Module*"
44
+ # test.include "*.{First,Second}Test"
45
+ #
46
+ # If you do not specify any inclusion pattern explicitly, the default pattern is used.
47
+ # This pattern picks up all classes with a name ending with Test (same as test.include "*Test").
48
+ # Use the Test suffix to specify test case classes, and avoid the Test suffix for classes
49
+ # that do not implement test cases (e.g. mock objects, helpers, etc).
50
+ def include(*classes)
51
+ @include += classes
52
+ self
53
+ end
37
54
 
38
- def with(*files)
39
- @classpath |= artifacts(files.flatten).uniq
40
- self
41
- end
55
+ # :call-seq:
56
+ # exclude(*classes) => self
57
+ #
58
+ # Exclude the specified test cases. This method accepts multiple arguments and returns self.
59
+ # See #include for the type of arguments you can use.
60
+ def exclude(*classes)
61
+ @exclude += classes
62
+ self
63
+ end
42
64
 
43
- def test_cases()
44
- unless @cases
45
- @include << "*" if @include.empty?
46
- @cases = @paths.map do |path|
47
- base = Pathname.new(path)
48
- FileList[File.join(path, "**", "*Test.class")].
49
- map { |file| Pathname.new(file).relative_path_from(base).to_s.ext("").gsub(File::SEPARATOR, ".") }.
50
- select { |name| @include.any? { |pattern| File.fnmatch(pattern, name) } }.
51
- reject { |name| @exclude.any? { |pattern| File.fnmatch(pattern, name) } }
52
- end.flatten.sort
53
- end
54
- @cases
55
- end
65
+ # :call-seq:
66
+ # from(*paths) => self
67
+ #
68
+ # Specify one or more directories that include test cases.
69
+ def from(*files)
70
+ @paths += files
71
+ self
72
+ end
56
73
 
57
- def invoke()
58
- setup
59
- begin
60
- super
61
- ensure
62
- teardown
74
+ # :call-seq:
75
+ # with(*specs) => self
76
+ #
77
+ # Specify artifacts (specs, tasks, files, etc) to include in the classpath when running
78
+ # the test cases.
79
+ def with(*files)
80
+ @classpath |= artifacts(files.flatten).uniq
81
+ self
63
82
  end
64
- end
65
83
 
66
- def needed?()
67
- return true unless ENV["TESTS"] =~ /(no|off|false|disable)/i
68
- end
84
+ private
85
+
86
+ def test_cases()
87
+ unless @cases
88
+ @include << "*Test" if @include.empty?
89
+ @cases = @paths.map do |path|
90
+ base = Pathname.new(path.to_s)
91
+ FileList["#{path}/**/*.class"].
92
+ map { |file| Pathname.new(file).relative_path_from(base).to_s.ext("").gsub(File::SEPARATOR, ".") }.
93
+ select { |name| @include.any? { |pattern| File.fnmatch(pattern, name) } }.
94
+ reject { |name| @exclude.any? { |pattern| File.fnmatch(pattern, name) } }
95
+ end.flatten.sort
96
+ end
97
+ @cases
98
+ end
69
99
 
70
- def prerequisites()
71
- super + classpath + @paths
72
100
  end
73
101
 
74
- def invoke_prerequisites()
75
- prerequisites.each { |n| application[n, @scope].invoke }
76
- end
77
102
 
78
- def setup()
79
- Rake::Task[name.sub(/run$/, "setup")].invoke
80
- end
81
-
82
- def teardown()
83
- Rake::Task[name.sub(/run$/, "teardown")].invoke
84
- end
103
+ # The test task controls the entire test lifecycle.
104
+ #
105
+ # You can use the test task in three ways. You can access and configure specific
106
+ # test tasks, e.g. enhance the #compile task, or run code during #setup/#teardown.
107
+ #
108
+ # You can use convenient methods that handle the most common settings. For example,
109
+ # add classpath dependencies using #with, or include only specific test cases
110
+ # using #include.
111
+ #
112
+ # You can also enhance this task directly. This task will first execute the #compile
113
+ # task, followed by the #setup task and #junit task, then any of your enhancements,
114
+ # and end by executing #teardown.
115
+ class TestTask < Rake::Task
116
+
117
+ def initialize(*args) #:nodoc:
118
+ super
119
+ enhance do
120
+ compile.invoke
121
+ setup.invoke
122
+ junit.invoke
123
+ enhance { teardown.invoke }
124
+ end
125
+ end
85
126
 
86
- end
127
+ # :call-seq:
128
+ # prepare(*prereqs) => task
129
+ # prepare(*prereqs) { |task| .. } => task
130
+ #
131
+ # Executes before the #compile task to prepare any source files used during compilation.
132
+ def prepare(*prereqs, &block)
133
+ @project.task("test:prepare").enhance prereqs, &block
134
+ end
87
135
 
136
+ # :call-seq:
137
+ # compile(*sources) => CompileTask
138
+ # compile(*sources) { |task| .. } => CompileTask
139
+ #
140
+ # The compile task is similar to the Project's compile task. However, it compiles all
141
+ # files found in the src/java/test directory into the target/test-classes directory.
142
+ # This task is executed by the test task before running any test cases.
143
+ #
144
+ # Once the project definition is complete, all classpath dependencies from the regular
145
+ # compile task are copied over, so you only need to specify classpath dependencies
146
+ # specific to your test cases. You can do so by calling #with on the test task.
147
+ # The classpath dependencies used here are also copied over to the junit task.
148
+ def compile(*sources, &block)
149
+ @project.task("test:compile").from(sources).enhance &block
150
+ end
151
+
152
+ # :call-seq:
153
+ # resources(*prereqs) => ResourcesTask
154
+ # resources(*prereqs) { |task| .. } => ResourcesTask
155
+ #
156
+ # Executes by the #compile task to copy resource files over. See Project#resources.
157
+ def resources(*prereqs, &block)
158
+ @project.task("test:resources").enhance prereqs, &block
159
+ end
88
160
 
89
- class Tests
161
+ # :call-seq:
162
+ # junit() => JUnitTask
163
+ #
164
+ # Returns the JUnit task. This task executes JUnit test cases, from classes compiled by
165
+ # the test task.
166
+ #
167
+ # By default it includes all classes with the suffix Test, and excludes all other classes.
168
+ # Use the Test suffix for classes that implement test cases, avoid this suffix for other
169
+ # classes (e.g. mocks, helper objects).
170
+ #
171
+ # You can also include only specific test cases, or exclude otherwise included test cases
172
+ # using #include and #exclude.
173
+ def junit()
174
+ @project.task("test:junit")
175
+ end
90
176
 
91
- def initialize(project)
92
- @project = project
93
- end
177
+ # :call-seq:
178
+ # setup(*prereqs) => task
179
+ # setup(*prereqs) { |task| .. } => task
180
+ #
181
+ # Returns the setup task. The setup task is executed at the beginning of the test task,
182
+ # after compiling the test files.
183
+ def setup(*prereqs, &block)
184
+ @project.task("test:setup").enhance prereqs, &block
185
+ end
94
186
 
95
- def prepare(*tasks, &block)
96
- @project.task("tests:prepare").enhance tasks, &block
97
- end
187
+ # :call-seq:
188
+ # teardown(*prereqs) => task
189
+ # teardown(*prereqs) { |task| .. } => task
190
+ #
191
+ # Returns the teardown task. The teardown task is executed at the end of the test task.
192
+ def teardown(*prereqs, &block)
193
+ @project.task("test.teardown").enhance prereqs, &block
194
+ end
98
195
 
99
- def compile(*sources, &block)
100
- @project.task("tests:compile").from(sources).enhance &block
101
- end
102
-
103
- def resources(*tasks, &block)
104
- @project.task("tests:resources").enhance tasks, &block
105
- end
196
+ # :call-seq:
197
+ # with(*specs) => self
198
+ #
199
+ # Specify artifacts (specs, tasks, files, etc) to include in the classpath when compiling
200
+ # and running test cases. Unless you need to limit specific classpath dependencies, use
201
+ # this instead of calling test.compile and test.junit individually.
202
+ def with(*artifacts)
203
+ compile.with artifacts
204
+ junit.with artifacts
205
+ self
206
+ end
106
207
 
107
- def setup(*tasks, &block)
108
- @project.task("tests:setup").enhance tasks, &block
109
- end
208
+ # :call-seq:
209
+ # include(*classes) => self
210
+ #
211
+ # See JUnitTask#include.
212
+ def include(*classes)
213
+ junit.include *classes
214
+ self
215
+ end
110
216
 
111
- def run(*tasks, &block)
112
- @project.task("tests:run").enhance tasks, &block
113
- end
217
+ # :call-seq:
218
+ # exclude(*classes) => self
219
+ #
220
+ # See JUnitTask#exclude.
221
+ def exclude(*classes)
222
+ junit.exclude *classes
223
+ self
224
+ end
114
225
 
115
- def teardown(*tasks, &block)
116
- @project.task("tests:teardown").enhance tasks, &block
117
226
  end
118
227
 
119
228
  end
120
229
 
121
230
  class Project
122
- inherited_attr :test_src_dir do File.join(src_dir, "test", "java") end
123
- inherited_attr :test_resources_dir do File.join(src_dir, "test", "resources") end
124
- inherited_attr :test_target_dir do File.join(target_dir, "test-classes") end
125
231
 
126
- def tests()
127
- @tests ||= Tests.new(self)
128
- end
129
-
130
- def test(*tasks, &block)
131
- tests.run *tasks, &block
232
+ # :call-seq:
233
+ # test(*prereqs) => TestTask
234
+ # test(*prereqs) { |task| .. } => TestTask
235
+ #
236
+ # Returns the test task. The test task controls the entire test lifecycle.
237
+ #
238
+ # You can use the test task in three ways. You can access and configure specific
239
+ # test tasks, e.g. enhance the compile task by calling test.compile, setup for
240
+ # the test cases by enhancing test.setup and so forth.
241
+ #
242
+ # You can use convenient methods that handle the most common settings. For example,
243
+ # add classpath dependencies using test.with, or include only specific test cases
244
+ # using test.include.
245
+ #
246
+ # You can also enhance this task directly. This method accepts a list of arguments
247
+ # that are used as prerequisites and an optional block that will be executed by the
248
+ # test task.
249
+ #
250
+ # This task will first execute the test.compile task, followed by the test.setup
251
+ # task and test.junit task, then any of your enhancements, and end by executing
252
+ # test.teardown.
253
+ def test(*prereqs, &block)
254
+ task("test").enhance prereqs, &block
132
255
  end
256
+
133
257
  end
134
258
 
135
259
  # Global task compiles all projects.
136
260
  desc "Run all test cases"
137
- Project.local_task task("test")
261
+ Project.local_task("test") { |name| "Running tests in #{name}" }
138
262
 
139
263
  Project.on_define do |project|
140
- namespace "tests" do
141
- # Compile task requires prepare and performs resources, if anything compiled.
142
- #Java::CompileTask.define_task("compile"=>[project.compile, task("prepare")]) { |task| project.tests.resources.invoke }
143
- Java::CompileTask.define_task("compile"=>[project.compile, task("prepare")]) { |task| project.tests.resources.invoke }
144
- # Resources task is a filter.
145
- FilterTask.define_task("resources")
146
- JUnitTask.define_task("run"=>task("compile"))
147
- task("setup")
148
- task("teardown")
149
- end
150
- project.tests.compile.with Java::JUNIT_REQUIRES
151
- project.recursive_task("test"=>project.test)
264
+ # Define a recursive test task, and pass it a reference to the project so it can discover all other tasks.
265
+ Java::TestTask.define_task("test")
266
+ project.test.instance_eval { instance_variable_set :@project, project }
267
+ project.recursive_task("test")
268
+ # Similar to the regular resources task but using different paths.
269
+ resources = Java::ResourcesTask.define_task("test:resources")
270
+ project.path_to("src/test/resources").tap { |dir| resources.filter.include project.path_to(dir, "*") if File.exist?(dir) }
271
+ # Similar to the regular compile task but using different paths.
272
+ compile = Java::CompileTask.define_task("test:compile"=>[project.compile, project.test.prepare, project.test.resources])
273
+ compile.enhance { project.test.resources.invoke }
274
+ project.path_to("src/test/java").tap { |dir| compile.from dir if File.exist?(dir) }
275
+ compile.into project.path_to("target/test-classes")
276
+ resources.filter.into compile.target
277
+ # Define the JUnit task here, otherwise we get a normal task.
278
+ Java::JUnitTask.define_task("test:junit")
279
+ # Define these tasks once, otherwise we may get a namespace error.
280
+ project.test.setup ; project.test.teardown
281
+ # Include the JUnit, Mock and other commonly used dependencies.
282
+ project.test.with Java::JUNIT_REQUIRES
152
283
 
153
284
  project.enhance do |project|
154
- project.tests.compile.from project.path_to(:test_src_dir) if File.exist?(project.path_to(:test_src_dir))
155
- project.tests.compile.into project.path_to(:test_target_dir) unless project.tests.compile.target
156
- project.tests.resources.include project.path_to(:test_resources_dir, "*") if File.exists?(project.path_to(:test_resources_dir))
157
- project.tests.resources.into project.tests.compile.target unless project.tests.resources.target
158
-
159
- project.tests.compile.classpath += project.compile.classpath
160
- project.tests.compile.classpath << project.compile.target
161
- project.tests.run.from project.tests.compile.target
162
- project.tests.run.classpath += project.tests.compile.classpath
163
- project.tests.run.classpath << project.tests.compile.target
285
+ # Copy the regular compile classpath over, and also include the generated classes.
286
+ project.test.with project.compile.classpath, project.compile.target
287
+ project.test.junit.with project.test.compile.classpath
288
+ # Tell the JUnit task where to pick the test cases from.
289
+ project.test.junit.from project.test.compile.target
164
290
  end
165
-
166
291
  end
167
292
 
293
+ # This rule takes a suffix and runs that test case in the current project. For example;
294
+ # rake test:MyTest
295
+ # will run the test case class com.example.MyTest, if found in the current project.
168
296
  rule /^test:.*$/ do |task|
169
297
  test = task.name.scan(/test:(.*)/)[0][0]
170
298
  Project.projects.select { |project| project.base_dir == Rake.application.original_dir }.
171
- map { |project| project.task("tests:run") }.
172
- each { |task| task.include("*#{test}").invoke }
299
+ map { |project| project.test }.each { |task| task.include("*#{test}").invoke }
173
300
  end
174
301
 
302
+ # Require tests after build unless TEST option is off.
303
+ # For example:
304
+ # rake build
305
+ # rake build TEST=off
306
+ task("build") { task("test").invoke } unless ENV["TEST"] =~ /(off|false|no)/
307
+
175
308
  end
data/lib/java/xmlbeans.rb CHANGED
@@ -1,66 +1,72 @@
1
+ require "java/java"
2
+
1
3
  module Buildr
4
+ module Java
5
+ module XMLBeans
2
6
 
3
- module XMLBeans
7
+ REQUIRES = [ "xmlbeans:xbean:jar:2.2.0", "stax:stax-api:jar:1.0" ]
4
8
 
5
- REQUIRES = [ "xmlbeans:xbean:jar:2.2.0", "stax:stax-api:jar:1.0" ]
9
+ class << self
6
10
 
7
- def self.compile(*args)
8
- options = Hash === args.last ? args.pop : {}
9
- options[:verbose] ||= Rake.application.options.trace || false
10
- fu_check_options options, :verbose, :noop, :javasource, :jar, :classes, :output
11
+ def compile(*args)
12
+ options = Hash === args.last ? args.pop : {}
13
+ options[:verbose] ||= Rake.application.options.trace || false
14
+ fu_check_options options, :verbose, :noop, :javasource, :jar, :compile, :output, :xsb
11
15
 
12
- # Options for SchemaCompiler.
13
- cmd_args = [ options[:verbose] ? "-verbose" : "-quiet" ]
14
- cmd_args << "-javasource" << options[:javasource].collect.join(File::PATH_SEPARATOR) if options[:javasource]
15
- cmd_args << "-out" << options[:jar] if options[:jar]
16
- cmd_args << "-d" << options[:classes] if options[:classes]
17
- cmd_args << "-src" << options[:output] if options[:output]
18
- cmd_args += args
19
- cmd_args << { :verbose=>options[:verbose] }
16
+ # Options for SchemaCompiler.
17
+ output = options[:output].to_s
18
+ cmd_args = [ options[:verbose] ? "-verbose" : "-quiet" ]
19
+ cmd_args << "-javasource" << options[:javasource].collect.join(File::PATH_SEPARATOR) if options[:javasource]
20
+ cmd_args << "-out" << options[:jar] if options[:jar]
21
+ cmd_args << "-d" << output
22
+ cmd_args << "-srconly" unless options[:compile]
23
+ cmd_args << "-src" << output
24
+ cmd_args += args.flatten
25
+ cmd_args << { :verbose=>options[:verbose] }
20
26
 
21
- unless options[:noop]
22
- puts "Running XMLBeans schema compiler" if verbose
23
- mkpath options[:classes], :verbose=>false rescue nil if options[:classes]
24
- mkpath options[:output], :verbose=>false rescue nil if options[:output]
25
- sh(Java.path_to_bin("java"), "-Xmx256m", "-cp", requires.join(File::PATH_SEPARATOR),
26
- "org.apache.xmlbeans.impl.tool.SchemaCompiler", *cmd_args) { |ok, res|
27
- fail "Failed to compile schemas, see errors above" unless ok }
28
- # Touch paths to let other tasks know there's an update.
29
- touch options[:classes], :verbose=>false if options[:classes]
30
- touch options[:output], :verbose=>false if options[:output]
31
- end
32
- end
27
+ unless options[:noop]
28
+ puts "Running XMLBeans schema compiler" if verbose
29
+ mkpath output, :verbose=>false rescue nil
30
+ sh(Java.path_to_bin("java"), "-Xmx256m", "-cp", requires.join(File::PATH_SEPARATOR),
31
+ "org.apache.xmlbeans.impl.tool.SchemaCompiler", *cmd_args) { |ok, res|
32
+ fail "Failed to compile schemas, see errors above" unless ok }
33
+ # Touch paths to let other tasks know there's an update.
34
+ touch output, :verbose=>false
35
+ end
36
+ end
33
37
 
34
- def self.requires()
35
- @requires ||= artifacts(REQUIRES).each { |artifact| artifact.invoke }.map(&:to_s)
36
- end
37
-
38
- class CompileTask < Rake::FileTask
38
+ private
39
39
 
40
- def initialize(*args)
41
- super
42
- enhance do |task|
43
- XMLBeans.compile *task.prerequisites + [options.merge(:output=>task.name)]
40
+ def requires()
41
+ @requires ||= artifacts(REQUIRES).each { |artifact| artifact.invoke }.map(&:to_s)
44
42
  end
43
+
45
44
  end
46
45
 
47
- def options()
48
- @options ||= {}
49
- end
50
-
51
- def using(options)
52
- self.options.merge!(options)
53
- self
46
+ def compile_xml_beans(*args)
47
+ # Generate sources and add them to the compile task.
48
+ generated = file(path_to("target/generated/xmlbeans")=>FileList[args.flatten]) do |task|
49
+ Java::XMLBeans.compile task.prerequisites, :output=>task.name,
50
+ :javasource=>compile.options.source, :xsb=>compile.target
51
+ end
52
+ compile.from(generated).with(JAVAX.stream, XMLBEANS)
53
+ # Once compiled, we need to copy the generated XSB/XSD and one (magical?) class file
54
+ # into the target directory, or the rest is useless.
55
+ compile do |task|
56
+ verbose(false) do
57
+ base = Pathname.new(generated.to_s)
58
+ FileList["#{base}/**/*.{class,xsb,xsd}"].each do |file|
59
+ target = File.join(compile.target.to_s, Pathname.new(file).relative_path_from(base))
60
+ mkpath File.dirname(target) ; cp file, target
61
+ end
62
+ end
63
+ end
54
64
  end
55
65
 
56
66
  end
57
-
58
- def self.compile_task(args)
59
- output = args.keys.first
60
- files = args.values.first.collect { |f| File.directory?(f) ? FileList[f + "/**/*"] : f }.flatten
61
- CompileTask.define_task(output=>files)
62
- end
63
-
64
67
  end
65
68
 
69
+ class Project
70
+ include Java::XMLBeans
71
+ end
66
72
  end