Skip to content
This repository
Browse code

RSpec additions, do we need the Sandbox and SpecHelpers of buildr its…

…elf, or can we test without?

I've added them @ spec/sandbox.rb & spec/spec_helpers.rb
  • Loading branch information...
commit a5c17b05147a7d9c80c39faad548ce15eddd87b8 1 parent b39f625
Dominic Graefen authored
5 Gemfile
@@ -10,6 +10,7 @@ group :development do
10 10 gem "bundler", "~> 1.0.0"
11 11 gem "jeweler", "~> 1.5.2"
12 12 gem "buildr", "~> 1.4.6"
13   - gem "rcov", ">= 0"
14   - gem "rspec"
  13 + #gem "rcov", ">= 0"
  14 + gem "rspec", "~> 2.1.0"
  15 + gem "ci_reporter", "~> 1.6.5"
15 16 end
26 Rakefile
@@ -22,21 +22,25 @@ Jeweler::Tasks.new do |gem|
22 22 end
23 23 Jeweler::RubygemsDotOrgTasks.new
24 24
25   -require 'rake/testtask'
26   -Rake::TestTask.new(:test) do |test|
27   - test.libs << 'lib' << 'test'
28   - test.pattern = 'test/**/test_*.rb'
29   - test.verbose = true
  25 +require 'rspec/core'
  26 +require 'rspec/core/rake_task'
  27 +require 'ci/reporter/rake/rspec'
  28 +
  29 +ENV["CI_REPORTS"] ||= File.expand_path( File.join( File.dirname(__FILE__), "test", "report" ) )
  30 +RSpec::Core::RakeTask.new(:spec) do |spec|
  31 + spec.pattern = FileList['spec/**/*_spec.rb']
30 32 end
31 33
32   -require 'rcov/rcovtask'
33   -Rcov::RcovTask.new do |test|
34   - test.libs << 'test'
35   - test.pattern = 'test/**/test_*.rb'
36   - test.verbose = true
  34 +task :spec => "ci:setup:rspec"
  35 +
  36 +RSpec::Core::RakeTask.new(:rcov) do |spec|
  37 + spec.pattern = 'spec/**/*_spec.rb'
  38 + spec.rcov = true
37 39 end
38 40
39   -task :default => :test
  41 +task :test => :spec
  42 +task :default => :spec
  43 +
