You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@buildr.apache.org by vb...@apache.org on 2008/09/23 21:14:06 UTC
svn commit: r698306 - in /incubator/buildr/trunk: lib/buildr/java/bdd.rb
lib/buildr/java/jtestr_result_handler.rb
lib/buildr/java/jtestr_runner.rb.erb lib/buildr/java/test_result.rb
spec/java/bdd_spec.rb
Author: vborja
Date: Tue Sep 23 12:14:06 2008
New Revision: 698306
URL: http://svn.apache.org/viewvc?rev=698306&view=rev
Log:
Created an rspec YAMLFormatter so that buildr can know which tests failed.
Removed ci_reporter dependency
Added:
incubator/buildr/trunk/lib/buildr/java/test_result.rb
Removed:
incubator/buildr/trunk/lib/buildr/java/jtestr_result_handler.rb
Modified:
incubator/buildr/trunk/lib/buildr/java/bdd.rb
incubator/buildr/trunk/lib/buildr/java/jtestr_runner.rb.erb
incubator/buildr/trunk/spec/java/bdd_spec.rb
Modified: incubator/buildr/trunk/lib/buildr/java/bdd.rb
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/lib/buildr/java/bdd.rb?rev=698306&r1=698305&r2=698306&view=diff
==============================================================================
--- incubator/buildr/trunk/lib/buildr/java/bdd.rb (original)
+++ incubator/buildr/trunk/lib/buildr/java/bdd.rb Tue Sep 23 12:14:06 2008
@@ -13,8 +13,8 @@
# License for the specific language governing permissions and limitations under
# the License.
-require 'yaml'
require 'buildr/java/tests'
+require 'buildr/java/test_result'
module Buildr
@@ -44,6 +44,7 @@
end
module TestFramework::JRubyBased
+ extend self
VERSION = '1.1.4' unless const_defined?('VERSION')
@@ -64,7 +65,11 @@
module ClassMethods
def dependencies
- super + (RUBY_PLATFORM[/java/] ? [] : JRubyBased.dependencies)
+ deps = super
+ unless RUBY_PLATFORM[/java/] && TestFramework::JRubyBased.jruby_installed?
+ deps |= TestFramework::JRubyBased.dependencies
+ end
+ deps
end
end
@@ -73,11 +78,17 @@
( ENV['JRUBY_HOME'] || File.expand_path("~/.jruby") )
end
+ def jruby_installed?
+ !Dir.glob(File.join(jruby_home, 'lib', 'jruby*.jar')).empty?
+ end
+
def jruby(*args)
java_args = ["org.jruby.Main", *args]
java_args << {} unless Hash === args.last
cmd_options = java_args.last
project = cmd_options.delete(:project)
+ cmd_options[:classpath] ||= []
+ Dir.glob(File.join(jruby_home, 'lib', '*.jar')) { |jar| cmd_options[:classpath] << jar }
cmd_options[:java_args] ||= []
cmd_options[:java_args] << "-Xmx512m" unless cmd_options[:java_args].detect {|a| a =~ /^-Xmx/}
cmd_options[:properties] ||= {}
@@ -93,12 +104,48 @@
yield config if block_given?
Java.org.jruby.Ruby.newInstance config
end
+
+ def jruby_gem
+ %{
+ require 'jruby'
+ def JRuby.gem(name, version = '>0', *args)
+ require 'rbconfig'
+ jruby_home = Config::CONFIG['prefix']
+ expected_version = '#{TestFramework::JRubyBased.version}'
+ unless JRUBY_VERSION >= expected_version
+ fail "Expected JRuby version \#{expected_version} installed at \#{jruby_home} but got \#{JRUBY_VERSION}"
+ end
+ if Dir.glob(File.join(jruby_home, 'lib', 'jruby*.jar')).empty?
+ require 'jruby/extract'
+ JRuby::Extract.new.extract
+ end
+ require 'rubygems'
+ begin
+ Kernel.gem name, version
+ rescue LoadError, Gem::LoadError => e
+ require 'rubygems/gem_runner'
+ Gem.manage_gems
+ args = ['install', name, '--version', version] + args
+ Gem::GemRunner.new.run(args)
+ Kernel.gem name, version
+ end
+ end
+ }
+ end
end
-
+
+ # <a href="http://rspec.info">RSpec</a> is the defacto BDD framework for ruby.
+ # To test your project with RSpec use:
+ # test.using :rspec
+ #
+ #
+ # Support the following options:
+ # * :properties -- Hash of properties passed to the test suite.
+ # * :java_args -- Arguments passed to the JVM.
class RSpec < TestFramework::JavaBDD
@lang = :ruby
- @bdd_dir = :spec
+ @bdd_dir = :spec
include TestFramework::JRubyBased
@@ -118,18 +165,54 @@
end
def run(tests, dependencies) #:nodoc:
- #jruby_home or fail "To use RSpec you must either run on JRuby or have JRUBY_HOME set"
+ dependencies |= [task.compile.target.to_s]
+
cmd_options = task.options.only(:properties, :java_args)
- #dependencies.push *Dir.glob(File.join(jruby_home, "lib/*.jar")) if RUBY_PLATFORM =~ /java/
- cmd_options.update :classpath => dependencies, :project => task.project
+ cmd_options.update :classpath => dependencies, :project => task.project, :name => 'RSpec'
report_dir = task.report_to.to_s
FileUtils.rm_rf report_dir
ENV['CI_REPORTS'] = report_dir
- jruby '-Ilib', '-S', 'spec', '--require', 'ci/reporter/rake/rspec_loader',
- '--format', 'CI::Reporter::RSpecDoc', tests, cmd_options.merge(:name => 'RSpec')
- tests
+ result_file = File.join(report_dir, 'result.yaml')
+
+ requires = task.options[:requires] || []
+ requires.push 'spec', File.join(File.dirname(__FILE__), 'test_result')
+ gems = task.options[:gems] || {}
+ argv = task.options[:args] || [ '--format', 'progress' ]
+ argv.push '--format', "Buildr::TestFramework::TestResult::RSpec:#{result_file}"
+ argv.push *tests
+
+ runner = %{
+ #{ jruby_gem }
+ JRuby.gem('rspec')
+ #{ dependencies.inspect }.each { |dep| $CLASSPATH << dep }
+ #{ gems.inspect }.each { |ary| JRuby.gem(*ary.flatten) }
+ #{ requires.inspect }.each { |rb| Kernel.require rb }
+ Buildr::TestFramework::TestResult.for_rspec
+ parser = ::Spec::Runner::OptionParser.new(STDERR, STDOUT)
+ parser.order!(#{argv.inspect})
+ $rspec_options = parser.options
+ ::Spec::Runner::CommandLine.run($rspec_options)
+ }
+
+ runner_file = task.project.path_to(:target, :spec, 'rspec_runner.rb')
+ Buildr.write runner_file, runner
+
+ if /java/ === RUBY_PLATFORM
+ runtime = new_runtime :current_directory => runner_file.pathmap('%d')
+ runtime.getLoadService.require runner_file
+ else
+ begin
+ jruby runner_file, tests, cmd_options
+ ensure
+ FileUtils.cp_r task.project.path_to(nil), '/tmp/foo'
+ end
+ end
+
+ result = YAML.load(File.read(result_file))
+ raise result if Exception === result
+ result.succeeded
end
end
@@ -203,7 +286,7 @@
end
def tests(dependencies) #:nodoc:
- dependencies += [task.compile.target.to_s]
+ dependencies |= [task.compile.target.to_s]
types = { :story => STORY_PATTERN, :rspec => RSpec::TESTS_PATTERN,
:testunit => TESTUNIT_PATTERN, :expect => EXPECT_PATTERN }
tests = types.keys.inject({}) { |h, k| h[k] = []; h }
@@ -220,9 +303,21 @@
end
def run(tests, dependencies) #:nodoc:
- dependencies += [task.compile.target.to_s]
+ dependencies |= [task.compile.target.to_s]
+
+ result_file = File.join(task.report_to.to_s, 'result.yaml')
+
+ requires = task.options[:requires] || []
+ requires.push 'spec', 'jtestr', File.join(File.dirname(__FILE__), 'test_result')
+ gems = task.options[:gems] || {}
+ argv = task.options[:args] || [ '--format', 'progress' ]
+ argv.push '--format', "Buildr::TestFramework::TestResult::RSpec:#{result_file}"
+ argv.push *tests
+
+ report_dir = task.report_to.to_s
+ FileUtils.rm_rf report_dir
+ ENV['CI_REPORTS'] = report_dir
- yaml_report = File.join(task.report_to.to_s, 'result.yaml')
spec_dir = task.project.path_to(:source, :spec, :ruby)
runner_file = task.project.path_to(:target, :spec, 'jtestr_runner.rb')
@@ -237,11 +332,12 @@
cmd_options = task.options.only(:properties, :java_args)
cmd_options.update(:classpath => dependencies, :project => task.project)
jruby runner_file, cmd_options.merge(:name => 'JtestR')
+ FileUtils.cp_r task.project.path_to(nil), '/tmp/foo'
end
- report = YAML::load(File.read(yaml_report))
- raise (Array(report[:error][:message]) + report[:error][:backtrace]).join("\n") if report[:error]
- report[:success]
+ result = YAML::load(File.read(result_file))
+ raise result if Exception === result
+ result.succeeded
end
end
Modified: incubator/buildr/trunk/lib/buildr/java/jtestr_runner.rb.erb
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/lib/buildr/java/jtestr_runner.rb.erb?rev=698306&r1=698305&r2=698306&view=diff
==============================================================================
--- incubator/buildr/trunk/lib/buildr/java/jtestr_runner.rb.erb (original)
+++ incubator/buildr/trunk/lib/buildr/java/jtestr_runner.rb.erb Tue Sep 23 12:14:06 2008
@@ -26,9 +26,14 @@
# <%= user_config %>
begin
- require 'jruby'
+ <%= jruby_gem %>
+ JRuby.gem('rspec')
+
<%= dependencies.map(&:to_s).inspect %>.each { |dep| $CLASSPATH << dep }
- require '<%= File.join(File.dirname(runner_erb), "jtestr_result_handler") %>'
+ <%= gems.inspect %>.each { |ary| JRuby.gem(*ary.flatten) }
+ <%= requires.inspect %>.each { |rb| Kernel.require rb }
+
+ Buildr::TestFramework::TestResult.for_jtestr
jtestr = JtestR::TestRunner.new
@@ -68,33 +73,34 @@
expectations <%= ts.inspect %>
ignore __FILE__
-
+
if File.file?(<%= user_config.inspect %>)
ignore <%= user_config.inspect %>
load <%= user_config.inspect %>
end
end # config
- args = [ '<%= spec_dir %>' ] # the directory to search for jtestr files
- args << JtestR::SimpleLogger::ERR # log level
- args << JtestR::GenericResultHandler::QUIET # verbose level
- <% if options[:output] == false %>
- args << StringIO.new # output
- <% elsif options[:output].kind_of?(String) %>
- args << File.open('<%= options[:output] %>')
- <% else %>
- args << STDOUT # output
- <% end %>
- args << [] # groups_to_run
- args << JtestR::YAMLResultHandler # result handler
-
- JtestR::YAMLResultHandler.report_to('<%= yaml_report %>')
- JtestR::YAMLResultHandler.tests = <%= tests.inspect %>
+ args = [ '<%= spec_dir %>', # the directory to search for jtestr files
+ JtestR::SimpleLogger::ERR, # log level
+ JtestR::GenericResultHandler::QUIET, #output level
+ StringIO.new, # output STDOUT
+ [], # groups to run
+ Buildr::TestFramework::TestResult::JtestR, # result handler
+ [] # classpath
+ ]
+
+ rspec_parser = ::Spec::Runner::OptionParser.new(STDERR, STDOUT)
+ rspec_parser.order!(<%= argv.inspect %>)
+ Buildr::TestFramework::TestResult::JtestR.options = rspec_parser.options
+
jtestr.run *args
rescue => e
- File.open('<%= yaml_report %>', "w") do |f|
- f.write YAML.dump({:error => { :message => e.message, :backtrace => e.backtrace}})
+ puts e, *e.backtrace
+ require 'fileutils'
+ FileUtils.mkdir_p(File.dirname('<%= result_file %>'))
+ File.open('<%= result_file %>', "w") do |f|
+ f.write YAML.dump(Buildr::TestFramework::TestResult::Error.new(e.message, e.backtrace))
end
end
Added: incubator/buildr/trunk/lib/buildr/java/test_result.rb
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/lib/buildr/java/test_result.rb?rev=698306&view=auto
==============================================================================
--- incubator/buildr/trunk/lib/buildr/java/test_result.rb (added)
+++ incubator/buildr/trunk/lib/buildr/java/test_result.rb Tue Sep 23 12:14:06 2008
@@ -0,0 +1,207 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with this
+# work for additional information regarding copyright ownership. The ASF
+# licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+require 'yaml'
+
+module Buildr #:nodoc:
+ module TestFramework
+
+ # A class used by buildr for jruby based frameworks, so that buildr can know
+ # which tests succeeded/failed.
+ class TestResult
+
+ class Error < ::Exception
+ attr_reader :message, :backtrace
+ def initialize(message, backtrace)
+ @message = message
+ @backtrace = backtrace
+ end
+ end
+
+ class << self
+ def for_rspec
+ unless const_defined?(:RSpec)
+ require 'spec/runner/formatter/base_formatter' # lazy loading only when using Rspec
+ cls = Class.new(Spec::Runner::Formatter::BaseFormatter) { include YamlFormatter }
+ const_set :RSpec, cls
+ end
+ end
+
+ def for_jtestr
+ unless const_defined?(:JtestR)
+ for_rspec
+ require 'jtestr' # lazy loading only when using JtestR
+ cls = Class.new { include RSpecResultHandler }
+ const_set :JtestR, cls
+ end
+ end
+ end
+
+ attr_accessor :failed, :succeeded
+
+ def initialize
+ @failed, @succeeded = [], []
+ end
+
+ module YamlFormatter
+ attr_reader :result
+
+ def start(example_count)
+ super
+ @result = TestResult.new
+ end
+
+ def close
+ files = options.files
+ failure_from_bt = lambda do |ary|
+ test = nil
+ ary.find do |bt|
+ bt = bt.split(':').first.strip
+ test = bt if files.include?(bt)
+ end
+ test
+ end
+ options.reporter.instance_variable_get(:@failures).each do |failure|
+ result.failed << files.delete(failure_from_bt[failure.exception.backtrace])
+ end
+ result.succeeded |= files
+
+ FileUtils.mkdir_p(File.dirname(where))
+ File.open(where, 'w') { |f| f.puts YAML.dump(result) }
+ end
+ end # YamlFormatter
+
+
+ # A JtestR ResultHandler
+ # Using this handler we can use RSpec formatters, like html/ci_reporter with JtestR
+ # Created for YamlFormatter
+ module RSpecResultHandler
+ def self.included(mod)
+ mod.extend ClassMethods
+ super
+ end
+
+ module ClassMethods
+ # an rspec reporter used to proxy events to rspec formatters
+ attr_reader :reporter
+
+ def options=(options)
+ @reporter = Spec::Runner::Reporter.new(options)
+ end
+
+ def before
+ reporter.start(reporter.options.files.size)
+ end
+
+ def after
+ reporter.end
+ reporter.dump
+ end
+ end
+
+ module ExampleMethods
+ attr_accessor :name, :description, :__full_description
+ end
+
+ def reporter
+ self.class.reporter
+ end
+
+ attr_accessor :example_group, :current_example, :current_failure
+
+ def initialize(name, desc, *args)
+ self.example_group = ::Spec::Example::ExampleGroup.new(desc)
+ reporter.add_example_group(example_group)
+ end
+
+ def starting
+ end
+
+ def ending
+ end
+
+ def add_fault(fault)
+ self.current_failure = fault
+ end
+
+ def add_pending(pending)
+ end
+
+ def starting_single(name = nil)
+ self.current_failure = nil
+ self.current_example = Object.new
+ current_example.extend ::Spec::Example::ExampleMethods
+ current_example.extend ExampleMethods
+ desc = name.to_s[/(.*)\(/] ? $1 : name.to_s
+ current_example.description = desc
+ current_example.__full_description = "#{example_group.description} #{desc}"
+ reporter.example_started(current_example)
+ end
+
+ def succeed_single(name = nil)
+ fail_unless_current(name)
+ reporter.example_finished(current_example)
+ end
+
+ def fail_single(name = nil)
+ fail_unless_current(name)
+ reporter.failure(current_example, current_error)
+ end
+
+ def error_single(name = nil)
+ fail_unless_current(name)
+ reporter.example_finished(current_example, current_error)
+ end
+
+ def pending_single(name = nil)
+ fail_unless_current(name)
+ error = ::Spec::Example::ExamplePendingError.new(name)
+ reporter.example_finished(current_example, error)
+ end
+
+ private
+ def fail_unless_current(name)
+ fail "Expected #{name.inspect} to be current example but was #{current_example.description}" unless current_example.description == name.to_s
+ end
+
+ def current_error
+ fault = current_failure
+ case fault
+ when nil
+ nil
+ when Test::Unit::Failure
+ Error.new(fault.message, fault.location)
+ when Test::Unit::Error, Expectations::Results::Error, Spec::Runner::Reporter::Failure
+ fault.exception
+ when Expectations::Results
+ fault
+ else
+ if fault.respond_to?(:test_header)
+ fault.test_header[/\((.+)\)/]
+ test = $1.to_s
+ self.class.add_failure(test)
+ elsif fault.respond_to?(:method)
+ test = fault.method.test_class.name
+ self.class.add_failure(test)
+ end
+ end
+ end
+
+
+ end # RSpecResultHandler
+
+ end # TestResult
+ end
+end
Modified: incubator/buildr/trunk/spec/java/bdd_spec.rb
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/spec/java/bdd_spec.rb?rev=698306&r1=698305&r2=698306&view=diff
==============================================================================
--- incubator/buildr/trunk/spec/java/bdd_spec.rb (original)
+++ incubator/buildr/trunk/spec/java/bdd_spec.rb Tue Sep 23 12:14:06 2008
@@ -32,18 +32,22 @@
foo { test.framework.should eql(:rspec) }
end
- it 'should include src/spec/ruby/**/*_spec.rb' do
- verbose true
- foo do
- spec = _('src/spec/ruby/some_spec.rb')
- write spec, ''
- test.invoke
- test.tests.should include(spec)
+ it 'should run rspecs' do
+ success = File.expand_path('src/spec/ruby/success_spec.rb')
+ write(success, 'describe("success") { it("is true") { nil.should be_nil } }')
+ failure = File.expand_path('src/spec/ruby/failure_spec.rb')
+ write(failure, 'describe("failure") { it("is false") { true.should == false } }')
+ error = File.expand_path('src/spec/ruby/error_spec.rb')
+ write(error, 'describe("error") { it("raises") { eval("lambda") } }')
+ foo do
+ lambda { test.invoke }.should raise_error(/Tests failed/)
+ test.tests.should include(success, failure, error)
+ test.failed_tests.should include(failure, error)
+ test.passed_tests.should include(success)
end
end
-
-end if RUBY_PLATFORM =~ /java/ || ENV['JRUBY_HOME'] # RSpec
+end if true || RUBY_PLATFORM =~ /java/ || ENV['JRUBY_HOME'] # RSpec
describe Buildr::JtestR do
@@ -237,6 +241,8 @@
write(failure, 'describe("failure") { it("is false") { true.should == false } }')
error = File.expand_path('src/spec/ruby/error_spec.rb')
write(error, 'describe("error") { it("raises") { eval("lambda") } }')
+ pending = File.expand_path('src/spec/ruby/pending_spec.rb')
+ write(pending, 'describe("peding") { it "is not implemented" }')
foo do
lambda { test.invoke }.should raise_error(/Tests failed/)
test.tests.should include(success, failure, error)