Thursday, November 24, 2011

Adding rspec to sinatra

In the previous post I showed how to deploy a sample sinatra app on Cloud Foundry using rake, and now I'm going to add rspec tests to the app.

The first step is to add the rspec gem to your Gemfile and run bundle
source "http://rubygems.org"

gem 'sinatra'

group :test do
  gem 'rspec'
end
Next you need to create the spec directory and add the spec_helper.rb file
require File.join(File.dirname(__FILE__), '..', 'app.rb')

require 'sinatra'
require 'rack/test'

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

def app
  Sinatra::Application
end

RSpec.configure do |config|
  config.include Rack::Test::Methods
end
This is for a classic style sinatra app, if you are using a modular app, you need to make some slight modifications for it to work. I'll show how to do that in a later post.

And finally you are ready to create the spec file that corresponds to the app.rb
require 'spec_helper'

describe "Sinatra App" do

  it "should respond to GET" do
    get '/'
    last_response.should be_ok
    last_response.body.should match(/It works!/)
  end

end
I usually don't use rspec for integration tests, for that I use cucumber. I normally use rspec for unit testing, but since this is a sample app and I don't have any models to test, I included this test for completeness sake. I'll write another blog post how to add cucumber tests to this sample sinatra app later.
To make life easier, I've added a rake task to run the rspec tests
require 'rspec/core/rake_task'

desc "run specs"
RSpec::Core::RakeTask.new
And then I've updated the deployment task to require the rspec task, so we can't update the application unless it passes all tests.
namespace :vmc do
  desc "update cloud foundry deployment"
  task :update => [:bundle, :spec] do
    sh "vmc update #{VMC_APP_NAME}"
  end
end
I've created a github repository for this app to make it easier for you to use it as a template.

Wednesday, November 23, 2011

My Cloud Foundry development laptop

I've been assembling a new laptop for Cloud Foundry development, and thought I'd document it for my own sake (and also so other can benefit from it).

Hardware
  • MacBook Pro
  • 27" Apple ThunderBolt screen
    One at work and one at home - so it can burn some midnight oil using the exact layout as at the office.
I'm not 100% satisfied with the screen, for two reasons:
  1. there is a bug that sometimes makes the network connection and USB go bonkers and force me to reboot
  2. the screen is very glossy, I prefer matte, but this is not a big issue
Once the price of ThunderBolt disk enclosures drops I'll get one so I can keep my photo archive on it.

It may seem like am an Apple fanboy, but it is not entirely true - I do like their products, but mostly it comes down to "it just works". I've got better things to do than fiddle with kernel updates and trying to get drivers to work...

Software
Apart from that I've got a bunch of other programs, but those are not development related.

Sunday, November 20, 2011

Rake file for a sinatra app on Cloud Foundry

My boss is on his money moon, next week is thanks giving, there is no fire to put out and the baby is sleeping - which means I had some time to catch up with my personal todo list today! One thing on it is a simple sinatra app which I wil deploy to Cloud Foundry later.
Exactly what the app is about isn't important, but rather how to get started with it. Note that I'm skipping over all BDD & TDD for now...
Usually I start with something simple like this:
Gemfile
source "http://rubygems.org"

gem 'sinatra'
app.rb
require 'sinatra'

get '/' do
  "It works!"
end
Then I run bundle to grab any missing gems, and then run ruby app.rb to start the app, and finally I verify that it works with curl localhost:4567
If everything turns out ok, I'll deploy the app on Cloud Foundry with:
vmc push -n cf-rake-sinatra
Creating Application: OK
Uploading Application:
  Checking for available resources: OK
  Packing application: OK
  Uploading (1K): OK
Push Status: OK
Staging Application: OK
Starting Application: OK
Now I can verify that this works too, using curl cf-rake-sinatra.cloudfoundry.com. Once this initial deploy is done, I'll run vmc update cf-rake-sinatra each time I change the app. Sometimes I add a new gem dependency, and it has happened more than once that I forget to run bundle, so I've created a Rakefile with two of commonly used tasks:
Rakefile
APP = "cf-rake-sinatra"

$:.unshift(File.dirname(__FILE__))

task :default => [:run]

desc "run app locally"
task :run => "Gemfile.lock" do
  require 'app'
  Sinatra::Application.run!
end

# need to touch Gemfile.lock as bundle doesn't touch the file if there is no change
file "Gemfile.lock" => "Gemfile" do
  sh "bundle && touch Gemfile.lock"
end

namespace :vmc do
  desc "update cloud foundry deployment"
  task :update => "Gemfile.lock" do
    sh "vmc update #{APP}"
  end

  desc "get application status"
  task :status do
    sh "vmc stats #{APP}"
  end
end
This will run bundle any time Gemfile is newer than Gemfile.lock so that we always have up to date gems.
The full list of available rake tasks are:
rake -T
(in /Users/martin/src/ruby/cf-rake-sinatra)
rake run         # run app locally
rake vmc:status  # get application status
rake vmc:update  # update cloud foundry deployment