#環境
ruby 2.2.2p95
Rails 4.2.3
devise 3.5.6
minitest 5.8.4
fixture
#deviseの導入
導入方法については詳しい記事がたくさんあるのでそちらを参考にしてください。
Qiita:Deviseの設定手順をまとめてみた。 その1 導入編
とか
Qiita:Rails 4.2 で ユーザー管理・認証 (devise)
とか。
フィールドを追加する場合はこちらを参考にすると良いと思います。
Qiita:Rails + Deviseでusernameを追加する
#testの前に
githubのwikiは目を通しておくと良いでしょう。
あとminitestで書きます。
wikiにはRSpec, factrygirlの書き方が載っていますので参考にしてください。
#functional test
fixtureでユーザーを用意します。
john:
email: "john@example.com"
encrypted_password: <%= Devise::Encryptor.digest(User, 'password') %>
コントローラーテストではinclude Devise::TestHelpers
を使います。
class hogesControllerTest < ActionController::TestCase
include Devise::TestHelpers
def setup
@user = users( :john )
sign_in(@user)
end
end
これだけでuser:john
でログインしたことになり、テストができます。
#integration test
WikiによるとDevise::TestHelpers
が使えないようなのでDeviseの核となっているWardenのTestHelperを使います。
class FugaTest < ActionDispatch::IntegrationTest
include Warden::Test::Helpers
def setup
Warden.test_mode!
@user = users( :john )
login_as(@user, :scope => :user)
end
end
これでコントローラーテストと同様user:john
でログインしたことになります。
#ヘルパーを使う場合
こんな感じでlog_in
というメソッドをつくってみると、functional test, integration testどちらでも使えます。
(ログイン周りでもう少し面倒なことをしている場合は、このように共通化しておくと良いと思います。
class ActiveSupport::TestCase
def log_in( user )
if integration_test?
#use warden helper
login_as(user, :scope => :user)
else #controller_test, model_test
#use devise helper
sign_in(user)
end
end
# 統合テスト内ではtrueを返す
def integration_test?
defined?(post_via_redirect)
end
end
#注意:confirmableについて
メール認証オプションであるconfirmableを利用している場合は普通にログインしてもunauthenticated
が返ってきてしまうため、以下いずれかの対応が必要です。
(自動テストでなければメール配信してリンクをクリックしたり、コンソールに書き出されたURLへアクセスすれば良いのですけどね。)
##1:fixtureで対応する場合
userにconfirmed_atを追記してください。
これでメール認証済みになります。
john:
email: "john@example.com"
encrypted_password: <%= Devise::Encryptor.digest(User, 'password') %>
confirmed_at: <%= Time.now - 100 %>
##2:新規ユーザー作成している場合
テスト中に新規ユーザーを作成するケースがあると思います。
その場合はskip_confirmation!
を使うと認証をスキップできます。
(user.confirmでも良いですが、こちらを使うと「本登録完了しました」メールが発送されます。)
※先ほどtest_helper内に作成したlog_inメソッドを利用しています。
user = User.new email: 'john@example.com', password: '12345678'
user.skip_confirmation!
user.save!
log_in( user )
###参考
そんなこと覚えてない: Devise で email 変更する。
Qiita: deviseでconfirmable設定をした際の確認メールをスキップさせる skip_confirmation! は、対象のオブジェクトをsaveする前に書く
#謝辞
Twitterでテストがうまくいかないことを呟いていたら、颯爽と現れてアドバイスをいただいた伊藤淳一さん、本当にありがとうございます。
※ちなみにその時ハマっていたのは最後に書いたconfirmableのところです。