大ちゃんの駆け出し技術ブログ

RUNTEQ受講生のかわいいといわれるアウトプットブログ

RSpecでページのステータスコードを取得する方法

はじめに

こんにちは!大ちゃんの駆け出し技術ブログです。

今回は超短いアウトプットです!!

いつも6000字は超えるようにしてるんですけど、今回は3000字ぐらいになります。

というのも紹介することがシンプルなんですよね。

タイトルにあるとおり、今回は「RSpecでページのステータスコードを取得する方法」を紹介します。

Capybaraではテストでステータスコードを取得できない

RSpecのテスト方法にはCapybaraを使ったテスト方法が主流かなと思っています。

テスト時に実際にブラウザを起動させて行うテストで、エラーがあったときにはエラー時のスクリーンショットを取ってくれる便利なやつです。

設定ファイルは以下のようになります。

# spec/support/capybara.rb
RSpec.configure do |config|
  config.before(:each, type: :system) do
    driven_by :selenium, using: :chrome, screen_size: [1920, 800]
  end
end

spec/supportディレクトリを生成し、spec_helper.rbとは違うファイルでテストの設定を行えるようにしています。

一見完璧に見えるCapybaraなのですが、意外と欠点があるんですよね。

それが「ページのステータスコードを取得できない」です。

例えば、権限がないページにユーザーがアクセスしたときに、403エラー(:forbidden)が発生します。そして、エラーが発生した時のステータスコードは403となるはずです。ですので、ステータスコードを検証したいのですが、それがCapybaraだとできないんです。

driven_by(:rack_test)

ステータスコードを取得するテストはどうすれば良いのかというと、実は簡単でCapybaraではなく、テストの設定をdriven_by(:rack_test)に変えるだけです。

この設定は実はシステムスペックファイルを作成するコマンド実行時にデフォルトで生成されたシステムスペックファイルに記述されています。

$ bin/rails g rspec:system sample
      create  spec/system/samples_spec.rb

作成されたシステムスペックファイル

# spec/system/samples_spec.rb
require 'rails_helper'

RSpec.describe "Samples", type: :system do
  before do
    driven_by(:rack_test) # ここ!
  end

  pending "add some scenarios (or delete) #{__FILE__}"
end

これでステータスコードを取得できるんですね。

実際にテストコードに書いてみます。

RSpec.describe "Pundit", type: :system do
  let(:writer) { create(:user, :writer) }
  before do
    driven_by(:rack_test) # ここに記載
  end

  describe 'Writer' do
    before { login_as(writer) }
    describe 'Not authorized pages' do
      context 'When writer accesses to admin_categories_path' do
        before { visit admin_categories_path }
        fit 'Current_page is 403 error page' do
          expect(page).to have_content('You are not authorized to perform this action.'), '403エラーページが表示されていません'
          expect(page.status_code).to eq(403), 'ステータスコードが403ではありません'
        end
      end
    end
  end
end

今回はadmin_categories_pathに権限を持たないwriterがアクセスするとステータスコードが403になるかを検証します。driven_by(:rack_test)を使うとステータスコードを取得するpage.status_codeが使用できるようになります。実際に使ってみると403が返ってきます。

[1] pry(#<RSpec:・・・省略)> page.status_code
=> 403

しかし、driven_by(:rack_test)を記述すると、Capybaraのテスト設定がオーバーライドされてしまい、スクリーンショットをとることができなくなるのでご注意を。

じゃあCapybaraでpage.status_codeを実行すればいいのでは?と思う方もいると思いますが、残念ながらCapybaraのテストでpage.status_codeを実行するとエラーが返ってきます。

[1] pry(#<RSpec:・・・省略)> page.status_code
Capybara::NotSupportedByDriverError: Capybara::Driver::Base#status_code

なのでステータスコードを取得することを検証するシステムスペックファイルにのみ、driven_by(:rack_test)を記載しましょう。

終わりに

これで連続投稿8日目となりました!

どこまで行けるかわかりませんが、少なくとも今月中は毎日アウトプットを繰り返してみようと思います。

以上、大ちゃんの駆け出し技術ブログでした!