おもしろwebサービス開発日記

Ruby や Rails を中心に、web技術について書いています

OmniAuthを利用しているプロジェクトのSystemテストでログインを可能な限り省略する

大抵のwebサービスのSystemテストは、ログインしてから何かをすることになると思います。ログイン機能のテストはちゃんとある前提で、ログインのために「トップページ→ログインページ→ログイン処理→ログイン画面」までの遷移を毎回やるのは時間がかかる。

deviseはそれを解決するためのテストヘルパーを用意していて、「次のリクエストをログイン状態として扱う」ができるようになっています*1

deviseではなくOmniAuthを単体で使っている場合はOmniAuth.config.test_mode = trueとしておいて、次のようにモックデータを用意することで「トップページ→"/auth/twitter"→"/auth/twitter/callback"→ログイン後のページ」のような遷移をしている人が多いはず。

OmniAuth.config.mock_auth[:twitter] = OmniAuth::AuthHash.new({
  :provider => 'twitter',
  :uid => '123545'
  # etc.
})

ref: Integration Testing · omniauth/omniauth Wiki

しかし、素朴な実装であれば直接"/auth/twitter/callback"にアクセスしてもログインすることができます。つまり

def login
  visit root_path
  click_on "Twitterでログイン" # ここで/auth/twitter ->/auth/twitter/callback -> ログイン後のページへの遷移が起きる
  expect(page).to have_content 'ログインしました'
end  

というコードを

def login
  visit "/auth/twitter/callback" # ログイン後のページへのリダイレクトが起きる
  expect(page).to have_content 'ログインしました'
end

に変更するということ。これで「トップページ→"/auth/twitter"」へのアクセスが省略できるのでちょっぴりsystemテストが高速化されます。ちょっぴり、とはいえ大量のテストがある場合は馬鹿にならないと思うので該当する方は試してみると良いかと思います*2

*1:systemテストで扱うには工夫が必要なこともあるけど今回はそこには触れません

*2:もちろんログイン機能のテストは別でちゃんと定義しておきましょう