rspec-rails3.0でのViewテストの書き方
rspec-rails3.0でのViewテストの書き方のメモ。
まずは公式に目を通しとくべき。
Upgrade - RSpec Rails - RSpec - Relish
view spec - View specs - RSpec Rails - RSpec - Relish
重なる内容もあるけど個人的に気になった点を以下に記述する。
Capybaraのmatchersを使う
have_tag
は無くなったようなのでCapybaraをインストールしてそのmatchersを使う。
Module: Capybara::Node::Matchers — Documentation for jnicklas/capybara (master)
spec_helper.rb
に以下の行を追加。
require 'capybara/rspec'
テストコードは以下のような感じになる。
describe "layouts/_navbar.html.haml" do
subject do
render partial: "layouts/navbar"
rendered
end
describe "session info" do
context "user not signed in" do
it { should have_text I18n.t('layouts.navbar.sign_in') }
end
end
end
have_cssではオプションのキーを指定する
have_css
(have_xpath
, have_selector
)のオプションには以下のようにtext:
等のキーを付ける。
it { should have_css(".username", text: "アリス さん") }
付けなくてもテストは動くが、表示されるメッセージに違いがある。
# text: を付けた場合
should have css ".username" with text "アリス さん"
# text: を付けずに文字列のみを渡した場合
should have css ".username"
Library not loaded
発生条件まで追っていないが、自分の環境ではCapybaraをインストールするとrails起動時に以下のエラーが発生するようになった。
/Users/yamotonalds/Work/project_dir/vendor/bundle/ruby/1.9.1/gems/activesupport-3.2.13/lib/active_support/dependencies.rb:251:in `require': dlopen(/Users/yamotonalds/Work/project_dir/vendor/bundle/ruby/1.9.1/gems/nokogiri-1.6.0/lib/nokogiri/nokogiri.bundle, 9): Library not loaded: /Users/yamotonalds/.rvm/rubies/ruby-1.9.3-p327/lib/libruby.1.9.1.dylib
Referenced from: /Users/yamotonalds/Work/project_dir/vendor/bundle/ruby/1.9.1/gems/nokogiri-1.6.0/lib/nokogiri/nokogiri.bundle
Reason: image not found - /Users/yamotonalds/Work/project_dir/vendor/bundle/ruby/1.9.1/gems/nokogiri-1.6.0/lib/nokogiri/nokogiri.bundle (LoadError)
nokogiri
を1.6.0から1.6.1にバージョンアップするとエラーは発生しなくなった。
bundle update nokogiri
Deviseを使っている場合
ReadmeにRSpecについての記述がある。
spec/support/devise.rb
を作成して以下を記述する。
RSpec.configure do |config|
config.include Devise::TestHelpers, type: :controller
config.include Devise::TestHelpers, type: :view
end
これで以下のようにsign_in
等が使える。
before do
sign_in FactoryGirl.create(:user)
end
view.stub(:current_user, stub_model(User))
とする方法もあるようだが、user_signed_in?
等の他のメソッドもあるためUser
クラスが使えるなら上記の方法で良いと思う。
helperのstub
before do
view.stub(:admin?).and_return(true)
end
stub_modelとmock_modelの使い分け
大体以下のような感じだと思う。
stub_model
呼び出すごとに固有のid
(正確にはto_param
)を持ったインスタンスを作成する。指定するクラスは実在しなければならない。
つまり、実際にDBにデータを保存せずに永続化されたオブジェクトのdoubleを作るメソッド。
stub_model(Widget).as_new_record
とすることで永続化していないオブジェクトのdoubleも作れる。
mock_model
基本的にはstub_model
と同じで、ActiveModel
のメソッドがstub化されたdoubleを作るメソッド。指定するクラスはActiveModel::Naming
を継承している必要がある。
stub_model
との大きな違いは実在しないクラスでも文字列で渡せばOKなところ。自動的にActiveModel::Naming
を継承したクラスを作ってくれる。
分業しててViewのテストを作る時にまだ必要なクラスが作成されていない場合等に使える。
注意: Ruby 1.9.3では"Hoge::Foo"
のようにモジュール内のクラスを指定するとNameError
が発生する。Ruby 2.1.0では修正されていた。