buildr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Assaf Arkin" <ar...@intalio.com>
Subject 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
Date Tue, 23 Sep 2008 21:43:04 GMT
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,  <vborja@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)
>
>
>

Mime
View raw message