1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【FactoryBot】RSpecでテストデータ作成が楽になる

1
Posted at

はじめに

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.comuser2@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を使うと、テストデータの準備がシンプルになり、テスト本来の「何を確認したいか」に集中できます。是非お試しください。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?