RSpec and Sinatra Quick Start

August 01, 2009

Are you familiar with RSpec, new to Sinatra, and can’t get the two to cooperate? This article maybe of use to you. Alternatively, if you’re like me and you’re simply new to this universe all together, this article can certainly be of use.

I recently started playing with learning Sinatra after months of procrastination. I started with some exploratory (throw away) code. My preliminary results were good and I was quickly hooked. I needed a more substantial problem to solve. I decided to take this site and redo it using Sinatra. The first task I needed to tackle, was learning how to specify my Sinatra application. I prefer RSpec, so naturally I focused my effort on getting RSpec setup with Sinatra. After running through this setup a few times, it seems like trivial knowledge to share. At the time, it took some real investigation to get it all going. If I can save (at least) one person a little time, then this article has served a purpose. As a bonus, if you’re using autospec, the following setup is compatible.

I’ll assume you’ve used RSpec before and you’re machine is configured correctly. If this assumption is incorrect, you can get up to speed here.

As a prerequisite, we need to add a few things to your filesystem. Here’s the list:

  1. Make a new spec folder in the root of your application folder
  2. Make a new spec_helper.rb file inside your spec folder
  3. Make a new spec.opts file inside your spec folder
  4. Make a new spec file inside your spec folder for your application
    ex. myapp_spec.rb

If you’re down with some terminal action, you can use these commands to accomplish all the steps above.

$ cd your/app_dir/
$ mkdir spec
$ touch spec/spec_helper.rb
$ touch spec/spec.opts
$ touch spec/myapp_spec.rb

Spec Helper

Lets move on to the spec_helper setup, shall we? The setup is pretty simple and for the most part, you can just paste in the following code and you’ll be good. There is one thing to note. Sinatra now relies on Rack::Test and has deprecated the use of Sinatra::Test.

Update: Vinicius has pointed out a few oversights in this article. The first is myapp.rb found on line one of the spec_helper. If the file that contains your application isn’t named myapp.rb (and it probably isn’t), you should update myapp.rb to match the name of your application file. Before continuing, you also need the rack-test gem installed. Simply issue the “sudo gem install rack-test” command at the command-line and you’ll be ready to proceed.

require File.join(File.dirname(__FILE__), '..', 'myapp.rb')

require 'rubygems'
require 'sinatra'
require 'rack/test'
require 'spec'
require 'spec/autorun'
require 'spec/interop/test'

# set test environment
set :environment, :test
set :run, false
set :raise_errors, true
set :logging, false

The spec.opts file is even simpler to setup. These are the basic options I use.

--colour
--format progress
--loadby mtime
--reverse

The Spec File

Now that all the setup work is complete we can write some specs. Requiring our spec_helper.rb file will grant our spec the magical powers it needs to be useful. The last thing we’ll need to do is include Rack::Test::Methods. We get all the goodies of Rack::Test via a mixin and we don’t need to inherit from a super class (I’m really happy they did it this way). The basic template for your specs will look like this:

require File.dirname(__FILE__) + '/spec_helper'

describe "My App" do
  include Rack::Test::Methods

  def app
    @app ||= Sinatra::Application
  end

  it "should respond to /" do
    get '/'
    last_response.should be_ok
  end
end

You can use last_response for most of your testing needs. You can test response headers like so:

it "should return the correct content-type when viewing root" do
  get '/'
  last_response.headers["Content-Type"].should == "text/html"
end

Testing status:

it "should return 404 when page cannot be found" do
  get '/404'
  last_response.status.should == 404
end

Testing the output:

it "should return blah blah blah when viewing root" do
  get '/'
  last_response.body.should == "blah blah blah"
end

That wasn’t that bad, was it? It would be a tragedy if the beautiful simplicity of Sinatra was paired with a complicated testing experience. That said, I think RSpec and Sinatra make great crime partners. If you’ve made it this far, let me reward you with a few more things you should probably read: Rack::Test Documentation, Testing Sinatra with Rack::Test. You can also explore the source for this site’s specification.