Thursday, August 23, 2012

A JRuby, Rails, RSpec, Spork, and an error walk in to a bar...

I was running a specific rspec over and over during a tight development cycle. The way our system was set up it was taking 30+ sec to run a single spec file, which made running them onerous.

We had Spork running at one point, but it wasn't working for me, with a "undefined method 'flush' for nil:NilClass" error (and a couple of others depending on the incantation):

$ rspec --drb spec/models/foo_spec.rb .../rubies/jruby-1.6.7/lib/ruby/1.9/drb/drb.rb:375 warning:
ObjectSpace is disabled; _id2ref only supports immediates, pass -X+O to enable
NoMethodError: undefined method `flush' for nil:NilClass
method_missing at .../rubies/jruby-1.6.7/lib/ruby/1.9/drb/drb.rb:1099
run at .../gems/jruby-1.6.7@cowbania/gems/rspec-core-2.11.1/lib/rspec/core/drb_command_line.rb:22
run at .../gems/jruby-1.6.7@cowbania/gems/rspec-core-2.11.1/lib/rspec/core/runner.rb:63
autorun at .../gems/jruby-1.6.7@cowbania/gems/rspec-core-2.11.1/lib/rspec/core/runner.rb:8
view raw 01_error.txt hosted with ❤ by GitHub
After upgrading Spork (we had been running an older version), setting the JRUBY_OPTS environment variable, and restarting Spork, the spec time dropped to ~8 sec. Still not particularly fast, but faster-enough to make it worth it.

gem 'spork', '~> 1.0rc'
view raw 02_Gemfile.rb hosted with ❤ by GitHub
export JRUBY_OPTS="--1.9 -J-XX:MaxPermSize=512m -J-Xmx1g -X+O"
spork rspec
view raw 03_cmd.sh hosted with ❤ by GitHub
Not currently running Guard. Not sure if the upgrade or opts made it start working.

This post is a work-in-progress.

Wednesday, August 08, 2012

RSpec Error With Implicit Subject

Ever write a trivial spec like this:

describe Foo do
it { should respond_to(:bar) }
end
view raw 01_spec.rb hosted with ❤ by GitHub
And get something totally baffling back, like this?

Failure/Error: it { should respond_to(:bar) }
ArgumentError:
wrong number of arguments (0 for 1)
# org/jruby/RubyBasicObject.java:1730:in `instance_eval'
# ./spec/models/foo_spec.rb:19:in `(root)'
# org/jruby/RubyBasicObject.java:1730:in `instance_eval'
# org/jruby/RubyArray.java:2339:in `collect'
# org/jruby/RubyArray.java:2339:in `collect'
# org/jruby/RubyArray.java:2339:in `collect'
view raw 02_error.txt hosted with ❤ by GitHub
Backstory: Refactoring some pre-written classes to use metaprogramming to create some methods and values. I wanted specs in place before starting the metaprogramming to avoid breaking things.
In retrospect, I should have figured this out sooner. In my defense, I love the Olympics and was distracted. The constructor of the model gives it away:

class Foo < Plugh
def initialize(s)
# Do stuff
end
end
view raw 03_foo.rb hosted with ❤ by GitHub
A parameterized constructor, no default value: rspec couldn't instantiate the implicit subject.

Silly mistake, exacerbated by magic, hidden functionality–it's one of the greatest things about Ruby, but can occasionally lead to opaque behavior, especially during the Olympics.