Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
30
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

Organization

RailsでController Specを書く際に知っておきたいTips

概要

RailsでController Specを書く際に、知っておくと便利なことをまとめました。

環境

  • Ruby 2.3.1
  • Ruby on Rails 5.0.0.1

Tips

ユーザーエージェントの切り替え

PCスマホで処理を切り替えるなど、ユーザーエージェントを参照して処理を行うactionをテストする場合には、次のようにユーザーエージェントを設定することでテストできます。

hoge_controller_spec.rb
RSpec.describe HogeController, type: :controller do
  describe "GET #index" do
    context 'iPhoneの場合' do
      it "returns http success" do
        request.env["HTTP_USER_AGENT"] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X; en-us) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53'
        get :index
        expect(response).to have_http_status(:success)
      end
    end
  end
end

ちなみにデフォルトでは「Rails Testing」というユーザーエージェントが設定されています。

明示的にクエリパラメータとして渡す

パラメータに対応する静的URLがあるが、あえて、クエリパラメータでアクセスしたい場合には次のようにします。

route.rb
Rails.application.routes.draw do
  get '/hoge' => 'hoge#index'
  get '/hoge/page-:page' => 'hoge#index'
end
hoge_controller_spec.rb
RSpec.describe HogeController, type: :controller do
  describe "GET /hoge/page-1" do
    context '/hoge/page-1でアクセス' do
      it "returns http success" do
        get :index, params: {page: '1'}
        expect(response).to have_http_status(:success)
      end
    end
  end

  describe "GET /hoge/?page=1" do
    context '/hoge/?page=1でアクセス' do
      it "returns http success" do
        request.env['PATH_INFO'] = '/hoge/?page=1'
        get :index, params: {page: '1'}
        expect(response).to have_http_status(:success)
      end
    end
  end
end

クエリパラメータを使っていたが、静的URLに移行したといった場合のリダイレクトなどのテストに必要になると思います。

ドメイン情報を含んだリダイレクト先のテスト

リダイレクト先のテストをするためには、redirect_toメソッドが用意されています。
redirect_toの使い方については、こちらのリンクに書かれています。
ここでは、上のリンクで説明されていない特殊なケースについて説明します。

同じRailsアプリケーション内で複数のドメインを使っている場合には、リダイレクト先にドメインを含んだパスを指定する必要がありますが、その際にredirect_toはドメインを自動的に補完してしまいます。
そういった場合には、次のようにドメインを明示的に指定すれば大丈夫です。

route.rb
Rails.application.routes.draw do
  get '/hoge/redirect' => 'hoge#redirect'

  constraints(:host=> /fuga\.hoge\.com\.jp/) do
    get '/hoge' => 'hoge#fuga_index'
  end
end
hoge_controller_spec.rb
RSpec.describe HogeController, type: :controller do
  describe "GET /hoge/redirect" do
    it "//fuga.hoge.com/hogeへのリダイレクト" do
      subject {get :redirect }
      expect(subject).to redirect_to('//fuga.hoge.com/hoge')
    end
  end
end

render_views

render_viewsは、その名の通りController Specを実行する際にViewのレンダリングをすることを指定するためのメソッドです。
これを指定しないとView内のエラーを拾うことができないので、基本的には設定することをお薦めします。
例えば、次のような、View内で未定義の変数を参照するといった明らかなバグを含んでいる場合であってもrender_viewsを記述しない場合にはテストが通ってしまいます。

hoge_controller_spec.rb
RSpec.describe HogeController, type: :controller do
  describe "GET /hoge" do
    render_views

    it "returns http success" do
      get :index
      expect(response).to have_http_status(:success)
    end
  end
end
hoge/index.html.erb
<h1>Hoge#index</h1>
<p><%= hoge %>の一覧です。</p>
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
30
Help us understand the problem. What are the problem?