使用 Rack::Test 测试 Sinatra
以下所有示例都假设使用 Test::Unit
,以尽可能通用。有关在其他测试环境中使用测试助手的更多信息,请参阅 测试框架示例。要使用 Rack::Test
库(在您需要 rack/test
时使用),您需要安装 rack-test
gem
gem install rack-test
您也可以将其添加到应用程序的 Gemfile
中,如下所示
gem 'rack-test'
示例应用程序:hello_world.rb
以下示例应用程序用于说明测试功能。假设它位于名为 hello_world.rb
的文件中
require 'sinatra'
get '/' do
"Hello World #{params[:name]}".strip
end
使用 Rack::Test::Methods
Mixin
Rack::Test::Methods
模块包含各种辅助方法,用于模拟对应用程序的请求并断言对响应的期望。它通常直接包含在测试上下文中,并提供一些辅助方法和属性。
以下是一个简单的示例,确保 hello world 应用程序正常运行
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
不使用 Mixin 使用 Rack::Test
由于各种原因,您可能不想将 Rack::Test::Methods
包含到您自己的类中。 Rack::Test
也支持这种测试风格,以下是上面示例中不使用 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 的模拟请求方法
get
、put
、post
、delete
和 head
方法模拟了应用程序上相应的请求类型。测试通常从调用其中一个方法开始,然后对生成的响应进行一个或多个断言。
所有模拟请求方法都具有相同的参数签名
get '/path', params={}, rack_env={}
-
/path
是请求路径,可以选择包含查询字符串。 -
params
是一个包含查询/POST 参数的哈希表,一个字符串请求体,或者nil
。 -
rack_env
是一个包含 Rack 环境值的哈希表。它可以用来设置请求头和其他与请求相关的信息,例如会话数据。有关可能键/值对的更多信息,请参阅 Rack SPEC。
断言对响应的期望
一旦请求方法被调用,以下属性可用于进行断言
-
app
- 处理模拟请求的 Sinatra 应用程序类。 -
last_request
- 用于生成请求的Rack::MockRequest
。 -
last_response
- 一个Rack::MockResponse
实例,包含有关应用程序生成的响应的信息。
断言通常针对 last_response
对象进行。请考虑以下示例
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
可选测试设置
Rack::Test
模拟请求方法将请求发送到名为 app
的方法的返回值。
如果您正在测试具有多个 Sinatra::Base
子类的模块化应用程序,只需将 app
方法设置为返回您的特定类。
def app
MySinatraApp
end
如果您使用的是经典风格的 Sinatra 应用程序,那么您需要返回一个 Sinatra::Application
实例。
def app
Sinatra::Application
end
使 Rack::Test
可用于所有测试用例
如果您希望 Rack::Test
方法在无需每次都包含的情况下可用于所有测试用例,您可以在 Test::Unit::TestCase
类中包含 Rack::Test
模块
require 'test/unit'
require 'rack/test'
class Test::Unit::TestCase
include Rack::Test::Methods
end
现在,所有 TestCase
子类将自动拥有可用的 Rack::Test
。
测试框架示例
从版本 0.9.1
开始,Sinatra 不再提供特定于测试框架的帮助程序。在 sinatra/test/*.rb
中找到的那些已弃用,并在 Sinatra 1.0
中被删除。
RSpec
Sinatra 可以使用纯 RSpec 进行测试。 Rack::Test
模块应该包含在 describe
块中
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
通过 RSpec
包含 Rack::Test
,使其对所有规范上下文可用
require 'rspec'
require 'rack/test'
RSpec.configure do |conf|
conf.include Rack::Test::Methods
end
Test::Spec
Rack::Test
模块应该包含在 describe
块的上下文中
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
通过在 Test::Unit::TestCase
中包含 Rack::Test
,使其对所有规范上下文可用
require 'test/spec'
require 'rack/test'
Test::Unit::TestCase.send :include, Rack::Test::Methods
Capybara
Capybara
默认情况下将使用 Rack::Test
。您可以通过设置 default_driver 使用其他驱动程序,例如 Selenium
。
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
另请参阅
有关 get
、post
、put
、delete
及其相关方法的更多信息,请参阅 Rack::Test 的源代码。