Buildr C0 Coverage Information - RCov

lib/buildr/core/test.rb

Name Total Lines Lines of Code Total Coverage Code Coverage
lib/buildr/core/test.rb 843 427
19.45%
26.23%

Key

Code reported as executed by Ruby looks like this...and this: this line is also marked as covered.Lines considered as run by rcov, but not reported by Ruby, look like this,and this: these lines were inferred by rcov (using simple heuristics).Finally, here's a line marked as not executed.

Coverage Details

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 = wildcardify(tests)
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 
180       # Used by the test/integration rule to only run tests that failed the last time.
181       def only_run_failed() #:nodoc:
182         # Since the tests may reside in a sub-project, we need to set the include/exclude pattern on
183         # all sub-projects, but only invoke test on the local project.
184         Project.projects.each { |project| project.test.send :only_run_failed }
185       end
186 
187       # Used by the test/integration rule to clear all previously included/excluded tests.
188       def clear()
189         Project.projects.each do |project|
190           project.test.send :clear
191         end
192       end
193 
194       # Used by the test/integration to include specific tests
195       def include(includes)
196         includes = wildcardify(Array(includes))
197         Project.projects.each do |project|
198           project.test.send :include, *includes if includes.size > 0
199           project.test.send :forced_need=, true
200         end
201       end
202 
203       # Used by the test/integration to exclude specific tests
204       def exclude(excludes)
205         excludes = wildcardify(Array(excludes))
206         Project.projects.each do |project|
207           project.test.send :exclude, *excludes if excludes.size > 0
208           project.test.send :forced_need=, true
209         end
210       end
211 
212     private
213 
214       def wildcardify(strings)
215         strings.map { |name| name =~ /\*/ ? name : "*#{name}*" }
216       end
217     end
218 
219     # Default options already set on each test task.
220     def default_options
221       { :fail_on_failure=>true, :fork=>:once, :properties=>{}, :environment=>{} }
222     end
223 
224     def initialize(*args) #:nodoc:
225       super
226       @dependencies = FileList[]
227       @include = []
228       @exclude = []
229       @forced_need = false
230       parent_task = Project.parent_task(name)
231       if parent_task.respond_to?(:options)
232         @options = OpenObject.new { |hash, key| hash[key] = parent_task.options[key].clone rescue hash[key] = parent_task.options[key] }
233       else
234         @options = OpenObject.new(default_options)
235       end
236 
237       unless ENV["IGNORE_BUILDFILE"] =~ /(true)|(yes)/i
238         enhance [ application.buildfile.name ]
239         enhance application.buildfile.prerequisites
240       end
241       enhance do
242         run_tests if framework
243       end
244     end
245 
246     # The dependencies used for running the tests. Includes the compiled files (compile.target)
247     # and their dependencies. Will also include anything you pass to #with, shared between the
248     # testing compile and run dependencies.
249     attr_accessor :dependencies
250 
251     # *Deprecated*: Use dependencies instead.
252     def classpath
253       Buildr.application.deprecated 'Use dependencies instead.'
254       @dependencies
255     end
256 
257     # *Deprecated*: Use dependencies= instead.
258     def classpath=(artifacts)
259       Buildr.application.deprecated 'Use dependencies= instead.'
260       @dependencies = artifacts
261     end
262 
263     def execute(args) #:nodoc:
264       if Buildr.options.test == false
265         info "Skipping tests for #{project.name}"
266         return
267       end
268       setup.invoke
269       begin
270         super
271       rescue RuntimeError
272         raise if options[:fail_on_failure] && Buildr.options.test != :all
273       ensure
274         teardown.invoke
275       end
276     end
277 
278     # :call-seq:
279     #   compile(*sources) => CompileTask
280     #   compile(*sources) { |task| .. } => CompileTask
281     #
282     # The compile task is similar to the Project's compile task. However, it compiles all
283     # files found in the src/test/{source} directory into the target/test/{code} directory.
284     # This task is executed by the test task before running any tests.
285     #
286     # Once the project definition is complete, all dependencies from the regular
287     # compile task are copied over, so you only need to specify dependencies
288     # specific to your tests. You can do so by calling #with on the test task.
289     # The dependencies used here are also copied over to the junit task.
290     def compile(*sources, &block)
291       @project.task('test:compile').from(sources).enhance &block
292     end
293 
294     # :call-seq:
295     #   resources(*prereqs) => ResourcesTask
296     #   resources(*prereqs) { |task| .. } => ResourcesTask
297     #
298     # Executes by the #compile task to copy resource files over. See Project#resources.
299     def resources(*prereqs, &block)
300       @project.task('test:resources').enhance prereqs, &block
301     end
302 
303     # :call-seq:
304     #   setup(*prereqs) => task
305     #   setup(*prereqs) { |task| .. } => task
306     #
307     # Returns the setup task. The setup task is executed at the beginning of the test task,
308     # after compiling the test files.
309     def setup(*prereqs, &block)
310       @project.task('test:setup').enhance prereqs, &block
311     end
312 
313     # :call-seq:
314     #   teardown(*prereqs) => task
315     #   teardown(*prereqs) { |task| .. } => task
316     #
317     # Returns the teardown task. The teardown task is executed at the end of the test task.
318     def teardown(*prereqs, &block)
319       @project.task('test:teardown').enhance prereqs, &block
320     end
321 
322     # :call-seq:
323     #   with(*specs) => self
324     #
325     # Specify artifacts (specs, tasks, files, etc) to include in the dependencies list
326     # when compiling and running tests.
327     def with(*artifacts)
328       @dependencies |= Buildr.artifacts(artifacts.flatten).uniq
329       compile.with artifacts
330       self
331     end
332 
333     # Returns various test options.
334     attr_reader :options
335 
336     # :call-seq:
337     #   using(options) => self
338     #
339     # Sets various test options from a hash and returns self.  For example:
340     #   test.using :fork=>:each, :properties=>{ 'url'=>'http://localhost:8080' }
341     #
342     # Can also be used to select the test framework, or to run these tests as
343     # integration tests.  For example:
344     #   test.using :testng
345     #   test.using :integration
346     #
347     # The :fail_on_failure option specifies whether the task should fail if
348     # any of the tests fail (default), or should report the failures but continue
349     # running the build (when set to false).
350     #
351     # All other options depend on the capability of the test framework.  These options
352     # should be used the same way across all frameworks that support them:
353     # * :fork -- Fork once for each project (:once, default), for each test in each
354     #     project (:each), or don't fork at all (false).
355     # * :properties -- Properties pass to the test, e.g. in Java as system properties.
356     # * :environment -- Environment variables.  This hash is made available in the
357     #     form of environment variables.
358     def using(*args)
359       args.pop.each { |key, value| options[key.to_sym] = value } if Hash === args.last
360       args.each do |name|
361         if TestFramework.has?(name)
362           self.framework = name
363         elsif name == :integration
364           options[:integration] = true
365         else
366           Buildr.application.deprecated "Please replace with using(:#{name}=>true)"
367           options[name.to_sym] = true
368         end
369       end
370       self
371     end
372 
373     # :call-seq:
374     #   include(*names) => self
375     #
376     # Include only the specified tests. Unless specified, the default is to include
377     # all tests identified by the test framework. This method accepts multiple arguments
378     # and returns self.
379     #
380     # Tests are specified by their full name, but you can use glob patterns to select
381     # multiple tests, for example:
382     #   test.include 'com.example.FirstTest'  # FirstTest only
383     #   test.include 'com.example.*'          # All tests under com/example
384     #   test.include 'com.example.Module*'    # All tests starting with Module
385     #   test.include '*.{First,Second}Test'   # FirstTest, SecondTest
386     def include(*names)
387       @include += names
388       self
389     end
390 
391     # :call-seq:
392     #   exclude(*names) => self
393     #
394     # Exclude the specified tests. This method accepts multiple arguments and returns self.
395     # See #include for the type of arguments you can use.
396     def exclude(*names)
397       @exclude += names
398       self
399     end
400 
401     # Clear all test includes and excludes and returns self
402     def clear
403       @include = []
404       @exclude = []
405       self
406     end
407 
408     # *Deprecated*: Use tests instead.
409     def classes
410       Buildr.application.deprecated 'Call tests instead of classes'
411       tests
412     end
413 
414     # After running the task, returns all tests selected to run, based on availability and include/exclude pattern.
415     attr_reader :tests
416     # After running the task, returns all the tests that failed, empty array if all tests passed.
417     attr_reader :failed_tests
418     # After running the task, returns all the tests that passed, empty array if no tests passed.
419     attr_reader :passed_tests
420 
421     # :call-seq:
422     #   framework => symbol
423     #
424     # Returns the test framework, e.g. :junit, :testng.
425     def framework
426       unless @framework
427         # Start with all frameworks that apply (e.g. JUnit and TestNG for Java),
428         # and pick the first (default) one, unless already specified in parent project.
429         candidates = TestFramework.frameworks.select { |cls| cls.applies_to?(@project) }
430         candidate = @project.parent && candidates.detect { |framework| framework.to_sym == @project.parent.test.framework } ||
431           candidates.first
432         self.framework = candidate if candidate
433       end
434       @framework && @framework.class.to_sym
435     end
436 
437     # :call-seq:
438     #   report_to => file
439     #
440     # Test frameworks that can produce reports, will write them to this directory.
441     #
442     # This is framework dependent, so unless you use the default test framework, call this method
443     # after setting the test framework.
444     def report_to
445       @report_to ||= file(@project.path_to(:reports, framework)=>self)
446     end
447 
448     # :call-seq:
449     #   failures_to => file
450     #
451     # We record the list of failed tests for the current framework in this file.
452     #
453     #
454     def failures_to
455       @failures_to ||= file(@project.path_to(:target, "#{framework}-failed")=>self)
456     end
457 
458     # :call-seq:
459     #    last_failures => array
460     #
461     # We read the last test failures if any and return them.
462     #
463     def last_failures
464       @last_failures ||= failures_to.exist? ? File.read(failures_to.to_s).split("\n") : []
465     end
466 
467     # The path to the file that stores the time stamp of the last successful test run.
468     def last_successful_run_file #:nodoc:
469       File.join(report_to.to_s, 'last_successful_run')
470     end
471 
472     # The time stamp of the last successful test run.  Or Rake::EARLY if no successful test run recorded.
473     def timestamp #:nodoc:
474       File.exist?(last_successful_run_file) ? File.mtime(last_successful_run_file) : Rake::EARLY
475     end
476 
477     # The project this task belongs to.
478     attr_reader :project
479 
480     # Whether the tests are forced
481     attr_accessor :forced_need
482 
483   protected
484 
485     def associate_with(project)
486       @project = project
487     end
488 
489     def framework=(name)
490       cls = TestFramework.select(name) or raise ArgumentError, "No #{name} test framework available. Did you install it?"
491       #cls.inherit_options.reject { |name| options.has_key?(name) }.
492       #  each { |name| options[name] = @parent_task.options[name] } if @parent_task.respond_to?(:options)
493       @framework = cls.new(self, options)
494       # Test framework dependency.
495       with @framework.dependencies
496     end
497 
498     # :call-seq:
499     #   include?(name) => boolean
500     #
501     # Returns true if the specified test name matches the inclusion/exclusion pattern. Used to determine
502     # which tests to execute.
503     def include?(name)
504       ((@include.empty? && !@forced_need)|| @include.any? { |pattern| File.fnmatch(pattern, name) }) &&
505         !@exclude.any? { |pattern| File.fnmatch(pattern, name) }
506     end
507 
508     # Runs the tests using the selected test framework.
509     def run_tests
510       dependencies = (Buildr.artifacts(self.dependencies + compile.dependencies) + [compile.target]).map(&:to_s).uniq
511       rm_rf report_to.to_s
512       rm_rf failures_to.to_s
513       @tests = @framework.tests(dependencies).select { |test| include?(test) }.sort
514       if @tests.empty?
515         @passed_tests, @failed_tests = [], []
516       else
517         info "Running tests in #{@project.name}"
518         begin
519           # set the baseDir system property if not set
520           @framework.options[:properties] = { 'baseDir' => compile.target.to_s }.merge(@framework.options[:properties] || {})
521           @passed_tests = @framework.run(@tests, dependencies)
522         rescue Exception=>ex
523           error "Test framework error: #{ex.message}"
524           error ex.backtrace.join("\n") if trace?
525           @passed_tests = []
526         end
527         @failed_tests = @tests - @passed_tests
528         unless @failed_tests.empty?
529           Buildr::write(failures_to.to_s, @failed_tests.join("\n"))
530           error "The following tests failed:\n#{@failed_tests.join("\n")}"
531           fail 'Tests failed!'
532         end
533       end
534       record_successful_run unless @forced_need
535     end
536 
537     # Call this method when a test run is successful to record the current system time.
538     def record_successful_run #:nodoc:
539       mkdir_p report_to.to_s
540       touch last_successful_run_file
541     end
542 
543     # Limit running tests to specific list.
544     def only_run(tests)
545       @include = Array(tests)
546       @exclude.clear
547       @forced_need = true
548     end
549 
550     # Limit running tests to those who failed the last time.
551     def only_run_failed()
552       @include = Array(last_failures)
553       @forced_need = true
554     end
555 
556     def invoke_prerequisites(args, chain) #:nodoc:
557       @prerequisites |= FileList[@dependencies.uniq]
558       super
559     end
560 
561     def needed? #:nodoc:
562       latest_prerequisite = @prerequisites.map { |p| application[p, @scope] }.max { |a,b| a.timestamp<=>b.timestamp }
563       needed = (timestamp == Rake::EARLY) || latest_prerequisite.timestamp > timestamp
564       trace "Testing#{needed ? ' ' : ' not '}needed. " +
565         "Latest prerequisite change: #{latest_prerequisite.timestamp} (#{latest_prerequisite.to_s}). " +
566         "Last successful test run: #{timestamp}."
567       return needed || @forced_need || Buildr.options.test == :all
568     end
569   end
570 
571 
572   # The integration tests task. Buildr has one such task (see Buildr#integration) that runs
573   # all tests marked with :integration=>true, and has a setup/teardown tasks separate from
574   # the unit tests.
575   class IntegrationTestsTask < Rake::Task
576 
577     def initialize(*args) #:nodoc:
578       super
579       @setup = task("#{name}:setup")
580       @teardown = task("#{name}:teardown")
581       enhance do
582         info 'Running integration tests...'
583         TestTask.run_local_tests true
584       end
585     end
586 
587     def execute(args) #:nodoc:
588       setup.invoke
589       begin
590         super
591       ensure
592         teardown.invoke
593       end
594     end
595 
596     # :call-seq:
597     #   setup(*prereqs) => task
598     #   setup(*prereqs) { |task| .. } => task
599     #
600     # Returns the setup task. The setup task is executed before running the integration tests.
601     def setup(*prereqs, &block)
602       @setup.enhance prereqs, &block
603     end
604 
605     # :call-seq:
606     #   teardown(*prereqs) => task
607     #   teardown(*prereqs) { |task| .. } => task
608     #
609     # Returns the teardown task. The teardown task is executed after running the integration tests.
610     def teardown(*prereqs, &block)
611       @teardown.enhance prereqs, &block
612     end
613 
614   end
615 
616 
617   # Methods added to Project to support compilation and running of tests.
618   module Test
619 
620     include Extension
621 
622     first_time do
623       desc 'Run all tests'
624       task('test') { TestTask.run_local_tests false }
625 
626       desc 'Run failed tests'
627       task('test:failed') {
628         TestTask.only_run_failed
629         task('test').invoke
630       }
631 
632       # This rule takes a suffix and runs that tests in the current project. For example;
633       #   buildr test:MyTest
634       # will run the test com.example.MyTest, if such a test exists for this project.
635       #
636       # If you want to run multiple test, separate them with a comma. You can also use glob
637       # (* and ?) patterns to match multiple tests, see the TestTask#include method.
638       rule /^test:.*$/ do |task|
639         # The map works around a JRuby bug whereby the string looks fine, but fails in fnmatch.
640         tests = task.name.scan(/test:(.*)/)[0][0].split(',').map(&:to_s)
641         excludes, includes = tests.partition { |t| t =~ /^-/ }
642         if excludes.empty?
643           TestTask.only_run includes
644         else
645           # remove leading '-'
646           excludes.map! { |t| t[1..-1] }
647 
648           TestTask.clear
649           TestTask.include(includes.empty? ? ['*'] : includes)
650           TestTask.exclude excludes
651         end
652         task('test').invoke
653       end
654 
655       IntegrationTestsTask.define_task('integration')
656 
657       # Similar to test:[pattern] but for integration tests.
658       rule /^integration:.*$/ do |task|
659         unless task.name.split(':')[1] =~ /^(setup|teardown)$/
660           # The map works around a JRuby bug whereby the string looks fine, but fails in fnmatch.
661           TestTask.only_run task.name[/integration:(.*)/, 1].split(',').map { |t| "#{t}" }
662           task('integration').invoke
663         end
664       end
665 
666     end
667 
668     before_define(:test) do |project|
669       # Define a recursive test task, and pass it a reference to the project so it can discover all other tasks.
670       test = TestTask.define_task('test')
671       test.send :associate_with, project
672 
673       # Similar to the regular resources task but using different paths.
674       resources = ResourcesTask.define_task('test:resources')
675       resources.send :associate_with, project, :test
676       project.path_to(:source, :test, :resources).tap { |dir| resources.from dir if File.exist?(dir) }
677 
678       # We define a module inline that will inject cancelling the task if tests are skipped.
679       module SkipIfNoTest
680 
681         def self.extended(base)
682           base.instance_eval {alias :execute_before_skip_if_no_test :execute}
683           base.instance_eval {alias :execute :execute_after_skip_if_no_test}
684         end
685 
686         def execute_after_skip_if_no_test(args) #:nodoc:
687           if Buildr.options.test == false
688             trace "Skipping #{to_s} for #{project.name} as tests are skipped"
689             return
690           end
691           execute_before_skip_if_no_test(args)
692         end
693       end
694 
695       # Similar to the regular compile task but using different paths.
696       compile = CompileTask.define_task('test:compile'=>[project.compile, resources])
697       compile.extend SkipIfNoTest
698       compile.send :associate_with, project, :test
699       test.enhance [compile]
700 
701       # Define these tasks once, otherwise we may get a namespace error.
702       test.setup ; test.teardown
703     end
704 
705 
706 
707     after_define(:test => :compile) do |project|
708       test = project.test
709       # Dependency on compiled tests and resources.  Dependencies added using with.
710       test.dependencies.concat [test.compile.target, test.resources.target].compact
711       test.dependencies.concat test.compile.dependencies
712       # Dependency on compiled code, its dependencies and resources.
713       test.with [project.compile.target, project.resources.target].compact
714       test.with project.compile.dependencies
715       # Picking up the test frameworks adds further dependencies.
716       test.framework
717 
718       project.build test unless test.options[:integration] || Buildr.options.test == :only
719 
720       project.clean do
721         rm_rf test.compile.target.to_s if test.compile.target
722         rm_rf test.report_to.to_s
723       end
724     end
725 
726 
727     # :call-seq:
728     #   test(*prereqs) => TestTask
729     #   test(*prereqs) { |task| .. } => TestTask
730     #
731     # Returns the test task. The test task controls the entire test lifecycle.
732     #
733     # You can use the test task in three ways. You can access and configure specific
734     # test tasks, e.g. enhance the compile task by calling test.compile, setup for
735     # the tests by enhancing test.setup and so forth.
736     #
737     # You can use convenient methods that handle the most common settings. For example,
738     # add dependencies using test.with, or include only specific tests using test.include.
739     #
740     # You can also enhance this task directly. This method accepts a list of arguments
741     # that are used as prerequisites and an optional block that will be executed by the
742     # test task.
743     #
744     # This task compiles the project and the tests (in that order) before running any tests.
745     # It execute the setup task, runs all the tests, any enhancements, and ends with the
746     # teardown tasks.
747     def test(*prereqs, &block)
748       task('test').enhance prereqs, &block
749     end
750 
751     # :call-seq:
752     #   integration { |task| .... }
753     #   integration => IntegrationTestTask
754     #
755     # Use this method to return the integration tests task, or enhance it with a block to execute.
756     #
757     # There is one integration tests task you can execute directly, or as a result of running the package
758     # task (or tasks that depend on it, like install and upload). It contains all the tests marked with
759     # :integration=>true, all other tests are considered unit tests and run by the test task before packaging.
760     # So essentially: build=>test=>packaging=>integration=>install/upload.
761     #
762     # You add new tests from projects that define integration tests using the regular test task,
763     # but with the following addition:
764     #   test.using :integration
765     #
766     # Use this method to enhance the setup and teardown tasks that are executed before (and after) all
767     # integration tests are run, for example, to start a Web server or create a database.
768     def integration(*deps, &block)
769       Rake::Task['rake:integration'].enhance deps, &block
770     end
771 
772   end
773 
774 
775   # :call-seq:
776   #   integration { |task| .... }
777   #   integration => IntegrationTestTask
778   #
779   # Use this method to return the integration tests task.
780   def integration(*deps, &block)
781     Rake::Task['rake:integration'].enhance deps, &block
782   end
783 
784   class Options
785 
786     # Runs tests after the build when true (default). This forces tests to execute
787     # after the build, including when running build related tasks like install, upload and release.
788     #
789     # Set to false to not run any tests. Set to :all to run all tests, ignoring failures.
790     #
791     # This option is set from the environment variable 'test', so you can also do:
792 
793     # Returns the test option (environment variable TEST). Possible values are:
794     # * :false -- Do not run any tests (also accepts 'no' and 'skip').
795     # * :true -- Run all tests, stop on failure (default if not set).
796     # * :all -- Run all tests, ignore failures.
797     def test
798       case value = ENV['TEST'] || ENV['test']
799       when /^(no|off|false|skip)$/i
800         false
801       when /^all$/i
802         :all
803       when /^only$/i
804         :only
805       when /^(yes|on|true)$/i, nil
806         true
807       else
808         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."
809         true
810       end
811     end
812 
813     # Sets the test option (environment variable TEST). Possible values are true, false or :all.
814     #
815     # You can also set this from the environment variable, e.g.:
816     #
817     #   buildr          # With tests
818     #   buildr test=no  # Without tests
819     #   buildr test=all # Ignore failures
820     #   set TEST=no
821     #   buildr          # Without tests
822     def test=(flag)
823       ENV['test'] = nil
824       ENV['TEST'] = flag.to_s
825     end
826 
827   end
828 
829   Buildr.help << <<-HELP
830 To run a full build without running any tests:
831   buildr test=no
832 To run specific test:
833   buildr test:MyTest
834 To run integration tests:
835   buildr integration
836     HELP
837 
838 end
839 
840 
841 class Buildr::Project
842   include Buildr::Test
843 end

Generated on 2011-07-06 23:35:37 -0700 with rcov 0.9.8