40 44
41 45 require 'rake/rdoctask'
42 46 Rake::RDocTask.new do |rdoc|
252 spec/as3/mxml_spec.rb
... ... @@ -0,0 +1,252 @@
  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 File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helpers'))
  18 +
  19 +
  20 +describe 'javac compiler' do
  21 + it 'should identify itself from source directories' do
  22 + write 'src/main/java/com/example/Test.java', 'package com.example; class Test {}'
  23 + define('foo').compile.compiler.should eql(:javac)
  24 + end
  25 +
  26 + it 'should identify from source directories using custom layout' do
  27 + write 'src/com/example/Code.java', 'package com.example; class Code {}'
  28 + write 'testing/com/example/Test.java', 'package com.example; class Test {}'
  29 + custom = Layout.new
  30 + custom[:source, :main, :java] = 'src'
  31 + custom[:source, :test, :java] = 'testing'
  32 + define 'foo', :layout=>custom do
  33 + compile.compiler.should eql(:javac)
  34 + test.compile.compiler.should eql(:javac)
  35 + end
  36 + end
  37 +
  38 + it 'should identify from compile source directories' do
  39 + write 'src/com/example/Code.java', 'package com.example; class Code {}'
  40 + write 'testing/com/example/Test.java', 'package com.example; class Test {}'
  41 + define 'foo' do
  42 + lambda { compile.from 'src' }.should change { compile.compiler }.to(:javac)
  43 + lambda { test.compile.from 'testing' }.should change { test.compile.compiler }.to(:javac)
  44 + end
  45 + end
  46 +
  47 + it 'should report the language as :java' do
  48 + define('foo').compile.using(:javac).language.should eql(:java)
  49 + end
  50 +
  51 + it 'should set the target directory to target/classes' do
  52 + define 'foo' do
  53 + lambda { compile.using(:javac) }.should change { compile.target.to_s }.to(File.expand_path('target/classes'))
  54 + end
  55 + end
  56 +
  57 + it 'should not override existing target directory' do
  58 + define 'foo' do
  59 + compile.into('classes')
  60 + lambda { compile.using(:javac) }.should_not change { compile.target }
  61 + end
  62 + end
  63 +
  64 + it 'should not change existing list of sources' do
  65 + define 'foo' do
  66 + compile.from('sources')
  67 + lambda { compile.using(:javac) }.should_not change { compile.sources }
  68 + end
  69 + end
  70 +
  71 + it 'should include classpath dependencies' do
  72 + write 'src/dependency/Dependency.java', 'class Dependency {}'
  73 + define 'dependency', :version=>'1.0' do
  74 + compile.from('src/dependency').into('target/dependency')
  75 + package(:jar)
  76 + end
  77 + write 'src/test/DependencyTest.java', 'class DependencyTest { Dependency _var; }'
  78 + define('foo').compile.from('src/test').with(project('dependency')).invoke
  79 + file('target/classes/DependencyTest.class').should exist
  80 + end
  81 +
  82 + it 'should include tools.jar dependency' do
  83 + write 'src/main/java/UseApt.java', <<-JAVA
  84 + import com.sun.mirror.apt.AnnotationProcessor;
  85 + public class UseApt { }
  86 + JAVA
  87 + define('foo').compile.invoke
  88 + file('target/classes/UseApt.class').should exist
  89 + end
  90 +end
  91 +
  92 +
  93 +describe 'javac compiler options' do
  94 + def compile_task
  95 + @compile_task ||= define('foo').compile.using(:javac)
  96 + end
  97 +
  98 + def javac_args
  99 + compile_task.instance_eval { @compiler }.send(:javac_args)
  100 + end
  101 +
  102 + it 'should set warnings option to false by default' do
  103 + compile_task.options.warnings.should be_false
  104 + end
  105 +
  106 + it 'should set warnings option to true when running with --verbose option' do
  107 + verbose true
  108 + compile_task.options.warnings.should be_false
  109 + end
  110 +
  111 + it 'should use -nowarn argument when warnings is false' do
  112 + compile_task.using(:warnings=>false)
  113 + javac_args.should include('-nowarn')
  114 + end
  115 +
  116 + it 'should not use -nowarn argument when warnings is true' do
  117 + compile_task.using(:warnings=>true)
  118 + javac_args.should_not include('-nowarn')
  119 + end
  120 +
  121 + it 'should not use -verbose argument by default' do
  122 + javac_args.should_not include('-verbose')
  123 + end
  124 +
  125 + it 'should use -verbose argument when running with --trace=javac option' do
  126 + Buildr.application.options.trace_categories = [:javac]
  127 + javac_args.should include('-verbose')
  128 + end
  129 +
  130 + it 'should set debug option to true by default' do
  131 + compile_task.options.debug.should be_true
  132 + end
  133 +
  134 + it 'should set debug option to false based on Buildr.options' do
  135 + Buildr.options.debug = false
  136 + compile_task.options.debug.should be_false
  137 + end
  138 +
  139 + it 'should set debug option to false based on debug environment variable' do
  140 + ENV['debug'] = 'no'
  141 + compile_task.options.debug.should be_false
  142 + end
  143 +
  144 + it 'should set debug option to false based on DEBUG environment variable' do
  145 + ENV['DEBUG'] = 'no'
  146 + compile_task.options.debug.should be_false
  147 + end
  148 +
  149 + it 'should use -g argument when debug option is true' do
  150 + compile_task.using(:debug=>true)
  151 + javac_args.should include('-g')
  152 + end
  153 +
  154 + it 'should not use -g argument when debug option is false' do
  155 + compile_task.using(:debug=>false)
  156 + javac_args.should_not include('-g')
  157 + end
  158 +
  159 + it 'should set deprecation option to false by default' do
  160 + compile_task.options.deprecation.should be_false
  161 + end
  162 +
  163 + it 'should use -deprecation argument when deprecation is true' do
  164 + compile_task.using(:deprecation=>true)
  165 + javac_args.should include('-deprecation')
  166 + end
  167 +
  168 + it 'should not use -deprecation argument when deprecation is false' do
  169 + compile_task.using(:deprecation=>false)
  170 + javac_args.should_not include('-deprecation')
  171 + end
  172 +
  173 + it 'should not set source option by default' do
  174 + compile_task.options.source.should be_nil
  175 + javac_args.should_not include('-source')
  176 + end
  177 +
  178 + it 'should not set target option by default' do
  179 + compile_task.options.target.should be_nil
  180 + javac_args.should_not include('-target')
  181 + end
  182 +
  183 + it 'should use -source nn argument if source option set' do
  184 + compile_task.using(:source=>'1.5')
  185 + javac_args.should include('-source', '1.5')
  186 + end
  187 +
  188 + it 'should use -target nn argument if target option set' do
  189 + compile_task.using(:target=>'1.5')
  190 + javac_args.should include('-target', '1.5')
  191 + end
  192 +
  193 + it 'should set lint option to false by default' do
  194 + compile_task.options.lint.should be_false
  195 + end
  196 +
  197 + it 'should use -lint argument if lint option is true' do
  198 + compile_task.using(:lint=>true)
  199 + javac_args.should include('-Xlint')
  200 + end
  201 +
  202 + it 'should use -lint argument with value of option' do
  203 + compile_task.using(:lint=>'all')
  204 + javac_args.should include('-Xlint:all')
  205 + end
  206 +
  207 + it 'should use -lint argument with value of option as array' do
  208 + compile_task.using(:lint=>['path', 'serial'])
  209 + javac_args.should include('-Xlint:path,serial')
  210 + end
  211 +
  212 + it 'should not set other option by default' do
  213 + compile_task.options.other.should be_nil
  214 + end
  215 +
  216 + it 'should pass other argument if other option is string' do
  217 + compile_task.using(:other=>'-Xprint')
  218 + javac_args.should include('-Xprint')
  219 + end
  220 +
  221 + it 'should pass other argument if other option is array' do
  222 + compile_task.using(:other=>['-Xstdout', 'msgs'])
  223 + javac_args.should include('-Xstdout', 'msgs')
  224 + end
  225 +
  226 + it 'should complain about options it doesn\'t know' do
  227 + write 'source/Test.java', 'class Test {}'
  228 + compile_task.using(:unknown=>'option')
  229 + lambda { compile_task.from('source').invoke }.should raise_error(ArgumentError, /no such option/i)
  230 + end
  231 +
  232 + it 'should inherit options from parent' do
  233 + define 'foo' do
  234 + compile.using(:warnings=>true, :debug=>true, :deprecation=>true, :source=>'1.5', :target=>'1.4')
  235 + define 'bar' do
  236 + compile.using(:javac)
  237 + compile.options.warnings.should be_true
  238 + compile.options.debug.should be_true
  239 + compile.options.deprecation.should be_true
  240 + compile.options.source.should eql('1.5')
  241 + compile.options.target.should eql('1.4')
  242 + end
  243 + end
  244 + end
  245 +
  246 + after do
  247 + Buildr.options.debug = nil
  248 + ENV.delete "debug"
  249 + ENV.delete "DEBUG"
  250 + end
  251 +end
  252 +
