capybaraとrspecを使ったテストコード
こんにちは!
今回は趣向を変えて、ヲタクトークから始めます。
本日8/26は私が好きなバンド、PEDROの2nd フルアルバム「浪漫」の発売日です!
リード曲「浪漫」のMVを置いておきます。
www.youtube.com
初期の「自律神経出張中」みたいな、世の中にツバかけるような曲も好きですが、最近は「生活革命」のように"ふとした幸せ"みたいな曲が増えてて、好きが増しています。
「浪漫」は後者ですね。
早くライブに行きたい。。。
では、今回のコンテンツです。
本題と概要
最近Rspecでテストコードを書く練習をしています。
今回の記事では、アプリを使うときの一連の動作をテストコードで模した時に、私が気になったポイントを何点か紹介します。
なお、上記のテストは「結合テスト」とか、「統合テスト」とか、「エンドツーエンドテスト」などと呼ばれています。
rails g rspec:system hoges
みたいにするとRSpecが
spec/system/hoges_spec.rb
を作ってくれます。(gem 'rspec-rails'がインストールされている前提です。)
テストコードで、ブラウザ操作を実行する時には、Capybaraというgemの機能を使っていくのですが、このメソッドの種類がかなりあります。
下記のサイトでほとんど網羅されているので、操作に対応するメソッドを忘れた時には、ここを調べています。
qiita.com
Basic認証の突破
Basic認証とは、あらかじめ設定したユーザ名とパスワードを要求するだけの簡単な認証機能です。
本番環境では使わないので、コメントアウトしておけば良いと思います。
が、どうしてもテストを突破したい場合は、下記のようにするとできます。
user_name = 'user_name' password = 'password' visit "http://#{user_name}:#{password}@#{Capybara.current_session.server.host}:#{Capybara.current_session.server.port}#{path}"
「user_name」と「password」には、自身で設定した変数や文字を入れてください。
毎回最初に必要になるので、サポートモジュールを使用して、メソッドにしておくと便利です。
deviseのログイン
deviseを使っていると、毎回ログイン処理が必要になります。
メソッドを自身で作っても良いのですが、公式ですでに準備されています。
How To: Test with Capybara · heartcombo/devise Wiki · GitHub
使い方を簡単にまとめると
spec/rails_helper.rb
にこう書きます。(RSpec.configure do~endは33行目くらいに準備されているので、do~endの中に記載します。)
RSpec.configure do |config| config.include Warden::Test::Helpers config.after :each do Warden.test_reset! end end
これで、ログイン処理のメソッドlogin_asが使えるようになります。
また、各テストの最後にログイン状態のリセットを実施してくれます。
あとは、テストコードの最初で、login_asを使ってログインするだけです。
user = User.create!(email: 'test@example.com', password: 'f4k3p455w0rd') login_as(user, scope: :user)
FactoryBotなどのあらかじめユーザ情報を作成しておくgemを使っていれば、もう少し簡単になります。
user = FactoryBot.create(:user) login_as(user, scope: :user)
注意点は、あくまでプログラム上でログイン処理をするだけのため、ログイン状態でページの表示が変わるような場合、login_asだけでは表示が変わりません。
visit root_path
などで、一度画面のリロード・遷移をする必要があります。
login_as後に、visitすればokです。
データベースに保存した画像が表示されていることの確認
データベースに保存されている画像のurlをみてみると以下のように???の感じになっています。
img class="item-image" src="http://localhost:3000/rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBDZz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--531d820f23be7783715afe29f9c98a9d5f33caaa/output-image1.png"
have_selectorマッチャを使用することで、img要素の存在を確認することはできるのですが、どうせなら「output-image1.png」というファイル名の一致まで確認したいです。
以下のようにするとできます。
expect(page).to have_selector('img[src*="output-image1.png"]')
これは、「output-image1.png」と部分一致するsrc属性を持つimg要素が存在するかを確認しています。
=を*=にすることで、完全一致ではなく、部分一致となっています。
他にも、
^=とすることで前方一致、
$=とすることで後方一致の検索ができます。
最後までお付き合いいただき、ありがとうございました!