社内用コンテンツ

【Railsテスト】factory_botを使ってテストコードを効率化する方法を分かりやすく解説!

Rails

 

今回は、テストを効率化できるGem「factory_bot」について解説したいと思います。

RSpecだけではダラダラと長いコードになってしまうため、「factory_bot」を使ってスッキリしたテストコードが書けるようにしていきましょう。

factory_botとは

factory_bot

「factory_bot」とは、簡単にダミーのインスタンスを作成することができるGemです。

もう少し深掘りするため、前回の記事を用いて解説していきます。

↓前回の記事はこちら

Rails
【Rails】プログラミングにおけるテストとは?RSpecを用いながら解説!プログラミングにおけるテストについて、RSpecと呼ばれるテスト独自の言語を用いながら解説しています。作成したwebサービスが正しく動くかどうかを試験することで、事前にエラーになり得る箇所を発見できたり、要件漏れを防ぐことができます。ぜひマスターしましょう。...

 

前回では「nickname」と「email」のバリデーションをテストするコードを書きましたが、それぞれUserクラスのインスタンスを作成し値をセットしていました。

↓ そのテストコード

require 'rails_helper'

describe User do
  describe '#create' do
    it "is invalid without a nickname" do
      user = User.new(nickname: "", email: "aaa@gmail.com", password: "00000000", password_confirmation: "00000000")
      user.valid?
      expect(user.errors[:nickname]).to include("can't be blank")
    end
  end
end


describe User do
  describe '#create' do
    it "is invalid without an email" do
     user = User.new(nickname: "test", email: "", password: "00000000", password_confirmation: "00000000")
     user.valid?
     expect(user.errors[:email]).to include("can't be blank")
    end
  end
end

 

しかし「factory_bot」を使うと、いちいちクラスのインスタンスを生成しなくても値をセットすることができます。

「user = User.new(~~~~)」の部分が省略できると言うことだね。

factory_botの導入

まずは「factory_bot」の導入を行なっていきましょう。RSpecの時と同じように、Gemfileを編集します。

↓ Gemfile

group :development, :test do
  # 省略
  gem 'rspec-rails'
  gem 'factory_bot_rails'
end

 

「bundle install」を実行しましょう。

↓ ターミナル

$ bundle install

 

続いて下図のように、specディレクトリ直下に「factoriesディレクトリ」を作成します。

factoriesディレクトリ

 

そして作成したfactoriesディレクトリ直下に、「users.rb」を作成しましょう。

users.rb

 

次に「users.rb」を編集していきます。以下のように「users.rb」に記述しましょう。

↓ factories/users.rb

FactoryBot.define do

  factory :user do
    nickname              {"test"}
    email                 {"test@gmail.com"}
    password              {"12345678"}
    password_confirmation {"12345678"}
  end

end

 

このように、あらかじめUserクラスのインスタンスを定義しておくと、specファイルの中で特定のメソッドにより簡単にインスタンスを生成したり、DBに保存できたりするようになります。

 

以上で「factory_bot」を使用する準備が整いました。では実際に「factory_bot」を使ってテストしていきましょう。

factory_botを使ったテスト

↓ RSpecのみを用いた記述

require 'rails_helper'

describe User do
  describe '#create' do
    it "is invalid without a nickname" do
      user = User.new(nickname: "", email: "aaa@gmail.com", password: "00000000", password_confirmation: "00000000")
      user.valid?
      expect(user.errors[:nickname]).to include("can't be blank")
    end
  end
end


describe User do
  describe '#create' do
    it "is invalid without an email" do
     user = User.new(nickname: "test", email: "", password: "00000000", password_confirmation: "00000000")
     user.valid?
     expect(user.errors[:email]).to include("can't be blank")
    end
  end
end

 

上記のRSpecのみを用いて記述したコードを、「factory_bot」を利用して書くと以下のようになります。

↓ factory_botを用いた記述

describe User do
  describe '#create' do

    it "is invalid without a nickname" do
      user = FactoryBot.build(:user, nickname: "")
      user.valid?
      expect(user.errors[:nickname]).to include("can't be blank")
    end

    it "is invalid without an email" do
      user = FactoryBot.build(:user, email: "")
      user.valid?
      expect(user.errors[:email]).to include("can't be blank")
    end

  end
end

buildメソッドは、引数にシンボル型で取ったクラス名のインスタンスを、factory_botの記述をもとに作成します。

例えば、以下の2つのコードは同じ意味になります。

user = User.new(nickname: "test", email: "test@gmail.com", password: "12345678", password_confirmation: "12345678")
user = FactoryBot.build(:user)

 

また、第2引数以降に「カラム名: 値」という形式でハッシュを渡すことで、値の上書きをすることができます。

user = build(:user, nickname: "")

 

このように記述することで、ニックネームは空であると上書きしています。

だいぶスッキリしたコードになりましたね!

よりコードをスッキリさせるには

ここまででも、だいぶ綺麗なコードにはなりましたが、もっとコードをスッキリさせることができます。それは以下の部分です。

user = FactoryBot.build(:user, nickname: "")
user = FactoryBot.build(:user, email: "")

 

この「FactoryBot」という表現を省略することができます。そのためには、「spec/rails_helper.rb」を以下のように編集する必要があります。

↓ spec/rails_helper.rb

# 省略

RSpec.configure do |config|

  # 下記を追記
  config.include FactoryBot::Syntax::Methods

  #省略

end

 

こうすることにより、「FactoryBot」という文言を省略して以下のように書くことができます。

user = build(:user, nickname: "")
user = build(:user, email: "")

 

最後にもう一度、「factory_bot」を用いたテストコードを記載しておきます。

describe User do
  describe '#create' do

    it "is invalid without a nickname" do
      user = build(:user, nickname: "")
      user.valid?
      expect(user.errors[:nickname]).to include("can't be blank")
    end

    it "is invalid without an email" do
      user = build(:user, email: "")
      user.valid?
      expect(user.errors[:email]).to include("can't be blank")
    end

  end
end

 

まとめ

  • factory_botとは、簡単にダミーのインスタンスを作成することができるGem
  • わざわざクラスのインスタンスを生成しなくても値をセットすることができる
  • 「FactoryBot」という表現は省略可能

 

 

今回はテストを効率化できるGem「factory_bot」について解説しました。RSpecと併せて、より効率的なテストコードが書けるように見直してみましょう。