You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@buildr.apache.org by Assaf Arkin <ar...@intalio.com> on 2008/09/23 23:43:04 UTC

Auto-installing JRuby Was: 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

Does anyone actually use this feature?

It strikes me as wrong that it would a) install executable code in my
home directory, b) do it without my express permission.  If I need to
have JRuby installed, I'll install it using apt-get or port, both of
which install it in the right place, take care of upgrade, inventory,
etc.  All Buildr has to do is notify me that it can't find JRuby.

If people do want JRuby magically installed, maybe move this to addon
and have them include this feature in their build?

Assaf

On Tue, Sep 23, 2008 at 12:14 PM,  <vb...@apache.org> wrote:
> 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)
>
>
>

Re: Auto-installing JRuby Was: 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

Posted by Victor Hugo Borja <vi...@gmail.com>.
You are right, Buildr should not automatically extract JRuby without express
permission, so I've just added a warning and
prompt the user if he wants to install JRuby using the system package
manager or let Buildr extract it from the artifact.

On Tue, Sep 23, 2008 at 4:43 PM, Assaf Arkin <ar...@intalio.com> wrote:

> Does anyone actually use this feature?
>
> It strikes me as wrong that it would a) install executable code in my
> home directory, b) do it without my express permission.  If I need to
> have JRuby installed, I'll install it using apt-get or port, both of
> which install it in the right place, take care of upgrade, inventory,
> etc.  All Buildr has to do is notify me that it can't find JRuby.
>
> If people do want JRuby magically installed, maybe move this to addon
> and have them include this feature in their build?
>
> Assaf
>
> On Tue, Sep 23, 2008 at 12:14 PM,  <vb...@apache.org> wrote:
> > 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)
> >
> >
> >
>



-- 
vic

Quaerendo invenietis.