Shoulda Sporked That

July 28th, 2009

Nick Rutherford

One of the feelings I got from Rails Underground (best not to ask about the others!) is that while RSpec, Cucumber and family have laid tracks in the Rails toolkit and community, many still use TestUnit.

Alternatives are good in some senses, but make me feel like I'm missing out and worry about chasing the wrong rabbit. Seeing things bridged can be nice, and here's an example of that. This one is extra-nice because it also patched what was, to my eyes, a crack in the plaster.

Shoulda for RSpec

I've got some rspec view and controller macros I am considering pulling out into a plugin, but decided to look around for alternatives first. Remarkable is noted on some wiki or other, but I couldn't make much sense of it. rspec_on_rails_macros is a sensible looking alternative, but the origin has been out of development for some time and the forks are somewhat confusing. Looking around did have a positive consequence though -- they pointed out that Shoulda now has rspec support!

That may sound confusing, since Shoulda is another way of writing declarative unit tests (with a similar looking syntax to rspec), but the bonus is a raft of new matchers. So far only the model macros are available but more are promised to come.

Instant gratification:

-    it "should not be valid without a meta description" do
-      Service.make_unsaved(:meta_description => nil).should_not be_valid
-      Service.make_unsaved(:meta_description => '').should_not be_valid
-    end
-    
-    it "should not be valid without meta keywords" do
-      Service.make_unsaved(:meta_keywords => nil).should_not be_valid
-      Service.make_unsaved(:meta_keywords => '').should_not be_valid
-    end
-    
+    it { should validate_presence_of(:name) }
+    it { should validate_presence_of(:teaser) }

I'd Spork That

Next up is Spork, a must-have if you find your specs are running slowly.

You get another executable to add to your workbench, spork, this is a distributed ruby server which uses forking (unix only) to cut down start-up times. Pretty cool I think, get set up to a common starting point then clone it per run.

I find this config works for me, without having to restart the server when I change Machinist blueprints or helper files

require 'rubygems'; require 'spork'

Spork.prefork do
  ENV["RAILS_ENV"] ||= 'test'
  require File.dirname(__FILE__) + "/../config/environment"
  require 'spec/autorun'
  require 'spec/rails'
  require 'shoulda'
  require 'webrat'

  Dir[File.dirname(__FILE__) + "/spec_helpers/**/*.rb"].each do |file| 
    require file 
  end

  # Requires supporting files with custom matchers and macros, etc,
  # in ./support/ and its subdirectories.
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}

  Spec::Runner.configure do |config|
    config.use_transactional_fixtures = true
    config.use_instantiated_fixtures  = false
    config.fixture_path = RAILS_ROOT + '/spec/fixtures/'

    config.include Webrat::Matchers, :type => :views

    #machinist setup
    config.before(:all)    { Sham.reset(:before_all)  }
    config.before(:each)   { Sham.reset(:before_each) }
    #end machinist setup
  end
end

Spork.each_run do
  # This code will be run each time you run your specs.
  require File.expand_path(File.dirname(__FILE__) + "/blueprints")

  Spec::Runner.configure do |config|
    config.include ViewHelpers, :type => :views
    config.include ControllerHelpers, :type => :controller
    config.extend ControllerMacros, :type => :controller
  end
end

I went the route of adding --drb to the spec.opts file. This works with textmate and autospec. If you forget to run spork it'll run locally without the drb.

If you want something more (or actually) distributed for your tests take a look at testjour, or even some of the cloud computing services (which I've forgotten the names of!).

Sorry, comments are closed for this article.