[MacRuby-devel] Exception backtraces in instance_eval

Martijn Walraven martijn at martijnwalraven.com
Sat Nov 13 09:43:17 PST 2010


Hi,

I'm trying to use RSpec (latest version, 2.1.0) with MacRuby, but there seems to be information missing from the exception backtraces which makes it difficult to see where exactly specs fail.

Running a straightforward helloworld_spec.rb with a failing example for instance, shows a reference to the failing line (hello_world.greeting.should == "Hello World!") in MRI Ruby 1.9.2:

Failures:
  1) A new HelloWorld object should return the appropriate greeting
     Failure/Error: hello_world.greeting.should == "Hello World!"
     expected: "Hello World!",
          got: "Hello Earth!" (using ==)
     # ./Spec/helloworld_spec.rb:6:in `block (2 levels) in <top (required)>'

In MacRuby (0.7.1) however, RSpec displays a 'Failure/Error: Unable to find matching line from backtrace' instead, which makes sense with no traces present referring to the actual spec:

Failures:
  1) A new HelloWorld object should return the appropriate greeting
     Failure/Error: Unable to find matching line from backtrace
     expected: "Hello World!",
          got: "Hello Earth!" (using ==)
     # /usr/local/rvm/gems/macruby-0.7.1 at test/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:41:in `block'
     # /usr/local/rvm/gems/macruby-0.7.1 at test/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:39:in `block'
     # /usr/local/rvm/gems/macruby-0.7.1 at test/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:75:in `block'
     # /usr/local/rvm/gems/macruby-0.7.1 at test/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:74:in `with_pending_capture'
     # /usr/local/rvm/gems/macruby-0.7.1 at test/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:32:in `run:'
     # /usr/local/rvm/gems/macruby-0.7.1 at test/gems/rspec-core-2.1.0/lib/rspec/core/example_group.rb:260:in `block'
     # /usr/local/rvm/gems/macruby-0.7.1 at test/gems/rspec-core-2.1.0/lib/rspec/core/example_group.rb:257:in `run_examples:'
     # /usr/local/rvm/gems/macruby-0.7.1 at test/gems/rspec-core-2.1.0/lib/rspec/core/example_group.rb:222:in `run:'
     # /usr/local/rvm/gems/macruby-0.7.1 at test/gems/rspec-core-2.1.0/lib/rspec/core/command_line.rb:26:in `block'
     # /usr/local/rvm/gems/macruby-0.7.1 at test/gems/rspec-core-2.1.0/lib/rspec/core/command_line.rb:15:in `run:'
     # /usr/local/rvm/gems/macruby-0.7.1 at test/gems/rspec-core-2.1.0/lib/rspec/core/runner.rb:10:in `block'
'
Looking at the complete backtrace in MRI Ruby 1.9.2 shows there seems to be a lot of information missing from the MacRuby backtrace. Apart from missing information about the context of a block and other differences in descriptions, MacRuby doesn't seem to list any traces beyond the instance_eval. The RSpec source (example.rb) shows it indeed uses instance_eval to evaluate the example block. I checked the backtraces in the rescue clauses there, but they don't contain traces from any execution beyond the instance_eval call. Is loss of exception backtraces in instance_eval a known limitations of MacRuby? Are there any plans to improve backtraces?

Failures:
  1) A new HelloWorld object should return the appropriate greeting
     Failure/Error: hello_world.greeting.should == "Hello World!"
     expected: "Hello World!",
          got: "Hello Earth!" (using ==)
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-expectations-2.1.0/lib/rspec/expectations/fail_with.rb:29:in `fail_with'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-expectations-2.1.0/lib/rspec/matchers/operator_matcher.rb:48:in `fail_with_message'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-expectations-2.1.0/lib/rspec/matchers/operator_matcher.rb:70:in `__delegate_operator'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-expectations-2.1.0/lib/rspec/matchers/operator_matcher.rb:60:in `eval_match'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-expectations-2.1.0/lib/rspec/matchers/operator_matcher.rb:29:in `block in use_custom_matcher_or_delegate'
     # ./Spec/helloworld_spec.rb:6:in `block (2 levels) in <top (required)>'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:42:in `instance_eval'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:42:in `block (2 levels) in run'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:81:in `call'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:81:in `with_around_hooks'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:39:in `block in run'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:75:in `call'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:75:in `block in with_pending_capture'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:74:in `catch'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:74:in `with_pending_capture'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:38:in `run'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-core-2.1.0/lib/rspec/core/example_group.rb:261:in `block in run_examples'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-core-2.1.0/lib/rspec/core/example_group.rb:257:in `map'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-core-2.1.0/lib/rspec/core/example_group.rb:257:in `run_examples'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-core-2.1.0/lib/rspec/core/example_group.rb:231:in `run'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-core-2.1.0/lib/rspec/core/command_line.rb:27:in `block (2 levels) in run'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-core-2.1.0/lib/rspec/core/command_line.rb:27:in `map'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-core-2.1.0/lib/rspec/core/command_line.rb:27:in `block in run'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-core-2.1.0/lib/rspec/core/reporter.rb:12:in `report'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-core-2.1.0/lib/rspec/core/command_line.rb:24:in `run'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-core-2.1.0/lib/rspec/core/runner.rb:55:in `run_in_process'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-core-2.1.0/lib/rspec/core/runner.rb:46:in `run'
     # /usr/local/rvm/gems/ruby-1.9.2-p0 at test/gems/rspec-core-2.1.0/lib/rspec/core/runner.rb:10:in `block in autorun'

Just for completeness' sake, this is the code from example.rb that runs the example:

begin
          unless pending
            with_pending_capture do
              with_around_hooks do
                begin
                  run_before_each
                  @example_group_instance.instance_eval(&@example_block)
                rescue Exception => e
                  set_exception(e)
                ensure
                  run_after_each
                end
              end
            end
          end
        rescue Exception => e
          set_exception(e)
        ensure
          @example_group_instance.example = nil
          assign_auto_description
        end

Thanks,

Martijn


More information about the MacRuby-devel mailing list