Sinatra Tests 101 - RSpec

So much (not that much actually...) documentation about Rails testing, it's time to give Sinatra some love!

Tests! They're important. They're very important...except I never actually made them a part of my normal workflow. I never did that much testing, besides from manually hammering down new features to find out just how buggy they were.

I'm gonna demonstrate testing with Sinatra in a 3-part series, each mostly dedicated to one specific tool: RSpec, MiniTest & Cucumber, something like retracing my footsteps while I did a little research on the matter.

Anyway, I also wanted to make my goal to have auto testing with Guard https://github.com/guard/guard. An ideal setup would have you configure a Continuous Integration server, but this seemed like an interesting alternative for now.

First, I basically followed this guide http://code.tutsplus.com/tutorials/how-to-integrate-rspec-into-a-sinatra-app--net-21564 (Tuts+ Sinatra Rspec screencast) since, like i said, I had never dealt with tests before, and I wanted to get a feel of what I was getting into. I ignored the bit about Growl notifications and autotesting since I'm not really interested in the first, and I wanted to use Guard for the latter.

RSPEC

If you ignored my intro text and skipped the bit about following the previous tutorial: shame on you, I just wrote all of that for notthing...(for the other 10%, I won't be mad if you skip these lines instead)

Let's get to the good part!

I started by setting up a new folder project with a basic Gemfile (Foreman https://github.com/ddollar/foreman is optional of course, but it's always handy.)

source 'https://rubygems.org'

gem 'rspec'  
gem 'sinatra'  
gem 'rack'  
gem 'rack-test'  
gem 'guard'  
gem 'guard-rspec'  
gem 'foreman'  

I really hope you have Bundler http://bundler.io/ installed so go ahead and

$ bundle install

I hope you noticed guard-rspec since it's the little gem that's gonna take care of another important bit with ease. Just do

$ guard init rspec

and your Guardfile will be ready to go! Of course you should edit it, and of course you should check out what other options are available @https://github.com/guard/guard-rspec, but that's pretty much all you have to do to get it up and running.

Create a new file server.rb in the root of your project and give it a little Sinatra magic so Put this in your pipe and smoke it

require 'sinatra'

get '/' do  
  'Hello, World!'
end

get '/real_page' do  
  'The other page.'
end  

Next, create a spec folder and a server_spec.rb file in it. Mind the filename with _spec.rb since that's important for your Guardfile (and will be handy if you create your own Guard rules in the future!). You don't actually have to place it inside this folder, but keeping the tests separate is usually the norm.

require_relative '../server.rb'  
require 'rspec'  
require 'rack/test'

set :environment, :test

describe 'Server Service' do  
  include Rack::Test::Methods

  def app
    Sinatra::Application
  end

  it "should load the home page" do
    get '/'
    expect(last_response).to be_ok
  end

  it "should not load the home page" do
    get '/home'
    expect(last_response).to_not be_ok
  end

  it "should load the other page" do
    get '/real_page'
    expect(last_response).to be_ok
  end
end  

So much going on there...

  • require the sinatra server file
  • set the right environment for testing
  • set the app to be a Sinatra::Application
  • describe& it "should...", those are RSpec's terms

Bring up a terminal, redirect yourself to your project folder and start

$ rspec

If you see something like

RSpec success

you're awesome! If not...well...there's always debugger.

Finally, the auto bit of our testing adventure. If you followed in my footsteps exactly as described, all you have to do is add a Procfile to the root of your project so Foreman can take care of everything for us.

web: bundle exec ruby server.rb  
guard: bundle exec guard -i  

To go one step further, change your Guardfile and add the following rule, which says that for every file named X.rb, run spec/X_spec.rb :

guard :rspec, cmd: "bundle exec rspec" do  
    ...
    # RSpec files
    watch(/^(.+)\.rb$/)         { |m| "spec/#{m[1]}_spec.rb" }
    ...
end  

Now, just run

$ foreman start

and every time you save server.rb or server_spec.rb your test suite will be executed. Pretty cool!

As your test suite grows, you should follow some RSpec guidelines like including a spec_helper.rb file to load your dependencies, and also keep your testing dependencies to a minimum. When you are ready to know more, look no further than http://betterspecs.org/.

Again, I stress that in an ideal setup you could should prepare a CI server, have your tests run on every commit and not on every save, and enjoy having the possibility to change your code with confidence.

However, I figured that just like some people want their IDEs running tests automatically, others would want to do the same with Sublime Text or Atom, so just think of this as a way to mimic that functionality with a text editor.

Github Repository

Tiago Casanova

Developer @ Jumpseller. Currently working with Ruby & JavaScript. Curious and creative on a daily basis and works like a chameleon. Loves hoops and cooks.

Subscribe to Binary Lies

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!