RSpec使ってERBに対するspecをどう書くか?
RSpec使ってERBに対するspecをどう書くのか模索してみて、最低限の書き方は自分なりに理解できたので折角なのでブログにまとめておこうと思います。
自分の環境はこんな感じです
あと、前提として
という感じで以下書いてますの。
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として描画される内容/ という意味なのか!」
と気づけて、そこからいっきに道が開けた感じになりました。