201 spec/sandbox.rb
... ... @@ -0,0 +1,201 @@
  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 +# The local repository we use for testing is void of any artifacts, which will break given
  18 +# that the code requires several artifacts. So we establish them first using the real local
  19 +# repository and cache these across test cases.
  20 +Buildr.application.instance_eval { @rakefile = File.expand_path('buildfile') }
  21 +repositories.remote << 'http://repo1.maven.org/maven2'
  22 +repositories.remote << 'http://scala-tools.org/repo-releases'
  23 +
  24 +# Force Scala version for specs; don't want to rely on SCALA_HOME
  25 +module Buildr::Scala
  26 + SCALA_VERSION_FOR_SPECS = ENV["SCALA_VERSION"] || "2.8.1"
  27 +end
  28 +Buildr.settings.build['scala.version'] = Buildr::Scala::SCALA_VERSION_FOR_SPECS
  29 +
  30 +# Add a 'require' here only for optional extensions, not for extensions that should be loaded by default.
  31 +require 'buildr/clojure'
  32 +require 'buildr/groovy'
  33 +require 'buildr/scala'
  34 +require 'buildr/bnd'
  35 +require 'buildr/jaxb_xjc'
  36 +
  37 +Java.load # Anything added to the classpath.
  38 +artifacts(
  39 + TestFramework.frameworks.map(&:dependencies).flatten,
  40 + JUnit.ant_taskdef,
  41 + Buildr::Groovy.dependencies,
  42 + Buildr::JaxbXjc.dependencies,
  43 + Buildr::Bnd.dependencies,
  44 + Buildr::Scala::Scalac.dependencies,
  45 + Buildr::Scala::Specs.dependencies,
  46 + Buildr::Shell::BeanShell.artifact,
  47 + Buildr::Clojure.dependencies
  48 +).each do |path|
  49 + file(path).invoke
  50 +end
  51 +
  52 +ENV['HOME'] = File.expand_path(File.join(File.dirname(__FILE__), '..', 'tmp', 'home'))
  53 +mkpath ENV['HOME']
  54 +
  55 +# Make Scala.version resilient to sandbox reset
  56 +module Buildr::Scala
  57 + DEFAULT_VERSION = SCALA_VERSION_FOR_SPECS
  58 +
  59 + class << self
  60 + def version
  61 + SCALA_VERSION_FOR_SPECS
  62 + end
  63 + end
  64 +
  65 + class Scalac
  66 + class << self
  67 + def use_installed?
  68 + false
  69 + end
  70 + end
  71 + end
  72 +end
  73 +
  74 +# We need to run all tests inside a _sandbox, tacking a snapshot of Buildr before the test,
  75 +# and restoring everything to its previous state after the test. Damn state changes.
  76 +module Sandbox
  77 +
  78 + class << self
  79 + attr_reader :tasks, :rules
  80 +
  81 + def included(spec)
  82 + spec.before(:each) { sandbox }
  83 + spec.after(:each) { reset }
  84 + end
  85 +
  86 + # Require an optional extension without letting its callbacks pollute the Project class.
  87 + def require_optional_extension(extension_require_path)
  88 + project_callbacks_without_extension = Project.class_eval { @global_callbacks }.dup
  89 + begin
  90 + require extension_require_path
  91 + ensure
  92 + Project.class_eval { @global_callbacks = project_callbacks_without_extension }
  93 + end
  94 + end
  95 + end
  96 +
  97 + @tasks = Buildr.application.tasks.collect do |original|
  98 + prerequisites = original.send(:prerequisites).map(&:to_s)
  99 + actions = original.instance_eval { @actions }.clone
  100 + lambda do
  101 + original.class.send(:define_task, original.name=>prerequisites).tap do |task|
  102 + task.comment = original.comment
  103 + actions.each { |action| task.enhance &action }
  104 + end
  105 + end
  106 + end
  107 + @rules = Buildr.application.instance_variable_get(:@rules)
  108 +
  109 + def sandbox
  110 + @_sandbox = {}
  111 +
  112 + # Create a temporary directory where we can create files, e.g,
  113 + # for projects, compilation. We need a place that does not depend
  114 + # on the current directory.
  115 + @_sandbox[:original_dir] = Dir.pwd
  116 + @temp = File.join(File.dirname(__FILE__), '../tmp')
  117 + FileUtils.mkpath @temp
  118 + Dir.chdir @temp
  119 +
  120 + ARGV.clear
  121 + Buildr.application = Buildr::Application.new
  122 + Sandbox.tasks.each { |block| block.call }
  123 + Buildr.application.instance_variable_set :@rules, Sandbox.rules.clone
  124 + Buildr.application.instance_eval { @rakefile = File.expand_path('buildfile') }
  125 +
  126 + @_sandbox[:load_path] = $LOAD_PATH.clone
  127 +
  128 + # clear RUBYOPT since bundler hooks into it
  129 + # e.g. RUBYOPT=-I/usr/lib/ruby/gems/1.8/gems/bundler-1.0.15/lib -rbundler/setup
  130 + # and so Buildr's own Gemfile configuration taints e.g., JRuby's environment
  131 + @_sandbox[:ruby_opt] = ENV["RUBYOPT"]
  132 + ENV["RUBYOPT"] = nil
  133 +
  134 + #@_sandbox[:loaded_features] = $LOADED_FEATURES.clone
  135 +
  136 + # Later on we'll want to lose all the on_define created during the test.
  137 + @_sandbox[:on_define] = Project.class_eval { (@on_define || []).dup }
  138 + @_sandbox[:extension_modules] = Project.class_eval { (@extension_modules || []).dup }
  139 + @_sandbox[:global_callbacks] = Project.class_eval { (@global_callbacks || []).dup }
  140 + @_sandbox[:layout] = Layout.default.clone
  141 +
  142 + # Create a local repository we can play with. However, our local repository will be void
  143 + # of some essential artifacts (e.g. JUnit artifacts required by build task), so we create
  144 + # these first (see above) and keep them across test cases.
  145 + @_sandbox[:artifacts] = Artifact.class_eval { @artifacts }.clone
  146 + @_sandbox[:local_repository] = Buildr.repositories.local
  147 + ENV['HOME'] = File.expand_path('home')
  148 + ENV['BUILDR_ENV'] = 'development'
  149 +
  150 + @_sandbox[:env_keys] = ENV.keys
  151 + ['DEBUG', 'TEST', 'HTTP_PROXY', 'HTTPS_PROXY', 'USER'].each { |k| ENV.delete(k) ; ENV.delete(k.downcase) }
  152 +
  153 + # By default, remote repository is user's own local M2 repository
  154 + # since we don't want to remotely download artifacts into the sandbox over and over
  155 + Buildr.repositories.instance_eval do
  156 + @remote = ["file://" + @local]
  157 + @local = @release_to = nil
  158 + end
  159 + Buildr.options.proxy.http = nil
  160 +
  161 + # Don't output crap to the console.
  162 + trace false
  163 + verbose false
  164 + end
  165 +
  166 + # Call this from teardown.
  167 + def reset
  168 + # Get rid of all the projects and the on_define blocks we used.
  169 + Project.clear
  170 +
  171 + on_define = @_sandbox[:on_define]
  172 + extension_modules = @_sandbox[:extension_modules]
  173 + global_callbacks = @_sandbox[:global_callbacks]
  174 +
  175 + Project.class_eval do
  176 + @on_define = on_define
  177 + @global_callbacks = global_callbacks
  178 + @extension_modules = extension_modules
  179 + end
  180 +
  181 + Layout.default = @_sandbox[:layout].clone
  182 +
  183 + $LOAD_PATH.replace @_sandbox[:load_path]
  184 + ENV["RUBYOPT"] = @_sandbox[:ruby_opt]
  185 +
  186 + FileUtils.rm_rf @temp
  187 + mkpath ENV['HOME']
  188 +
  189 + # Get rid of all artifacts.
  190 + @_sandbox[:artifacts].tap { |artifacts| Artifact.class_eval { @artifacts = artifacts } }
  191 +
  192 + Buildr.repositories.local = @_sandbox[:local_repository]
  193 +
  194 + # Restore options.
  195 + Buildr.options.test = nil
  196 + (ENV.keys - @_sandbox[:env_keys]).each { |key| ENV.delete key }
  197 +
  198 + Dir.chdir @_sandbox[:original_dir]
  199 + end
  200 +
  201 +end
