RSpec使ってERBに対するspecをどう書くのか模索してみて、最低限の書き方は自分なりに理解できたのでまとめておこうと思います。
自分の環境
こんな感じです
- 環境
- Mac OS X 10.9.4
- ruby 2.1.0
- Rails 4.0.1
- rspec-rails 2.13.1
- factory_girl_rails 4.2.1
一応前提として
- RSpecの概念がざっくりわかってる
- RSpec使ったテストの実行方法を知ってる
- FactoryGirlでテストデータが登録済である
という感じで以下書いてます。
FactoryGirlのテストデータはこんなのを準備してあるということで説明していきます
FactoryGirl.define do
# 一部省略
factory :event do
name 'サンプルイベント : サンプル1(北海道)'
price_man 10000
price_woman 8000
price_boy 5000
price_girl 4000
end
end
まずはひな形となるspecを生成する
app/views/events/show.html.erbというファイルがあったとします。その場合には以下のようにして、ひな形となるspecを作ります。
./bin/rails g rspec:view events show
spec/views/events/show.html.erb_spec.rbが自動的に生成されます
show.html.erb_spec.rbを編集する
ひな形をベースにして、以下のように編集します。
require 'spec_helper'
describe "events/show" do
before do
@event = FactoryGirl.build(:event)
@event.save
end
it "イベント情報の名前の表示が行える" do
assign(:event, @event)
render :template => "events/show.html.erb"
expect(rendered).to match /サンプルイベント : サンプル1(北海道)/
end
編集が完了したら
./bin/bundle exec rspec spec/views/events/show.html.erb_spec.rb
という感じでテスト実行します。
レンダリングされたHTMLの中にサンプルイベント : サンプル1(北海道)という文字が含まれてるかどうかが to match /xxx/という所で評価されて、問題なければテストがパスするという感じになってます
ハマった所
実際に自分が今仕事で関わってるものは、今回ここで示してるものと当然ことなってて、2つほどハマったことがあったのでそれをまとめておこうと思います。※まだ理解が浅いから、きっと近いうちにまた同じことでハマりそうなんで^^;
before doの記述
このERBを呼び出すapp/controllers/events_controller.rbでのshowメソッドの処理は
def show
@calendar = EventCalendar.new(@event, calendar_options(params[:year], params[:month]))
# その他処理
end
# 中略
private
def calendar_options(year, month)
{
year: year,
month: month
}
end
みたいな感じになっています。そのため、上記で書いた
before do
@event = FactoryGirl.build(:event)
@event.save
end
というものだけでは、app/views/events/show.html.erbの描画をするのに必要なオブジェクトが不足してるため
before do
@event = FactoryGirl.build(:event)
@calendar = EventCalendar.new(@event, {year:2014, month:10})
@event.save
end
という処理が必要というのがすぐわからず地味にはまりました。
to_match内の記述
RSpec使ってERBに対するspecをどう書いていいのかわからず、ひとまず
を参考にしてました。
後者のやつは3.x系の話っぽいけど、説明は自分としてはわかりやすく大枠はこれでつかめたのですが、to_match内の記述をどう書いていいのかさっぱりわかりませんでした。。
具体的には、こんなサンプルが上記サイトにあって
require "rails_helper"
RSpec.describe "rendering the widget template" do
it "displays the widget" do
assign(:widget, Widget.create!(:name => "slicer"))
render :template => "widgets/widget.html.erb"
expect(rendered).to match /slicer/
end
end
実際のERBにこんなのがあったとして、なんで、match /slicer/ ってなるのかが理解できませんでした。
<h2><%= @widget.name %></h2>
slicer っていうのがどっから出てきた単語かが最初すぐにわからなかったのと、match /xxx/ という記法って何だろうって疑問だったのですが、失敗したテストの画面を眺めていたら
「もしかして、match / 実際にHTMLとして描画される内容/ という意味なのか!」
と気づけて、そこからいっきに道が開けた感じになりました。