Ruby
Rails
RSpec
FactoryGirl
FactoryBot

RailsアプリへのRspecとFactory_botの導入手順

はじめに

導入に手こずったので、RspecとFactory_botを導入する手順を記事に残そうと思います。基本的にはFactory_girlと同じ(だと思う....)

追記履歴

2018/02/02 supportディレクトリのパス修正
2018/04/17 bin/rspecの記載を追加

動作環境

  • macOS High Sierra

  • ruby, railsのバージョン

$ ruby -v
ruby 2.4.2p198 (2017-09-14 revision 59899) [x86_64-darwin17]

$ rails -v
Rails 5.1.4

導入手順

1. Gemのインストール

以下のようにGemfileにRails用のrspecとfactory_botのgemを加えて、インストールを行います。

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

2. rspecの導入

まず、以下のコマンドでRailsアプリに、rspecを導入します。

$ bundle exec rails generate rspec:install
      create  .rspec
      create  spec
      create  spec/spec_helper.rb
      create  spec/rails_helper.rb

3. rspecの生成ファイルの定義

次にrails generate model等のコマンドで生成されるrspecファイルを設定していきます。設定ファイルはconfig/application.rbです。

以下が、設定です。falseをつけると不要なテストファイルは作成されなくなります。

/config/application.rb
config.generators do |g|
  g.test_framework :rspec, 
        view_specs: false, 
        helper_specs: false, 
        controller_specs: false, 
        routing_specs: false
end

4. Factory_botの設定

spec/rails.helper
RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods

end

上述のコードを加えることで、以下のようにrspecのテストコード中でFactory_botのメソッドを使用する際に、名前空間の指定を省略できるようになります。

 # 通常FactoryBotをつけないと、メソッドを呼べない
 user = FactoryBot.create(:user)

 # 上の設定を追加することで、FactoryBotの記述が省略できる。
 user = create(:user)

5. rails_helper.rbの設定

次に、/spec/rails_helper.rb内で以下の一文がコメントアウトされているので、コメントアウトを外してください。これでspec/support/配下のファイルを読み込むことができます。

/spec/rails_helper.rb
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }

この設定は必須ではないですが、やっておいた方がいいと思います。理由としては、テスト用のヘルパーメソッドを使う際に記述するファイル置き場なので、よく使用するからです。

ここまでで、rspec, factory_botの設定は終了です。

使って見る

1.テストデータの定義

例えばUserモデルに関しては、テストデータの定義は/spec/factories/users.rbに行います。以下は定義例です。データを生成する毎に通し番号をふってユニークな値を作るようにしています。

/spec/factories/users.rb
FactoryBot.define do
  factory :user do
    sequence(:name) { |n| "TEST_NAME#{n}"}
    sequence(:email) { |n| "TEST#{n}@example.com"}
  end
end

2. Specテスト内でのテストデータの生成

使い方としては、以下のようにcreateか、buildでモデルを作成して、テストデータとして使うのが基本だと思います。

# DBへレコード生成
@user = create(:user)

# モデルのみの作成
@user = build(:user)

以下に、Userモデルのバリデーションをチェックするテストを書きました。参考になればどうぞ。

/app/models/users.rb
class User < ApplicationRecord
  validates :name, presence: true
  validates :email, presence: true
end
/spec/models/users_spec.rb
require 'rails_helper'

RSpec.describe User, type: :model do
  before do 
    @user = build(:user)
  end

  describe 'バリデーション' do
    it 'nameとemailどちらも値が設定されていれば、OK' do
      expect(@user.valid?).to eq(true)
    end

    it 'nameが空だとNG' do
      @user.name = ''
      expect(@user.valid?).to eq(false)
    end

    it 'emailが空だとNG' do
      @user.email = ''
      expect(@user.valid?).to eq(false)
    end
  end
end

3. Rspecテストの実行

作成したテストは以下のコマンドで実行できます。

$ bundle exec rspec spec/models/users_spec.rb

また、行数を指定することで、itdescribe単位でテストを実行でき、逆にディレクトリを指定することで配下も含めた対象ファイル全てを一度に実行できます。

# users_spec.rbの12行目にあるテストを実行
$ bundle exec rspec spec/models/users_spec.rb:12

# 全てのテストファイルを実行
$ bundle exec rspec spec

4. binstubでテスト実行

binstubの概要

rspecのテストの実行方法には上述の他に、binstubから使う方法もあります。
binstubからrspecを実行するとSpringの恩恵を得ることができ、実行開始時間を早めることができ便利です。

Spring

binstubの導入

ます、必要なGemをインストールします。Gemfileに以下のgemファイルを記述し、bundle installでインストールします。

group :development, :test do

  gem 'spring-commands-rspec'

end

次に、以下のbundleコマンドを実行し、rspecのbinstubをインストールします。

$ bundle exec spring binstub rspec

これで準備完了です。

実行コマンド

$ bin/rspec spec/

5. 「bundel exec rspec」 と 「bin/rspec」の使い分け

立ち上がりの速いbin/rspec

1つのテストファイルを実行する場合は、断然bin/rspecの方が実行が速いです。
新規機能に対して、新しくテストファイルを作成している際は、何度もテスト実行を繰り返すので、立ち上がりが速いbin/rspecを多用しますね。

立ち上がり後の実行スピードの速いbundle exec rspec

一方で、新規機能追加等で、既存の全てのテストが落ちていないか確認する際は、bundle exec rspecの方が起動後の実行スピードが速いので効率的です。テスト項目が100を超える場合は、その効果をより実感できると思います。

参考文献

↓これを読めば、基礎から実践的なものまで、体系的に学ぶことができます
Everyday Rails - RSpecによるRailsテスト入門
テスト駆動開発の習得に向けた実践的アプローチ

参考ページ

factory_girlがfactory_botに名前変更!使用方法の解説など

Rails RSpecの基本 ~導入編~

Spring