369 spec/spec_helpers.rb
... ... @@ -0,0 +1,369 @@
  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 +# This file gets loaded twice when running 'spec spec/*' and not with pleasent results,
  18 +# so ignore the second attempt to load it.
  19 +unless defined?(SpecHelpers)
  20 +
  21 + require 'rubygems'
  22 +
  23 + # For testing we use the gem requirements specified on the buildr.gemspec
  24 + spec = Gem::Specification.load(File.expand_path('../buildr.gemspec', File.dirname(__FILE__)))
  25 + # Dependency.version_requirements deprecated in rubygems 1.3.6
  26 + spec.dependencies.select {|dep| dep.type == :runtime }.each { |dep| gem dep.name, (dep.respond_to?(:requirement) ? dep.requirement.to_s : dep.version_requirements.to_s) }
  27 +
  28 + # Make sure to load from these paths first, we don't want to load any
  29 + # code from Gem library.
  30 + $LOAD_PATH.unshift File.expand_path('../lib', File.dirname(__FILE__)),
  31 + File.expand_path('../addon', File.dirname(__FILE__))
  32 +
  33 + # Buildr uses autoload extensively, but autoload when running specs creates
  34 + # a problem -- we sandbox $LOADED_FEATURES, so we endup autoloading the same
  35 + # module twice. This turns autoload into a require, which is not the right
  36 + # thing, but will do for now.
  37 + def autoload(symbol, path)
  38 + require path
  39 + end
  40 + require 'buildr'
  41 + # load ecj
  42 + require 'buildr/java/ecj'
  43 + #Make ecj appear as a compiler that doesn't apply:
  44 + class Buildr::Compiler::Ecj
  45 + class << self
  46 + def applies_to?(project, task)
  47 + false
  48 + end
  49 + end
  50 + end
  51 +
  52 + # Give a chance for plugins to do a few things before requiring the sandbox.
  53 + include SandboxHook if defined?(SandboxHook)
  54 +
  55 + require File.expand_path('sandbox', File.dirname(__FILE__))
  56 +
  57 + module SpecHelpers
  58 +
  59 + include Checks::Matchers
  60 +
  61 + [:info, :warn, :error, :puts].each do |severity|
  62 + ::Object.class_eval do
  63 + define_method severity do |*args|
  64 + $messages ||= {}
  65 + $messages[severity] ||= []
  66 + $messages[severity].push(*args)
  67 + end
  68 + end
  69 + end
  70 +
  71 + class << Buildr.application
  72 + alias :deprecated_without_capture :deprecated
  73 + def deprecated(message)
  74 + verbose(true) { deprecated_without_capture message }
  75 + end
  76 + end
  77 +
  78 + class MessageWithSeverityMatcher
  79 + def initialize(severity, message)
  80 + @severity = severity
  81 + @expect = message
  82 + end
  83 +
  84 + def matches?(target)
  85 + $messages = {@severity => []}
  86 + target.call
  87 + return Regexp === @expect ? $messages[@severity].join('\n') =~ @expect : $messages[@severity].include?(@expect.to_s)
  88 + end
  89 +
  90 + def failure_message
  91 + "Expected #{@severity} #{@expect.inspect}, " +
  92 + ($messages[@severity].empty? ? "no #{@severity} issued" : "found #{$messages[@severity].inspect}")
  93 + end
  94 +
  95 + def negative_failure_message
  96 + "Found unexpected #{$messages[@severity].inspect}"
  97 + end
  98 + end
  99 +
  100 + # Test if an info message was shown. You can use a string or regular expression.
  101 + #
  102 + # For example:
  103 + # lambda { info 'ze test' }.should show_info(/ze test/)
  104 + def show_info(message)
  105 + MessageWithSeverityMatcher.new :info, message
  106 + end
  107 +
  108 + # Test if a warning was shown. You can use a string or regular expression.
  109 + #
  110 + # For example:
  111 + # lambda { warn 'ze test' }.should show_warning(/ze test/)
  112 + def show_warning(message)
  113 + MessageWithSeverityMatcher.new :warn, message
  114 + end
  115 +
  116 + # Test if an error message was shown. You can use a string or regular expression.
  117 + #
  118 + # For example:
  119 + # lambda { error 'ze test' }.should show_error(/ze test/)
  120 + def show_error(message)
  121 + MessageWithSeverityMatcher.new :error, message
  122 + end
  123 +
  124 + # Test if any message was shown (puts). You can use a string or regular expression.
  125 + #
  126 + # For example:
  127 + # lambda { puts 'ze test' }.should show(/ze test/)
  128 + def show(message)
  129 + MessageWithSeverityMatcher.new :puts, message
  130 + end
  131 +
  132 + # Yields a block that should try exiting the application.
  133 + # Accepts
  134 + #
  135 + # For example:
  136 + # test_exit(1) { puts "Hello" ; exit(1) }.should show("Hello")
  137 + #
  138 + def test_exit(status = nil)
  139 + return lambda {
  140 + begin
  141 + yield
  142 + raise "Exit was not called!"
  143 + rescue SystemExit => e
  144 + raise "Exit status incorrect! Expected: #{status}, got #{e.status}" if status && (e.status != status)
  145 + end
  146 + }
  147 + end
  148 +
  149 + class ::Rake::Task
  150 + alias :execute_without_a_record :execute
  151 + def execute(args)
  152 + $executed ||= []
  153 + $executed << name
  154 + execute_without_a_record args
  155 + end
  156 + end
  157 +
  158 + class InvokeMatcher
  159 + def initialize(*tasks)
  160 + @expecting = tasks.map { |task| [task].flatten.map(&:to_s) }
  161 + end
  162 +
  163 + def matches?(target)
  164 + $executed = []
  165 + target.call
  166 + return false unless all_ran?
  167 + return !@but_not.any_ran? if @but_not
  168 + return true
  169 + end
  170 +
  171 + def failure_message
  172 + return @but_not.negative_failure_message if all_ran? && @but_not
  173 + "Expected the tasks #{expected} to run, but #{remaining} did not run, or not in the order we expected them to." +
  174 + " Tasks that ran: #{$executed.inspect}"
  175 + end
  176 +
  177 + def negative_failure_message
  178 + if all_ran?
  179 + "Expected the tasks #{expected} to not run, but they all ran."
  180 + else
  181 + "Expected the tasks #{expected} to not run, and all but #{remaining} ran."
  182 + end
  183 + end
  184 +
  185 + def but_not(*tasks)
  186 + @but_not = InvokeMatcher.new(*tasks)
  187 + self
  188 + end
  189 +
  190 + protected
  191 +
  192 + def expected
  193 + @expecting.map { |tests| tests.join('=>') }.join(', ')
  194 + end
  195 +
  196 + def remaining
  197 + @remaining.map { |tests| tests.join('=>') }.join(', ')
  198 + end
  199 +
  200 + def all_ran?
  201 + @remaining ||= $executed.inject(@expecting) do |expecting, executed|
  202 + expecting.map { |tasks| tasks.first == executed ? tasks[1..-1] : tasks }.reject(&:empty?)
  203 + end
  204 + @remaining.empty?
  205 + end
  206 +
  207 + def any_ran?
  208 + all_ran?
  209 + @remaining.size < @expecting.size
  210 + end
  211 +
  212 + end
  213 +
  214 + # Tests that all the tasks ran, in the order specified. Can also be used to test that some
  215 + # tasks and not others ran.
  216 + #
  217 + # Takes a list of arguments. Each argument can be a task name, matching only if that task ran.
  218 + # Each argument can be an array of task names, matching only if all these tasks ran in that order.
  219 + # So run_tasks('foo', 'bar') expects foo and bar to run in any order, but run_task(['foo', 'bar'])
  220 + # expects foo to run before bar.
  221 + #
  222 + # You can call but_not on the matchers to specify that certain tasks must not execute.
  223 + #
  224 + # For example:
  225 + # # Either task
  226 + # lambda { task('compile').invoke }.should run_tasks('compile', 'resources')
  227 + # # In that order
  228 + # lambda { task('build').invoke }.should run_tasks(['compile', 'test'])
  229 + # # With exclusion
  230 + # lambda { task('build').invoke }.should run_tasks('compile').but_not('install')
  231 + def run_tasks(*tasks)
  232 + InvokeMatcher.new *tasks
  233 + end
  234 +
  235 + # Tests that a task ran. Similar to run_tasks, but accepts a single task name.
  236 + #
  237 + # For example:
  238 + # lambda { task('build').invoke }.should run_task('test')
  239 + def run_task(task)
  240 + InvokeMatcher.new [task]
  241 + end
  242 +
  243 + class UriPathMatcher
  244 + def initialize(re)
  245 + @expression = re
  246 + end
  247 +
  248 + def matches?(uri)
  249 + @uri = uri
  250 + uri.path =~ @expression
  251 + end
  252 +
  253 + def description
  254 + "URI with path matching #{@expression}"
  255 + end
  256 + end
  257 +
  258 + # Matches a parsed URI's path against the given regular expression
  259 + def uri(re)
  260 + UriPathMatcher.new(re)
  261 + end
  262 +
  263 +
  264 + class AbsolutePathMatcher
  265 + def initialize(path)
  266 + @expected = File.expand_path(path.to_s)
  267 + end
  268 +
  269 + def matches?(path)
  270 + @provided = File.expand_path(path.to_s)
  271 + @provided == @expected
  272 + end
  273 +
  274 + def failure_message
  275 + "Expected path #{@expected}, but found path #{@provided}"
  276 + end
  277 +
  278 + def negative_failure_message
  279 + "Expected a path other than #{@expected}"
  280 + end
  281 + end
  282 +
  283 + def point_to_path(path)
  284 + AbsolutePathMatcher.new(path)
  285 + end
  286 +
  287 +
  288 + # Value covered by range. For example:
  289 + # (1..5).should cover(3)
  290 + RSpec::Matchers.define :cover do |actual|
  291 + match do |range|
  292 + actual >= range.min && actual <= range.max
  293 + end
  294 + end
  295 +
  296 +
  297 + def suppress_stdout
  298 + stdout = $stdout
  299 + $stdout = StringIO.new
  300 + begin
  301 + yield
  302 + ensure
  303 + $stdout = stdout
  304 + end
  305 + end
  306 +
  307 + def dryrun
  308 + Buildr.application.options.dryrun = true
  309 + begin
  310 + suppress_stdout { yield }
  311 + ensure
  312 + Buildr.application.options.dryrun = false
  313 + end
  314 + end
  315 +
  316 + # We run tests with tracing off. Then things break. And we need to figure out what went wrong.
  317 + # So just use trace() as you would use verbose() to find and squash the bug.
  318 + def trace(value = nil)
  319 + old_value = Buildr.application.options.trace
  320 + Buildr.application.options.trace = value unless value.nil?
  321 + if block_given?
  322 + begin
  323 + yield
  324 + ensure
  325 + Buildr.application.options.trace = old_value
  326 + end
  327 + end
  328 + Buildr.application.options.trace
  329 + end
  330 +
  331 + # Change the Buildr original directory, faking invocation from a different directory.
  332 + def in_original_dir(dir)
  333 + begin
  334 + original_dir = Buildr.application.original_dir
  335 + Buildr.application.instance_eval { @original_dir = File.expand_path(dir) }
  336 + yield
  337 + ensure
  338 + Buildr.application.instance_eval { @original_dir = original_dir }
  339 + end
  340 + end
  341 +
  342 +
  343 + # Buildr's define method creates a project definition but does not evaluate it
  344 + # (that happens once the buildfile is loaded), and we include Buildr's define in
  345 + # the test context so we can use it without prefixing with Buildr. This just patches
  346 + # define to evaluate the project definition before returning it.
  347 + def define(name, properties = nil, &block) #:yields:project
  348 + Project.define(name, properties, &block).tap { |project| project.invoke }
  349 + end
  350 +
  351 + end
  352 +
  353 +
  354 + # Allow using matchers within the project definition.
  355 + class Buildr::Project
  356 + include ::RSpec::Matchers, SpecHelpers
  357 + end
  358 +
  359 +
  360 + ::RSpec.configure do |config|
  361 + # Make all Buildr methods accessible from test cases, and add various helper methods.
  362 + config.include Buildr
  363 + config.include SpecHelpers
  364 +
  365 + # Sanbdox Buildr for each test.
  366 + config.include Sandbox
  367 + end
  368 +
  369 +end
18 test/helper.rb
... ... @@ -1,18 +0,0 @@
1   -require 'rubygems'
2   -require 'bundler'
3   -begin
4   - Bundler.setup(:default, :development)
5   -rescue Bundler::BundlerError => e
6   - $stderr.puts e.message
7   - $stderr.puts "Run `bundle install` to install missing gems"
8   - exit e.status_code
9   -end
10   -require 'test/unit'
11   -require 'shoulda'
12   -
13   -$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14   -$LOAD_PATH.unshift(File.dirname(__FILE__))
15   -#require File.dirname(__FILE__) +
16   -
17   -class Test::Unit::TestCase
18   -end
7 test/test_buildr_as3.rb
... ... @@ -1,7 +0,0 @@
1   -require 'helper'
2   -
3   -class TestBuildrAs3 < Test::Unit::TestCase
4   - should "probably rename this file and start testing for real" do
5   - assert_equal( 1, 1, "1 should be one")
6   - end
7   -end

0 comments on commit a5c17b0

Please sign in to comment.
Something went wrong with that request. Please try again.