assaf-buildr 1.3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (163) hide show
  1. data/CHANGELOG +887 -0
  2. data/DISCLAIMER +7 -0
  3. data/LICENSE +176 -0
  4. data/NOTICE +26 -0
  5. data/README.rdoc +146 -0
  6. data/Rakefile +62 -0
  7. data/_buildr +38 -0
  8. data/addon/buildr/antlr.rb +65 -0
  9. data/addon/buildr/cobertura.rb +236 -0
  10. data/addon/buildr/emma.rb +238 -0
  11. data/addon/buildr/hibernate.rb +142 -0
  12. data/addon/buildr/javacc.rb +85 -0
  13. data/addon/buildr/jdepend.rb +60 -0
  14. data/addon/buildr/jetty.rb +248 -0
  15. data/addon/buildr/jibx.rb +86 -0
  16. data/addon/buildr/nailgun.rb +817 -0
  17. data/addon/buildr/openjpa.rb +90 -0
  18. data/addon/buildr/org/apache/buildr/BuildrNail$Main.class +0 -0
  19. data/addon/buildr/org/apache/buildr/BuildrNail.class +0 -0
  20. data/addon/buildr/org/apache/buildr/BuildrNail.java +41 -0
  21. data/addon/buildr/org/apache/buildr/JettyWrapper$1.class +0 -0
  22. data/addon/buildr/org/apache/buildr/JettyWrapper$BuildrHandler.class +0 -0
  23. data/addon/buildr/org/apache/buildr/JettyWrapper.class +0 -0
  24. data/addon/buildr/org/apache/buildr/JettyWrapper.java +144 -0
  25. data/addon/buildr/xmlbeans.rb +93 -0
  26. data/bin/buildr +28 -0
  27. data/buildr.buildfile +53 -0
  28. data/buildr.gemspec +58 -0
  29. data/doc/css/default.css +228 -0
  30. data/doc/css/print.css +100 -0
  31. data/doc/css/syntax.css +52 -0
  32. data/doc/images/apache-incubator-logo.png +0 -0
  33. data/doc/images/buildr-hires.png +0 -0
  34. data/doc/images/buildr.png +0 -0
  35. data/doc/images/favicon.png +0 -0
  36. data/doc/images/growl-icon.tiff +0 -0
  37. data/doc/images/note.png +0 -0
  38. data/doc/images/project-structure.png +0 -0
  39. data/doc/images/tip.png +0 -0
  40. data/doc/images/zbuildr.tif +0 -0
  41. data/doc/pages/artifacts.textile +207 -0
  42. data/doc/pages/building.textile +240 -0
  43. data/doc/pages/contributing.textile +208 -0
  44. data/doc/pages/download.textile +62 -0
  45. data/doc/pages/extending.textile +175 -0
  46. data/doc/pages/getting_started.textile +273 -0
  47. data/doc/pages/index.textile +42 -0
  48. data/doc/pages/languages.textile +407 -0
  49. data/doc/pages/mailing_lists.textile +17 -0
  50. data/doc/pages/more_stuff.textile +286 -0
  51. data/doc/pages/packaging.textile +427 -0
  52. data/doc/pages/projects.textile +274 -0
  53. data/doc/pages/recipes.textile +103 -0
  54. data/doc/pages/settings_profiles.textile +274 -0
  55. data/doc/pages/testing.textile +212 -0
  56. data/doc/pages/troubleshooting.textile +103 -0
  57. data/doc/pages/whats_new.textile +323 -0
  58. data/doc/print.haml +51 -0
  59. data/doc/print.toc.yaml +29 -0
  60. data/doc/scripts/buildr-git.rb +412 -0
  61. data/doc/scripts/install-jruby.sh +44 -0
  62. data/doc/scripts/install-linux.sh +64 -0
  63. data/doc/scripts/install-osx.sh +52 -0
  64. data/doc/site.haml +56 -0
  65. data/doc/site.toc.yaml +47 -0
  66. data/etc/KEYS +151 -0
  67. data/etc/git-svn-authors +16 -0
  68. data/lib/buildr.rb +35 -0
  69. data/lib/buildr/core.rb +27 -0
  70. data/lib/buildr/core/application.rb +489 -0
  71. data/lib/buildr/core/application_cli.rb +139 -0
  72. data/lib/buildr/core/build.rb +311 -0
  73. data/lib/buildr/core/checks.rb +382 -0
  74. data/lib/buildr/core/common.rb +154 -0
  75. data/lib/buildr/core/compile.rb +596 -0
  76. data/lib/buildr/core/environment.rb +120 -0
  77. data/lib/buildr/core/filter.rb +362 -0
  78. data/lib/buildr/core/generate.rb +195 -0
  79. data/lib/buildr/core/help.rb +118 -0
  80. data/lib/buildr/core/progressbar.rb +156 -0
  81. data/lib/buildr/core/project.rb +892 -0
  82. data/lib/buildr/core/test.rb +715 -0
  83. data/lib/buildr/core/transports.rb +558 -0
  84. data/lib/buildr/core/util.rb +289 -0
  85. data/lib/buildr/groovy.rb +18 -0
  86. data/lib/buildr/groovy/bdd.rb +105 -0
  87. data/lib/buildr/groovy/compiler.rb +138 -0
  88. data/lib/buildr/ide.rb +19 -0
  89. data/lib/buildr/ide/eclipse.rb +212 -0
  90. data/lib/buildr/ide/idea.ipr.template +300 -0
  91. data/lib/buildr/ide/idea.rb +189 -0
  92. data/lib/buildr/ide/idea7x.ipr.template +290 -0
  93. data/lib/buildr/ide/idea7x.rb +210 -0
  94. data/lib/buildr/java.rb +23 -0
  95. data/lib/buildr/java/ant.rb +92 -0
  96. data/lib/buildr/java/bdd.rb +449 -0
  97. data/lib/buildr/java/commands.rb +211 -0
  98. data/lib/buildr/java/compiler.rb +348 -0
  99. data/lib/buildr/java/deprecated.rb +141 -0
  100. data/lib/buildr/java/jruby.rb +117 -0
  101. data/lib/buildr/java/jtestr_runner.rb.erb +116 -0
  102. data/lib/buildr/java/org/apache/buildr/JavaTestFilter.class +0 -0
  103. data/lib/buildr/java/org/apache/buildr/JavaTestFilter.java +119 -0
  104. data/lib/buildr/java/packaging.rb +713 -0
  105. data/lib/buildr/java/pom.rb +178 -0
  106. data/lib/buildr/java/rjb.rb +155 -0
  107. data/lib/buildr/java/test_result.rb +308 -0
  108. data/lib/buildr/java/tests.rb +324 -0
  109. data/lib/buildr/java/version_requirement.rb +172 -0
  110. data/lib/buildr/packaging.rb +21 -0
  111. data/lib/buildr/packaging/artifact.rb +730 -0
  112. data/lib/buildr/packaging/artifact_namespace.rb +972 -0
  113. data/lib/buildr/packaging/artifact_search.rb +140 -0
  114. data/lib/buildr/packaging/gems.rb +102 -0
  115. data/lib/buildr/packaging/package.rb +233 -0
  116. data/lib/buildr/packaging/tar.rb +104 -0
  117. data/lib/buildr/packaging/zip.rb +722 -0
  118. data/lib/buildr/resources/buildr.icns +0 -0
  119. data/lib/buildr/scala.rb +19 -0
  120. data/lib/buildr/scala/compiler.rb +109 -0
  121. data/lib/buildr/scala/tests.rb +203 -0
  122. data/rakelib/apache.rake +191 -0
  123. data/rakelib/changelog.rake +57 -0
  124. data/rakelib/doc.rake +103 -0
  125. data/rakelib/package.rake +73 -0
  126. data/rakelib/release.rake +65 -0
  127. data/rakelib/rspec.rake +83 -0
  128. data/rakelib/rubyforge.rake +53 -0
  129. data/rakelib/scm.rake +49 -0
  130. data/rakelib/setup.rake +86 -0
  131. data/rakelib/stage.rake +48 -0
  132. data/spec/addon/cobertura_spec.rb +77 -0
  133. data/spec/addon/emma_spec.rb +120 -0
  134. data/spec/addon/test_coverage_spec.rb +255 -0
  135. data/spec/core/application_spec.rb +412 -0
  136. data/spec/core/artifact_namespace_spec.rb +646 -0
  137. data/spec/core/build_spec.rb +415 -0
  138. data/spec/core/checks_spec.rb +537 -0
  139. data/spec/core/common_spec.rb +664 -0
  140. data/spec/core/compile_spec.rb +566 -0
  141. data/spec/core/generate_spec.rb +33 -0
  142. data/spec/core/project_spec.rb +754 -0
  143. data/spec/core/test_spec.rb +1091 -0
  144. data/spec/core/transport_spec.rb +500 -0
  145. data/spec/groovy/bdd_spec.rb +80 -0
  146. data/spec/groovy/compiler_spec.rb +239 -0
  147. data/spec/ide/eclipse_spec.rb +243 -0
  148. data/spec/java/ant.rb +28 -0
  149. data/spec/java/bdd_spec.rb +358 -0
  150. data/spec/java/compiler_spec.rb +446 -0
  151. data/spec/java/java_spec.rb +88 -0
  152. data/spec/java/packaging_spec.rb +1103 -0
  153. data/spec/java/tests_spec.rb +466 -0
  154. data/spec/packaging/archive_spec.rb +503 -0
  155. data/spec/packaging/artifact_spec.rb +754 -0
  156. data/spec/packaging/packaging_helper.rb +63 -0
  157. data/spec/packaging/packaging_spec.rb +589 -0
  158. data/spec/sandbox.rb +137 -0
  159. data/spec/scala/compiler_spec.rb +228 -0
  160. data/spec/scala/tests_spec.rb +215 -0
  161. data/spec/spec_helpers.rb +304 -0
  162. data/spec/version_requirement_spec.rb +123 -0
  163. metadata +369 -0
