Sunday, June 7, 2009

Rack Test with RSpec

‹prev | My Chain | next›

No too long ago, I upgraded to Sinatra 0.9.2. Ever since then I've been getting deprecation warnings in my RSpec output:
cstrom@jaynestown:~/repos/eee-code$ rake
(in /home/cstrom/repos/eee-code)

==
Sinatra app spec
Sinatra::Test is deprecated; use Rack::Test instead.
.......................
Since I've been mucking about with Rack recently, now is a good time to address that deprecation warning.

First up, I gem install rack-test. Next I update my spec_helper.rb by replacing:
require 'sinatra/test'
with:
require 'rack/test'
Also, per the Sinatra testing documentation, I inject Rack test methods into Test::Unit::TestCase:
Test::Unit::TestCase.send :include, Rack::Test::Methods
Finally (also per the documentation), I add an app method so that Rack::Test has somewhere to send requests:
def app
Sinatra::Application
end
After all that, when I run my specs, I get:
cstrom@jaynestown:~/repos/eee-code$ rake
(in /home/cstrom/repos/eee-code)

==
Sinatra app spec
F..F..F.FFF........FFFF

1)
NoMethodError in 'eee a CouchDB meal GET /meals/YYYY should respond OK'
undefined method `ok?' for nil:NilClass
./spec/eee_spec.rb:46:

2)
NoMethodError in 'eee a CouchDB meal GET /meals/YYYY/MM should respond OK'
undefined method `ok?' for nil:NilClass
./spec/eee_spec.rb:72:

3)
NoMethodError in 'eee a CouchDB meal GET /meals/YYYY/MM/DD should respond OK'
undefined method `ok?' for nil:NilClass
./spec/eee_spec.rb:104:

4)
NoMethodError in 'eee a CouchDB recipe GET /recipes/permalink should respond OK'
undefined method `ok?' for nil:NilClass
./spec/eee_spec.rb:141:

5)
'eee a CouchDB recipe GET /recipes/:permalink/:image should retrieve the image' FAILED
expected Rack::Lint::LintError but nothing was raised
./spec/eee_spec.rb:155:

6)
NoMethodError in 'eee a CouchDB recipe GET /recipes/:permalink/:image should return 404 for a non-existent image'
undefined method `not_found?' for nil:NilClass
./spec/eee_spec.rb:161:

7)
'eee GET /recipes/search should display a helpful message when no results' FAILED
expected the following element's content to include "No results":
./spec/eee_spec.rb:244:

8)
NoMethodError in 'eee GET /recipes/search should redirect without pagination after navigating beyond the pagination window'
undefined method `status' for nil:NilClass
./spec/eee_spec.rb:253:

9)
'eee GET /recipes/search should treat couchdb errors as no-results' FAILED
expected the following element's content to include "No results":
./spec/eee_spec.rb:263:

10)
'eee GET /recipes/search should treat couchdb-lucene errors as an empty query' FAILED
expected following output to contain a <input[@name=query][@value='']/> tag:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">

./spec/eee_spec.rb:272:

Finished in 0.315517 seconds

23 examples, 10 failures
I think most of those failures are likely due to using the old response from sinatra/test instead of the last_response from rack/test. Searching/replacing in my spec finds 10 occurrences, so maybe everything is working now:
 cstrom@jaynestown:~/repos/eee-code$ rake
(in /home/cstrom/repos/eee-code)

==
Sinatra app spec
.........F.............

1)
'eee a CouchDB recipe GET /recipes/:permalink/:image should retrieve the image' FAILED
expected Rack::Lint::LintError but nothing was raised
./spec/eee_spec.rb:155:

Finished in 0.293289 seconds

23 examples, 1 failure
Hmm... After some investigating, I find that spec to be an odd one:
    describe 'GET /recipes/:permalink/:image' do
it "should retrieve the image" do
data = RestClient.get "#{@@db}/#{@permalink}"
recipe = JSON.parse(data)

RestClient.put "#{@@db}/#{@permalink}/sample.jpg?rev=#{recipe['_rev']}",
File.read('spec/fixtures/sample.jpg'),
:content_type => 'image/jpeg'


lambda { get "/images/#{@permalink}/sample.jpg" }.
should raise_error(Rack::Lint::LintError)
end
What on Earth was I thinking when I wrote that? Normally I would be kicking myself for not leaving a comment behind on something like. Thankfully, I have plenty of documentation in my chain. This particular spec was written because I could not satisfactorily simulate a Sinatra session—my ultimate (unsatisfactory) solution was to test the spec library's implementation. With Rack::Test, I no longer need to do that, so I replace the lambda/should-raise_error weirdness with a simple get and should-be_ok:
    describe 'GET /recipes/:permalink/:image' do
it "should retrieve the image" do
data = RestClient.get "#{@@db}/#{@permalink}"
recipe = JSON.parse(data)

RestClient.put "#{@@db}/#{@permalink}/sample.jpg?rev=#{recipe['_rev']}",
File.read('spec/fixtures/sample.jpg'),
:content_type => 'image/jpeg'

get "/images/#{@permalink}/sample.jpg"
last_response.should be_ok

end
And now...
cstrom@jaynestown:~/repos/eee-code$ rake
(in /home/cstrom/repos/eee-code)

==
Sinatra app spec
.......................

Finished in 0.396667 seconds

23 examples, 0 failures

==
Helper specs
..............................................

Finished in 0.039739 seconds

46 examples, 0 failures

==
View specs
...................................................

Finished in 0.319114 seconds

51 examples, 0 failures
Yay! All my specs are passing and I was even able to get rid of a poor spec, making this excursion very much worthwhile.
(commit)

No comments:

Post a Comment