sinatraでテストの入門の入門(その1)

sinatraすげー」って今さら思い、sinatraで何か作ってみようかねーと思い、当然テストのことが気になりました。

そもそも「テスト出来るの?実はrailsと比べて大変じゃないの???」って感じのアホな不安でした。(1週間前までsinatraのことと言えば名前しかしらなかったので。。)テストについてはちゃんと公式ページで解説されています。rspecも使えます。capybaraも使えます。他のテストフレームワークも使えるようです。

参考ページは

です。ここの内容を理解していきます。

サンプルコード

テスト対象のコード。いつものhello world

require 'sinatra'

get '/' do
  "Hello World #{params[:name]}".strip
end

テストコード

require './hello_world'     # ruby1.9はこうしないと動かないはず。
require 'test/unit'
require 'rack/test'

ENV['RACK_ENV'] = '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

コードの理解

Rack::Testっていうのがsinatraのリクエストとかをシュミレートしてくれるライブラリで

include Rack::Test::Methods

ってやると色々便利メソッドを追加してくれます。include Rack::Test::Methodsってやらないと、各行でRack::Test::Session.new(Rack::MockSession.new(Sinatra::Application))のインスタンスに対してアサーションやら色々おこなうことになり、かっこよくないです。

以下で便利メソッドを理解していきます。

リクエスト生成

get、put、post、delete、headメソッド

railsやってるとおなじみになっているhttpメソッドをシュミレートする各メソッドです。
引数は

  • '/path' : urlのパス
  • params={} : パラメータ
  • rack_env={} : rackの環境変数。sessionとか入るとか書いてある。(実はよく理解していない。。)

をそれぞれ渡します。

レスポンス

getメソッド等で、リクエストをシュミレートした後は以下の2つの変数が設定されます。

  • last_request : リクエスト
  • last_response : リクエストのレスポンス

last_responseに実際動かす時にブラウザに渡ってくる情報が全部入ってくる感じ。
なので、

last_response.body
last_response.headers
last_response.ok?

とかって感じで使います。このlast_responseがアサーションの対象の元になる。

もう一つのlast_requestってようするにリクエストの内容だと思うんだけど何に使うんだろ?

さらにもう一つ

Rack::Testはリクエストのレスポンスを返す時にappというメソッドにテスト対象のアプリケーション名(インスタンスなのかな?)があると想定しているようです。
そのため、テストにappというメソッドを定義する必要があります。

例としてこの記事の最初にあるサンプルコードからappメソッドの定義を削除すると

undefined local variable or method `app' for #

って見事に落ちます。

includeをhelperに

sinatraテストで必須のRack::Test::Methodsのインクルードですが、当然helperでやれば一箇所にまとめられます。

require 'test/unit'
require 'rack/test'

class Test::Unit::TestCase
  include Rack::Test::Methods
end

こんな感じ。

まとめ

入門の入門としてのまとめ。

  1. sinatraでテストすることは簡単。(rubyですもの)
  2. ただし、Rack::Testをインクルードしてリクエストやレスポンスのやりとりをするので、Rack::Testを覚える必要あり。
  3. そうはいっても、レスポンスはlast_responseにあるからそこを検証すればだいたいやりたいことは出来そう。

rspec版を書きました。こちらからどうぞ。