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
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.