40歳からのキャリアチェンジ

20代はエンジニア・PM、30代はWeb系エンジニア向けのキャリアアドバイザー。40代の今はフリーランスで開発含めて色々やってます。技術ネタとしてはRuby/RailsとJavaScript関連あたり

RSpec使ってERBに対するspecをどう書くか?

RSpec使ってERBに対するspecをどう書くのか模索してみて、最低限の書き方は自分なりに理解できたので折角なのでブログにまとめておこうと思います。

自分の環境はこんな感じです

あと、前提として

  • 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として描画される内容/ という意味なのか!」

と気づけて、そこからいっきに道が開けた感じになりました。