Testing Sinatra with Rack::Test
All examples in the following sections assume that Test::Unit
is being
used in an attempt to be as general as possible. See the Test Framework
Examples for information on using the test helpers in
other testing environments. To use the Rack::Test
library used when you require rack/test
, you’ll need to install the rack-test
gem:
gem install rack-test
You can also add it to your applications Gemfile
like this:
gem 'rack-test'
Example App: hello_world.rb
The following example app is used to illustrate testing features. This is
assumed to be in a file named hello_world.rb
:
require 'sinatra'
get '/' do
"Hello World #{params[:name]}".strip
end
Using The Rack::Test::Methods
Mixin
The Rack::Test::Methods
module includes a variety of helper methods for
simulating requests against an application and asserting expectations about
the response. It’s typically included directly within the test context and
makes a few helper methods and attributes available.
The following is a simple example that ensures the hello world app functions properly:
ENV['APP_ENV'] = 'test'
require 'hello_world'
require 'test/unit'
require 'rack/test'
class HelloWorldTest < Test::Unit::TestCase
include Rack::Test::Methods
def app
Sinatra::Application
end
def test_it_says_hello_world
get '/'
assert last_response.ok?
assert_equal 'Hello World', last_response.body
end
def test_it_says_hello_to_a_person
get '/', :name => 'Simon'
assert last_response.body.include?('Simon')
end
end
Using Rack::Test
without the Mixin
For a variety of reasons you may not want to include Rack::Test::Methods
into your own classes. Rack::Test
supports this style of testing as well,
here is the above example without using Mixin.
ENV['APP_ENV'] = 'test'
require 'hello_world'
require 'test/unit'
require 'rack/test'
class HelloWorldTest < Test::Unit::TestCase
def test_it_says_hello_world
browser = Rack::Test::Session.new(Rack::MockSession.new(Sinatra::Application))
browser.get '/'
assert browser.last_response.ok?
assert_equal 'Hello World', browser.last_response.body
end
def test_it_says_hello_to_a_person
browser = Rack::Test::Session.new(Rack::MockSession.new(Sinatra::Application))
browser.get '/', :name => 'Simon'
assert browser.last_response.body.include?('Simon')
end
end
Rack::Test’s Mock Request Methods
The get
, put
, post
, delete
, and head
methods simulate the
respective type of request on the application. Tests typically begin with
a call to one of these methods followed by one or more assertions against
the resulting response.
All mock request methods have the same argument signature:
get '/path', params={}, rack_env={}
-
/path
is the request path and may optionally include a query string. -
params
is a Hash of query/post parameters, a String request body, ornil
. -
rack_env
is a Hash of Rack environment values. This can be used to set request headers and other request related information, such as session data. See the Rack SPEC for more information on possible key/values.
Asserting Expectations About The Response
Once a request method has been invoked, the following attributes are available for making assertions:
-
app
- The Sinatra application class that handled the mock request. -
last_request
- TheRack::MockRequest
used to generate the request. -
last_response
- ARack::MockResponse
instance with information on the response generated by the application.
Assertions are typically made against the last_response
object.
Consider the following examples:
def test_it_says_hello_world
get '/'
assert last_response.ok?
assert_equal 'Hello World'.length.to_s, last_response.headers['Content-Length']
assert_equal 'Hello World', last_response.body
end
Optional Test Setup
The Rack::Test
mock request methods send requests to the return value of
a method named app
.
If you’re testing a modular application that has multiple Sinatra::Base
subclasses, simply set the app
method to return your particular class.
def app
MySinatraApp
end
If you’re using a classic style Sinatra application, then you need to return an
instance of Sinatra::Application
.
def app
Sinatra::Application
end
Making Rack::Test
available to all test cases
If you’d like the Rack::Test
methods to be available to all test cases
without having to include it each time, you can include the Rack::Test
module in the Test::Unit::TestCase
class:
require 'test/unit'
require 'rack/test'
class Test::Unit::TestCase
include Rack::Test::Methods
end
Now all TestCase
subclasses will automatically have Rack::Test
available to them.
Test Framework Examples
As of version 0.9.1
, Sinatra no longer provides testing framework-specific
helpers. Those found in sinatra/test/*.rb
are deprecated and has been
removed in Sinatra 1.0
.
RSpec
Sinatra can be tested under plain RSpec. The Rack::Test
module should be
included within the describe
block:
ENV['APP_ENV'] = 'test'
require 'hello_world' # <-- your sinatra app
require 'rspec'
require 'rack/test'
RSpec.describe 'The HelloWorld App' do
include Rack::Test::Methods
def app
Sinatra::Application
end
it "says hello" do
get '/'
expect(last_response).to be_ok
expect(last_response.body).to eq('Hello World')
end
end
Make Rack::Test
available to all spec contexts by including it via
RSpec
:
require 'rspec'
require 'rack/test'
RSpec.configure do |conf|
conf.include Rack::Test::Methods
end
Test::Spec
The Rack::Test
module should be included within the context of the
describe
block:
ENV['APP_ENV'] = 'test'
require 'hello_world' # <-- your sinatra app
require 'test/spec'
require 'rack/test'
describe 'The HelloWorld App' do
include Rack::Test::Methods
def app
Sinatra::Application
end
it "says hello" do
get '/'
last_response.should.be.ok
last_response.body.should.equal 'Hello World'
end
end
Make Rack::Test
available to all spec contexts by including it in
Test::Unit::TestCase
:
require 'test/spec'
require 'rack/test'
Test::Unit::TestCase.send :include, Rack::Test::Methods
Capybara
Capybara
will use Rack::Test
by default. You can use another driver, like
Selenium
, by setting the default_driver.
ENV['APP_ENV'] = 'test'
require 'hello_world' # <-- your sinatra app
require 'capybara'
require 'capybara/dsl'
require 'test/unit'
class HelloWorldTest < Test::Unit::TestCase
include Capybara::DSL
# Capybara.default_driver = :selenium # <-- use Selenium driver
def setup
Capybara.app = Sinatra::Application.new
end
def test_it_works
visit '/'
assert page.has_content?('Hello World')
end
end
See Also
See the source for Rack::Test for
more information on get
, post
, put
, delete
and friends.