Using RSpec with MacRuby, Part 1

Update 11/Dec/2009: The described solution doesn't work with MacRuby 0.5 as noted by Matt Aimonetti in the comments.

After playing with MacRuby for a while, I was definitely missing something: RSpec. I got so used to writing tests or specs with various Rails projects that I am feeling somewhat lost, lonely and uncertain when no testing framework is available... ok, maybe it's not that bad. :) Anyway, this article explains my first steps to run RSpec with MacRuby 0.4.

The starting point is my last post about MGTwitterEngine and MacRuby. If you haven't already read it, you might want to give it a look.

  1. Open the console and checkout MacRubyTwitterMG from GitHub:
    cd ~/Project
    git clone git@github.com:ashtom/macruby_twitter_mg.git MacRubyTwitterMG
  2. Switch to the Vendor subdirectory:
    cd Vendor
  3. Checkout RSpec:
    git clone git://github.com/dchelimsky/rspec.git RSpec
  4. Create a directory for your specs (I choose Spec with a capital letter only because Classes and Vendor also start with a capital letter):
    cd ..
    mkdir Spec
  5. Create a file named spec_helper.rb:
    $LOAD_PATH << File.expand_path(File.dirname(__FILE__) + '/../Vendor/RSpec/lib/')
    require 'spec/autorun'
    
    framework 'Cocoa'
    
    # Loading all the Ruby project files.
    dir_path = File.expand_path(File.dirname(__FILE__) + '/../Classes/')
    Dir.entries(dir_path).each do |path|
      if path != File.basename(__FILE__) and path[-3..-1] == '.rb'
        require(dir_path + '/' + path)
      end
    end
    In the first line we add RSpec to the load path of MacRuby, in the second line we require the RSpec runner. The rest of the file is more or less a copy of the rb_main.rb and loads all MacRuby project files.
  6. Create a very simple test spec in test_spec.rb to test whether RSpec actually works:
    require File.expand_path(File.dirname(__FILE__) + '/spec_helper.rb')
    
    describe "RSpec" do
      it "should work" do
        "Hello World".length.should == 11
      end
    end
  7. Back on the console, we try to run the spec:
    $ macruby Spec/test_spec.rb 
    F
    
    1)
    NameError in 'RSpec should work'
    undefined local variable or method `setup_mocks_for_rspec' for #<Spec::Example::ExampleGroup::Subclass_1:0x80064ec00>
    
    Finished in 0.0821 seconds
    
    1 example, 1 failure
    
  8. Hm... I haven't found any solution or hints for this error at Google, so I tried to fix this by myself. Here's my approach: Open the file /Vendor/RSpec/lib/spec/runner/options.rb and search for the following line (at the time of writing this post, it was line 273):
    Spec::Example::ExampleMethods.__send__ :include, Spec::Adapters::MockFramework
    Change the line to
    Spec::Example::ExampleGroup.__send__ :include, Spec::Adapters::MockFramework
    and save the file. If you have a better solution, please leave a comment below this post. Thanks!
  9. Try to run the spec again:
    $ macruby Spec/test_spec.rb 
    .
    
    Finished in 0.077641 seconds
    
    1 example, 0 failures
  10. Yay! :)
  11. Finally we can write our first real spec for the MainController.
    require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
    
    describe "MainController" do
      describe "#numberOfRowsInTableView" do
        before :each do
          @main_controller = MainController.new
        end
    
        it "should return zero if timeline is empty" do
          @main_controller.timeline = []
          @main_controller.numberOfRowsInTableView(nil).should == 0
        end
    
        it "should return the number of entries in the timeline" do
          @main_controller.timeline = ["one", "two", "three"]
          @main_controller.numberOfRowsInTableView(nil).should == 3
        end
      end
    end
    I've put this stuff under Spec/Controllers/MainControllerSpec.rb although the spelling looks a bit awkward for now. As before, the spec is executed with a simple shell command:
    $ macruby Spec/Controllers/MainControllerSpec.rb 
    ..
    
    Finished in 0.082415 seconds
    
    2 examples, 0 failures

That's it with this post, still pretty simple, but it works. In the next post (coming soon) we'll do some more testing and see how to use mocks. In the meantime, your suggestions and comments are very welcome.

Git Repository

I've put all code of this post into the branch spec of MacRubyTwitterMG's git repository at GitHub. Feel free to fork. :)

Keywords: mac, programming, ruby

Added by Thomas Dohmke 288 days ago


Comments

Added by Matt Aimonetti 288 days ago

Great blog post, thanks a lot! The problem you encountered with RSpec is related to a known bug in MacRuby 0.4 which was fixed in 0.5.

Added by Mikael Hallendal 287 days ago

Thanks a lot for sharing, had planned on looking at this soon.

Added by Johan Lind 287 days ago

Awesome, great work! Now I don't have to write legacy code anymore!

Added by Matt Aimonetti 92 days ago

as of MacRuby 0.5b2, rspec doesn't work as it's using #caller to find the list of files to load and #caller isn't working at 100% on MacRuby. We are looking at rspec 2.0 alpha which is a cleaner rewrite of rspec internals.

Add a comment

Twitter

Follow us on Twitter:

Keywords