はじめに
RSpecでテストを書いているとき、下記のようなコードがあります。
user = User.create(name: "田中太郎", email: "tanaka@example.com", age: 25)
テストが増えるたびにこれを毎回書くのは、めんどくさいです。そんなときに役立つのが FactoryBot です。
FactoryBotとは?
FactoryBotは、テスト用データの「ひな形」を定義しておけるツールです。
一度ひな形(ファクトリ)を作っておけば、テストのたびに create(:user) の1行だけでデータを用意できます。毎回カラムを全部書く必要がなくなるので、テストコードがスッキリします。
セットアップ
まず、Gemfileに追加します。
# Gemfile
group :development, :test do
gem 'factory_bot_rails'
end
追加したら bundle install を実行しましょう。
次に、spec/rails_helper.rb に以下を追加すると、テスト内で FactoryBot.create(:user) を create(:user) と省略して書けるようになります。
# spec/rails_helper.rb
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods
end
ファクトリを定義する
spec/factories/ ディレクトリにファクトリのファイルを作ります。
# spec/factories/users.rb
FactoryBot.define do
factory :user do
name { "田中太郎" }
email { "tanaka@example.com" }
age { 25 }
end
end
rails generate factory_bot:model user コマンドでも自動生成できます。
基本的な使い方
create と build の違い
FactoryBotには主に2つのデータ作成方法があります。
# DBに保存する
user = create(:user)
# DBに保存しない(バリデーションのテストなどに使う)
user = build(:user)
モデルのバリデーションを確認したいだけのときは build を使うと、DBへの書き込みが発生しないので、テストが少し速くなります。
属性を上書きする
ひな形の一部だけ変えたいときは、引数で上書きできます。
user = create(:user, name: "鈴木花子", email: "suzuki@example.com")
テスト内での使用例
RSpec.describe User, type: :model do
it "名前とメールアドレスがあれば有効であること" do
user = build(:user)
expect(user).to be_valid
end
it "名前がなければ無効であること" do
user = build(:user, name: nil)
expect(user).not_to be_valid
end
it "メールアドレスが重複していれば無効であること" do
create(:user, email: "tanaka@example.com")
user = build(:user, email: "tanaka@example.com")
expect(user).not_to be_valid
end
end
少し便利な使い方
Sequenceで連番を使う
メールアドレスのように、同じ値があると困る場合は sequence を使うと連番で自動生成できます。
FactoryBot.define do
factory :user do
name { "田中太郎" }
sequence(:email) { |n| "user#{n}@example.com" }
age { 25 }
end
end
これで create(:user) を複数回呼んでも、user1@example.com、user2@example.com と自動的にずれてくれます。
Traitで状態を使い分ける
「管理者ユーザー」「ゲストユーザー」のように、同じモデルでも状態が違うデータを使いたいときは trait が便利です。
FactoryBot.define do
factory :user do
name { "田中太郎" }
sequence(:email) { |n| "user#{n}@example.com" }
age { 25 }
role { "general" }
trait :admin do
role { "admin" }
end
end
end
# 通常ユーザー
user = create(:user)
# 管理者ユーザー
admin = create(:user, :admin)
まとめ
| メソッド | 説明 |
|---|---|
create(:user) |
DBに保存してデータを作る |
build(:user) |
DBに保存せずデータを作る |
create(:user, name: "〇〇") |
属性を上書きしてデータを作る |
sequence |
連番で一意な値を生成する |
trait |
同じファクトリで状態を使い分ける |
FactoryBotを使うと、テストデータの準備がシンプルになり、テスト本来の「何を確認したいか」に集中できます。是非お試しください。