RSpec、Capybara、FactoryBotを使用したテスト環境の構築・設定方法、及びテストの書き方一例

テスト環境の構築構築方法

1. RSpec、Capybara、FactpryBot、Webdriversのgemをインストール

# Gemfile

group :development, :test do
  gem 'rspec-rails'
  gem 'factory_bot_rails'
  gem 'capybara'
  gem 'webdrivers'
end

=> bundle installコマンドを実行

2. RSpecに必要なディレクトリや設定ファイルを作成する

% bin/rails g rspec:install
=> Running via Spring preloader in process 10358
     create  .rspec
     create  spec
     create  spec/spec_helper.rb
     create  spec/rails_helper.rb

3. 自動で作成されてあるtestディレクトリを削除する

% rm -r ./test

FactoryBotを使用したテストデータの作成方法

# spec/factories/tasks.rb

FactoryBot.define do
  factory :task do

    # 重複したデータの作成を阻止したい場合、シーケンスを使用する。
    sequence(:title) { |n| "title_#{n}" }
    # シーケンスの第二引数で定義した文字の末尾にはnextメソッドが実行されるので、文字列の末尾を変更することで独立したデータを作成する上のようなコードの場合、以下のようにも書ける。
    => sequence(:title, "title_1")
    content { "content" }
    status { :todo }
    deadline { 1.week.from_now }

    # Userモデルのファクトリとアソシエーションを作成する場合、以下のコードを記載
    association :user

  # traitを使用することで元となるデータを継承・オーバーライドして、属性地をグループ化することができる。
    trait :finished_task do
      status { :done }
      completion_date { Time.current.yesterday }
    end
  end
end

以下、SystemSpecの書き方一例

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

RSpec.describe 'User', type: :system do
  # letは遅延読み込みを実現するメソッドで、変数に値を代入するように使用できる。
  # 以下のコードでは、テストファイル内でuserを呼び出すことでFactoryBot内で作成したuserデータを作成し、データベースに保存できる。
  let(:user) { FactoryBot.create(:user) }

  describe 'ログイン後' do
    before do
      visit root_path
      click_link "ログイン"
      fill_in "メールアドレス", with: user.email
      fill_in "パスワード", with: "password"
      click_button "ログイン"
    end

    describe 'ユーザー編集' do
      before do
        visit users_path
        click_link "ユーザー編集"
      end

      context 'フォームの入力値が正常' do
        before do
          fill_in "メールアドレス", with: user.email
          fill_in "パスワード", with: "update_password"
          fill_in "再確認", with: "update_password"
          click_button "ユーザー更新"
        end

        it 'ユーザーの編集が成功する' do
          expect(current_path).to eq user_path(user)
          expect(page).to have_content user.email
          expect(page).to have_content "User was successfully updated."
        end
      end
    end
  end
end

テスト環境の各種設定

・ヘッドレスドライバを使用して、ブラウザのウィンドウを開くことなくテストを実行する

# spec/spec_helper.rb

require 'capybara/rspec'

RSpec.configure do |config|
  config.before(:each, type: :system) do
    driven_by(:selenium_chrome_headless)
  end
end

RSpec の出力をデフォルトの形式からドキュメント形式に変更する

# .rspec
# 以下のコードを追加

--format documentation

・テストで使用する共通の処理(login処理など)を記述したサポートモジュールのファイルをspec/support配下に作成し、その配下のファイルを読み込む

# spec/support/login_support.rb

module LoginSupport
  def sign_in_as(user)
    visit root_path
    click_link "Sign in"
    fill_in "Email", with: user.email
    fill_in "Password", with: user.password
    click_button "Log in"
  end
end
# spec/rails_helper.rb

# 20行目付近にある以下のコードのコメントアウトをはずすことで、spec/support配下のファイルを読み込む

# Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
=> Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f } 

# 以下のコードを追加してLoginSupportモジュールをテストで使用できるようにする
RSpec.configure do |config|
  config.include LoginSupport
end

・実行するテストケースを限定する設定

# spec/spec_helper.rb

# 50行付近にある以下のコードのコメントアウトをはずす
RSpec.configure do |config|
  # config.filter_run_when_matching :focus
  => config.filter_run_when_matching :focus
end

FactoryBot.create(:user)FactoryBot.build(:user)をする時、以下の記載をすることでFactoryBot.の部分を省略できる

RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods
end