@@ -0,0 +1,715 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with this
3
+ # work for additional information regarding copyright ownership. The ASF
4
+ # licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations under
14
+ # the License.
15
+
16
+
17
+ require 'buildr/core/project'
18
+ require 'buildr/core/build'
19
+ require 'buildr/core/compile'
20
+
21
+
22
+ module Buildr
23
+
24
+ # The underlying test framework used by TestTask.
25
+ # To add a new test framework, extend TestFramework::Base and add your framework using:
26
+ # Buildr::TestFramework << MyFramework
27
+ module TestFramework
28
+
29
+ class << self
30
+
31
+ # Returns true if the specified test framework exists.
32
+ def has?(name)
33
+ frameworks.any? { |framework| framework.to_sym == name.to_sym }
34
+ end
35
+
36
+ # Select a test framework by its name.
37
+ def select(name)
38
+ frameworks.detect { |framework| framework.to_sym == name.to_sym }
39
+ end
40
+
41
+ # Identify which test framework applies for this project.
42
+ def select_from(project)
43
+ # Look for a suitable test framework based on the compiled language,
44
+ # which may return multiple candidates, e.g. JUnit and TestNG for Java.
45
+ # Pick the one used in the parent project, if not, whichever comes first.
46
+ candidates = frameworks.select { |framework| framework.applies_to?(project) }
47
+ parent = project.parent
48
+ parent && candidates.detect { |framework| framework.to_sym == parent.test.framework } || candidates.first
49
+ end
50
+
51
+ # Adds a test framework to the list of supported frameworks.
52
+ #
53
+ # For example:
54
+ # Buildr::TestFramework << Buildr::JUnit
55
+ def add(framework)
56
+ @frameworks ||= []
57
+ @frameworks |= [framework]
58
+ end
59
+ alias :<< :add
60
+
61
+ # Returns a list of available test frameworks.
62
+ def frameworks
63
+ @frameworks ||= []
64
+ end
65
+
66
+ end
67
+
68
+ # Base class for all test frameworks, with common functionality. Extend and over-ride as you see fit
69
+ # (see JUnit as an example).
70
+ class Base
71
+
72
+ class << self
73
+
74
+ # The framework's identifier (e.g. :junit). Inferred from the class name.
75
+ def to_sym
76
+ @symbol ||= name.split('::').last.downcase.to_sym
77
+ end
78
+
79
+ # Returns true if this framework applies to the current project. For example, JUnit returns
80
+ # true if the tests are written in Java.
81
+ def applies_to?(project)
82
+ raise 'Not implemented'
83
+ end
84
+
85
+ # Returns a list of dependencies for this framework. Default is an empty list,
86
+ # override to add dependencies.
87
+ def dependencies
88
+ @dependencies ||= []
89
+ end
90
+
91
+ end
92
+
93
+ # Construct a new test framework with the specified options. Note that options may
94
+ # change before the framework is run.
95
+ def initialize(test_task, options)
96
+ @options = options
97
+ @task = test_task
98
+ end
99
+
100
+ # Options for this test framework.
101
+ attr_reader :options
102
+ # The test task we belong to
103
+ attr_reader :task
104
+
105
+ # Returns a list of dependenices for this framework. Defaults to calling the #dependencies
106
+ # method on the class.
107
+ def dependencies
108
+ self.class.dependencies
109
+ end
110
+
111
+ # TestTask calls this method to return a list of test names that can be run in this project.
112
+ # It then applies the include/exclude patterns to arrive at the list of tests that will be
113
+ # run, and call the #run method with that list.
114
+ #
115
+ # This method should return a list suitable for using with the #run method, but also suitable
116
+ # for the user to manage. For example, JUnit locates all the tests in the test.compile.target
117
+ # directory, and returns the class names, which are easier to work with than file names.
118
+ def tests(dependencies)
119
+ raise 'Not implemented'
120
+ end
121
+
122
+ # TestTask calls this method to run the named (and only those) tests. This method returns
123
+ # the list of tests that ran successfully.
124
+ def run(tests, dependencies)
125
+ raise 'Not implemented'
126
+ end
127
+
128
+ end
129
+
130
+ end
131
+
132
+
133
+ # The test task controls the entire test lifecycle.
134
+ #
135
+ # You can use the test task in three ways. You can access and configure specific test tasks,
136
+ # e.g. enhance the #compile task, or run code during #setup/#teardown.
137
+ #
138
+ # You can use convenient methods that handle the most common settings. For example,
139
+ # add dependencies using #with, or include only specific tests using #include.
140
+ #
141
+ # You can also enhance this task directly. This task will first execute the #compile task, followed
142
+ # by the #setup task, run the unit tests, any other enhancements, and end by executing #teardown.
143
+ #
144
+ # The test framework is determined based on the available test files, for example, if the test
145
+ # cases are written in Java, then JUnit is selected as the test framework. You can also select
146
+ # a specific test framework, for example, to use TestNG instead of JUnit:
147
+ # test.using :testng
148
+ class TestTask < Rake::Task
149
+
150
+ class << self
151
+
152
+ # Used by the local test and integration tasks to
153
+ # a) Find the local project(s),
154
+ # b) Find all its sub-projects and narrow down to those that have either unit or integration tests,
155
+ # c) Run all the (either unit or integration) tests, and
156
+ # d) Ignore failure if necessary.
157
+ def run_local_tests(integration) #:nodoc:
158
+ Project.local_projects do |project|
159
+ # !(foo ^ bar) tests for equality and accepts nil as false (and select is less obfuscated than reject on ^).
160
+ projects = ([project] + project.projects).select { |project| !(project.test.options[:integration] ^ integration) }
161
+ projects.each do |project|
162
+ info "Testing #{project.name}"
163
+ begin
164
+ project.test.invoke
165
+ rescue
166
+ raise unless Buildr.options.test == :all
167
+ end
168
+ end
169
+ end
170
+ end
171
+
172
+ # Used by the test/integration rule to only run tests that match the specified names.
173
+ def only_run(tests) #:nodoc:
174
+ tests = tests.map { |name| name =~ /\*/ ? name : "*#{name}*" }
175
+ # Since the tests may reside in a sub-project, we need to set the include/exclude pattern on
176
+ # all sub-projects, but only invoke test on the local project.
177
+ Project.projects.each { |project| project.test.send :only_run, tests }
178
+ end
179
+ end
180
+
181
+ # Default options already set on each test task.
182
+ def default_options
183
+ { :fail_on_failure=>true, :fork=>:once, :properties=>{}, :environment=>{} }
184
+ end
185
+
186
+ def initialize(*args) #:nodoc:
187
+ super
188
+ @dependencies = FileList[]
189
+ @include = []
190
+ @exclude = []
191
+ @forced_need = false
192
+ parent_task = Project.parent_task(name)
193
+ if parent_task.respond_to?(:options)
194
+ @options = OpenObject.new { |hash, key| hash[key] = parent_task.options[key].clone rescue hash[key] = parent_task.options[key] }
195
+ else
196
+ @options = OpenObject.new(default_options)
197
+ end
198
+ enhance [application.buildfile.name] do
199
+ run_tests if framework
200
+ end
201
+ end
202
+
203
+ # The dependencies used for running the tests. Includes the compiled files (compile.target)
204
+ # and their dependencies. Will also include anything you pass to #with, shared between the
205
+ # testing compile and run dependencies.
206
+ attr_reader :dependencies
207
+
208
+ # *Deprecated*: Use dependencies instead.
209
+ def classpath
210
+ Buildr.application.deprecated 'Use dependencies instead.'
211
+ dependencies
212
+ end
213
+
214
+ # *Deprecated*: Use dependencies= instead.
215
+ def classpath=(artifacts)
216
+ Buildr.application.deprecated 'Use dependencies= instead.'
217
+ self.dependencies = artifacts
218
+ end
219
+
220
+ def execute(args) #:nodoc:
221
+ if Buildr.options.test == false
222
+ info "Skipping tests for #{project.name}"
223
+ return
224
+ end
225
+ setup.invoke
226
+ begin
227
+ super
228
+ rescue RuntimeError
229
+ raise if options[:fail_on_failure]
230
+ ensure
231
+ teardown.invoke
232
+ end
233
+ end
234
+
235
+ # :call-seq:
236
+ # compile(*sources) => CompileTask
237
+ # compile(*sources) { |task| .. } => CompileTask
238
+ #
239
+ # The compile task is similar to the Project's compile task. However, it compiles all
240
+ # files found in the src/test/{source} directory into the target/test/{code} directory.
241
+ # This task is executed by the test task before running any tests.
242
+ #
243
+ # Once the project definition is complete, all dependencies from the regular
244
+ # compile task are copied over, so you only need to specify dependencies
245
+ # specific to your tests. You can do so by calling #with on the test task.
246
+ # The dependencies used here are also copied over to the junit task.
247
+ def compile(*sources, &block)
248
+ @project.task('test:compile').from(sources).enhance &block
249
+ end
250
+
251
+ # :call-seq:
252
+ # resources(*prereqs) => ResourcesTask
253
+ # resources(*prereqs) { |task| .. } => ResourcesTask
254
+ #
255
+ # Executes by the #compile task to copy resource files over. See Project#resources.
256
+ def resources(*prereqs, &block)
257
+ @project.task('test:resources').enhance prereqs, &block
258
+ end
259
+
260
+ # :call-seq:
261
+ # setup(*prereqs) => task
262
+ # setup(*prereqs) { |task| .. } => task
263
+ #
264
+ # Returns the setup task. The setup task is executed at the beginning of the test task,
265
+ # after compiling the test files.
266
+ def setup(*prereqs, &block)
267
+ @project.task('test:setup').enhance prereqs, &block
268
+ end
269
+
270
+ # :call-seq:
271
+ # teardown(*prereqs) => task
272
+ # teardown(*prereqs) { |task| .. } => task
273
+ #
274
+ # Returns the teardown task. The teardown task is executed at the end of the test task.
275
+ def teardown(*prereqs, &block)
276
+ @project.task('test:teardown').enhance prereqs, &block
277
+ end
278
+
279
+ # :call-seq:
280
+ # with(*specs) => self
281
+ #
282
+ # Specify artifacts (specs, tasks, files, etc) to include in the dependencies list
283
+ # when compiling and running tests.
284
+ def with(*artifacts)
285
+ @dependencies |= Buildr.artifacts(artifacts.flatten).uniq
286
+ compile.with artifacts
287
+ self
288
+ end
289
+
290
+ # Returns various test options.
291
+ attr_reader :options
292
+
293
+ # :call-seq:
294
+ # using(options) => self
295
+ #
296
+ # Sets various test options from a hash and returns self. For example:
297
+ # test.using :fork=>:each, :properties=>{ 'url'=>'http://localhost:8080' }
298
+ #
299
+ # Can also be used to select the test framework, or to run these tests as
300
+ # integration tests. For example:
301
+ # test.using :testng
302
+ # test.using :integration
303
+ #
304
+ # The :fail_on_failure option specifies whether the task should fail if
305
+ # any of the tests fail (default), or should report the failures but continue
306
+ # running the build (when set to false).
307
+ #
308
+ # All other options depend on the capability of the test framework. These options
309
+ # should be used the same way across all frameworks that support them:
310
+ # * :fork -- Fork once for each project (:once, default), for each test in each
311
+ # project (:each), or don't fork at all (false).
312
+ # * :properties -- Properties pass to the test, e.g. in Java as system properties.
313
+ # * :environment -- Environment variables. This hash is made available in the
314
+ # form of environment variables.
315
+ def using(*args)
316
+ args.pop.each { |key, value| options[key.to_sym] = value } if Hash === args.last
317
+ args.each do |name|
318
+ if TestFramework.has?(name)
319
+ self.framework = name
320
+ elsif name == :integration
321
+ options[:integration] = true
322
+ else
323
+ Buildr.application.deprecated "Please replace with using(:#{name}=>true)"
324
+ options[name.to_sym] = true
325
+ end
326
+ end
327
+ self
328
+ end
329
+
330
+ # :call-seq:
331
+ # include(*names) => self
332
+ #
333
+ # Include only the specified tests. Unless specified, the default is to include
334
+ # all tests identified by the test framework. This method accepts multiple arguments
335
+ # and returns self.
336
+ #
337
+ # Tests are specified by their full name, but you can use glob patterns to select
338
+ # multiple tests, for example:
339
+ # test.include 'com.example.FirstTest' # FirstTest only
340
+ # test.include 'com.example.*' # All tests under com/example
341
+ # test.include 'com.example.Module*' # All tests starting with Module
342
+ # test.include '*.{First,Second}Test' # FirstTest, SecondTest
343
+ def include(*names)
344
+ @include += names
345
+ self
346
+ end
347
+
348
+ # :call-seq:
349
+ # exclude(*names) => self
350
+ #
351
+ # Exclude the specified tests. This method accepts multiple arguments and returns self.
352
+ # See #include for the type of arguments you can use.
353
+ def exclude(*names)
354
+ @exclude += names
355
+ self
356
+ end
357
+
358
+ # *Deprecated*: Use tests instead.
359
+ def classes
360
+ Buildr.application.deprecated 'Call tests instead of classes'
361
+ tests
362
+ end
363
+
364
+ # After running the task, returns all tests selected to run, based on availability and include/exclude pattern.
365
+ attr_reader :tests
366
+ # After running the task, returns all the tests that failed, empty array if all tests passed.
367
+ attr_reader :failed_tests
368
+ # After running the task, returns all the tests that passed, empty array if no tests passed.
369
+ attr_reader :passed_tests
370
+
371
+ # :call-seq:
372
+ # framework => symbol
373
+ #
374
+ # Returns the test framework, e.g. :junit, :testng.
375
+ def framework
376
+ unless @framework
377
+ # Start with all frameworks that apply (e.g. JUnit and TestNG for Java),
378
+ # and pick the first (default) one, unless already specified in parent project.
379
+ candidates = TestFramework.frameworks.select { |cls| cls.applies_to?(@project) }
380
+ candidate = @project.parent && candidates.detect { |framework| framework.to_sym == @project.parent.test.framework } ||
381
+ candidates.first
382
+ self.framework = candidate if candidate
383
+ end
384
+ @framework && @framework.class.to_sym
385
+ end
386
+
387
+ # :call-seq:
388
+ # report_to => file
389
+ #
390
+ # Test frameworks that can produce reports, will write them to this directory.
391
+ #
392
+ # This is framework dependent, so unless you use the default test framework, call this method
393
+ # after setting the test framework.
394
+ def report_to
395
+ @report_to ||= file(@project.path_to(:reports, framework)=>self)
396
+ end
397
+
398
+ # The path to the file that stores the time stamp of the last successful test run.
399
+ def last_successful_run_file #:nodoc:
400
+ File.join(report_to.to_s, 'last_successful_run')
401
+ end
402
+
403
+ # The time stamp of the last successful test run. Or Rake::EARLY if no successful test run recorded.
404
+ def timestamp #:nodoc:
405
+ File.exist?(last_successful_run_file) ? File.mtime(last_successful_run_file) : Rake::EARLY
406
+ end
407
+
408
+ # The project this task belongs to.
409
+ attr_reader :project
410
+
411
+ protected
412
+
413
+ def associate_with(project)
414
+ @project = project
415
+ end
416
+
417
+ def framework=(name)
418
+ cls = TestFramework.select(name) or raise ArgumentError, "No #{name} test framework available. Did you install it?"
419
+ #cls.inherit_options.reject { |name| options.has_key?(name) }.
420
+ # each { |name| options[name] = @parent_task.options[name] } if @parent_task.respond_to?(:options)
421
+ @framework = cls.new(self, options)
422
+ # Test framework dependency.
423
+ with @framework.dependencies
424
+ end
425
+
426
+ # :call-seq:
427
+ # include?(name) => boolean
428
+ #
429
+ # Returns true if the specified test name matches the inclusion/exclusion pattern. Used to determine
430
+ # which tests to execute.
431
+ def include?(name)
432
+ (@include.empty? || @include.any? { |pattern| File.fnmatch(pattern, name) }) &&
433
+ !@exclude.any? { |pattern| File.fnmatch(pattern, name) }
434
+ end
435
+
436
+ # Runs the tests using the selected test framework.
437
+ def run_tests
438
+ dependencies = Buildr.artifacts(self.dependencies).map(&:to_s).uniq
439
+ rm_rf report_to.to_s
440
+ @tests = @framework.tests(dependencies).select { |test| include?(test) }.sort
441
+ if @tests.empty?
442
+ @passed_tests, @failed_tests = [], []
443
+ else
444
+ info "Running tests in #{@project.name}"
445
+ @passed_tests = @framework.run(@tests, dependencies)
446
+ @failed_tests = @tests - @passed_tests
447
+ unless @failed_tests.empty?
448
+ error "The following tests failed:\n#{@failed_tests.join("\n")}"
449
+ fail 'Tests failed!'
450
+ end
451
+ end
452
+ record_successful_run unless @forced_need
453
+ end
454
+
455
+ # Call this method when a test run is successful to record the current system time.
456
+ def record_successful_run #:nodoc:
457
+ mkdir_p report_to.to_s
458
+ touch last_successful_run_file
459
+ end
460
+
461
+ # Limit running tests to specific list.
462
+ def only_run(tests)
463
+ @include = Array(tests)
464
+ @exclude.clear
465
+ @forced_need = true
466
+ end
467
+
468
+ def invoke_prerequisites(args, chain) #:nodoc:
469
+ @prerequisites |= FileList[@dependencies.uniq]
470
+ super
471
+ end
472
+
473
+ def needed? #:nodoc:
474
+ latest_prerequisite = @prerequisites.map { |p| application[p, @scope] }.max { |a,b| a.timestamp<=>b.timestamp }
475
+ needed = (timestamp == Rake::EARLY) || latest_prerequisite.timestamp > timestamp
476
+ trace "Testing#{needed ? ' ' : ' not '}needed. " +
477
+ "Latest prerequisite change: #{latest_prerequisite.timestamp} (#{latest_prerequisite.to_s}). " +
478
+ "Last successful test run: #{timestamp}."
479
+ return needed || @forced_need || Buildr.options.test == :all
480
+ end
481
+ end
482
+
483
+
484
+ # The integration tests task. Buildr has one such task (see Buildr#integration) that runs
485
+ # all tests marked with :integration=>true, and has a setup/teardown tasks separate from
486
+ # the unit tests.
487
+ class IntegrationTestsTask < Rake::Task
488
+
489
+ def initialize(*args) #:nodoc:
490
+ super
491
+ @setup = task("#{name}:setup")
492
+ @teardown = task("#{name}:teardown")
493
+ enhance do
494
+ info 'Running integration tests...'
495
+ TestTask.run_local_tests true
496
+ end
497
+ end
498
+
499
+ def execute(args) #:nodoc:
500
+ setup.invoke
501
+ begin
502
+ super
503
+ ensure
504
+ teardown.invoke
505
+ end
506
+ end
507
+
508
+ # :call-seq:
509
+ # setup(*prereqs) => task
510
+ # setup(*prereqs) { |task| .. } => task
511
+ #
512
+ # Returns the setup task. The setup task is executed before running the integration tests.
513
+ def setup(*prereqs, &block)
514
+ @setup.enhance prereqs, &block
515
+ end
516
+
517
+ # :call-seq:
518
+ # teardown(*prereqs) => task
519
+ # teardown(*prereqs) { |task| .. } => task
520
+ #
521
+ # Returns the teardown task. The teardown task is executed after running the integration tests.
522
+ def teardown(*prereqs, &block)
523
+ @teardown.enhance prereqs, &block
524
+ end
525
+
526
+ end
527
+
528
+
529
+ # Methods added to Project to support compilation and running of tests.
530
+ module Test
531
+
532
+ include Extension
533
+
534
+ first_time do
535
+ desc 'Run all tests'
536
+ task('test') { TestTask.run_local_tests false }
537
+
538
+ # This rule takes a suffix and runs that tests in the current project. For example;
539
+ # buildr test:MyTest
540
+ # will run the test com.example.MyTest, if such a test exists for this project.
541
+ #
542
+ # If you want to run multiple test, separate them with a comma. You can also use glob
543
+ # (* and ?) patterns to match multiple tests, see the TestTask#include method.
544
+ rule /^test:.*$/ do |task|
545
+ # The map works around a JRuby bug whereby the string looks fine, but fails in fnmatch.
546
+ TestTask.only_run task.name.scan(/test:(.*)/)[0][0].split(',').map { |t| "#{t}" }
547
+ task('test').invoke
548
+ end
549
+
550
+ IntegrationTestsTask.define_task('integration')
551
+
552
+ # Similar to test:[pattern] but for integration tests.
553
+ rule /^integration:.*$/ do |task|
554
+ unless task.name.split(':')[1] =~ /^(setup|teardown)$/
555
+ # The map works around a JRuby bug whereby the string looks fine, but fails in fnmatch.
556
+ TestTask.only_run task.name[/integration:(.*)/, 1].split(',').map { |t| "#{t}" }
557
+ task('integration').invoke
558
+ end
559
+ end
560
+
561
+ end
562
+
563
+ before_define do |project|
564
+ # Define a recursive test task, and pass it a reference to the project so it can discover all other tasks.
565
+ test = TestTask.define_task('test')
566
+ test.send :associate_with, project
567
+
568
+ # Similar to the regular resources task but using different paths.
569
+ resources = ResourcesTask.define_task('test:resources')
570
+ resources.send :associate_with, project, :test
571
+ project.path_to(:source, :test, :resources).tap { |dir| resources.from dir if File.exist?(dir) }
572
+
573
+ # Similar to the regular compile task but using different paths.
574
+ compile = CompileTask.define_task('test:compile'=>[project.compile, resources])
575
+ compile.send :associate_with, project, :test
576
+ test.enhance [compile]
577
+
578
+ # Define these tasks once, otherwise we may get a namespace error.
579
+ test.setup ; test.teardown
580
+ end
581
+
582
+ after_define do |project|
583
+ test = project.test
584
+ # Dependency on compiled tests and resources. Dependencies added using with.
585
+ test.dependencies.concat [test.compile.target, test.resources.target].compact
586
+ # Dependency on compiled code, its dependencies and resources.
587
+ test.with [project.compile.target, project.resources.target].compact
588
+ test.with project.compile.dependencies
589
+ # Picking up the test frameworks adds further dependencies.
590
+ test.framework
591
+
592
+ project.build test unless test.options[:integration]
593
+
594
+ project.clean do
595
+ rm_rf test.compile.target.to_s, :verbose=>false if test.compile.target
596
+ rm_rf test.report_to.to_s, :verbose=>false
597
+ end
598
+ end
599
+
600
+
601
+ # :call-seq:
602
+ # test(*prereqs) => TestTask
603
+ # test(*prereqs) { |task| .. } => TestTask
604
+ #
605
+ # Returns the test task. The test task controls the entire test lifecycle.
606
+ #
607
+ # You can use the test task in three ways. You can access and configure specific
608
+ # test tasks, e.g. enhance the compile task by calling test.compile, setup for
609
+ # the tests by enhancing test.setup and so forth.
610
+ #
611
+ # You can use convenient methods that handle the most common settings. For example,
612
+ # add dependencies using test.with, or include only specific tests using test.include.
613
+ #
614
+ # You can also enhance this task directly. This method accepts a list of arguments
615
+ # that are used as prerequisites and an optional block that will be executed by the
616
+ # test task.
617
+ #
618
+ # This task compiles the project and the tests (in that order) before running any tests.
619
+ # It execute the setup task, runs all the tests, any enhancements, and ends with the
620
+ # teardown tasks.
621
+ def test(*prereqs, &block)
622
+ task('test').enhance prereqs, &block
623
+ end
624
+
625
+ # :call-seq:
626
+ # integration { |task| .... }
627
+ # integration => IntegrationTestTask
628
+ #
629
+ # Use this method to return the integration tests task, or enhance it with a block to execute.
630
+ #
631
+ # There is one integration tests task you can execute directly, or as a result of running the package
632
+ # task (or tasks that depend on it, like install and deploy). It contains all the tests marked with
633
+ # :integration=>true, all other tests are considered unit tests and run by the test task before packaging.
634
+ # So essentially: build=>test=>packaging=>integration=>install/deploy.
635
+ #
636
+ # You add new tests from projects that define integration tests using the regular test task,
637
+ # but with the following addition:
638
+ # test.using :integration
639
+ #
640
+ # Use this method to enhance the setup and teardown tasks that are executed before (and after) all
641
+ # integration tests are run, for example, to start a Web server or create a database.
642
+ def integration(*deps, &block)
643
+ Rake::Task['rake:integration'].enhance deps, &block
644
+ end
645
+
646
+ end
647
+
648
+
649
+ # :call-seq:
650
+ # integration { |task| .... }
651
+ # integration => IntegrationTestTask
652
+ #
653
+ # Use this method to return the integration tests task.
654
+ def integration(*deps, &block)
655
+ Rake::Task['rake:integration'].enhance deps, &block
656
+ end
657
+
658
+ class Options
659
+
660
+ # Runs tests after the build when true (default). This forces tests to execute
661
+ # after the build, including when running build related tasks like install, deploy and release.
662
+ #
663
+ # Set to false to not run any tests. Set to :all to run all tests, ignoring failures.
664
+ #
665
+ # This option is set from the environment variable 'test', so you can also do:
666
+
667
+ # Returns the test option (environment variable TEST). Possible values are:
668
+ # * :false -- Do not run any tests (also accepts 'no' and 'skip').
669
+ # * :true -- Run all tests, stop on failure (default if not set).
670
+ # * :all -- Run all tests, ignore failures.
671
+ def test
672
+ case value = ENV['TEST'] || ENV['test']
673
+ when /^(no|off|false|skip)$/i
674
+ false
675
+ when /^all$/i
676
+ :all
677
+ when /^(yes|on|true)$/i, nil
678
+ true
679
+ else
680
+ warn "Expecting the environment variable test to be 'no' or 'all', not sure what to do with #{value}, so I'm just going to run all the tests and stop at failure."
681
+ true
682
+ end
683
+ end
684
+
685
+ # Sets the test option (environment variable TEST). Possible values are true, false or :all.
686
+ #
687
+ # You can also set this from the environment variable, e.g.:
688
+ #
689
+ # buildr # With tests
690
+ # buildr test=no # Without tests
691
+ # buildr test=all # Ignore failures
692
+ # set TEST=no
693
+ # buildr # Without tests
694
+ def test=(flag)
695
+ ENV['test'] = nil
696
+ ENV['TEST'] = flag.to_s
697
+ end
698
+
699
+ end
700
+
701
+ Buildr.help << <<-HELP
702
+ To run a full build without running any tests:
703
+ buildr test=no
704
+ To run specific test:
705
+ buildr test:MyTest
706
+ To run integration tests:
707
+ buildr integration
708
+ HELP
709
+
710
+ end
711
+
712
+
713
+ class Buildr::Project
714
+ include Buildr::Test
715
+ end