Factory Botの導入、Blogモデルスペック

Blogモデルのテストを実装していきます。

$ rails g rspec:model blog

Factory Botの導入

サンプルデータを生成するために今回はFactory Botを使用します。

(Gemlfile)

group :development, :test do
# (省略)
  gem 'factory_bot_rails'
end
$ bundle

congis.generatorsfixtures: falseを外す。

(config/initializers/generators.rb)

Rails.application.config.generators do |g|
  g.assets false
  g.helper false
  g.test_framework :rspec,
  # fixtures: false, (削除)
  view_specs: false,
  helper_specs: false,
  routing_specs: false,
  controller_specs: false,
  request_specs: false
end

spec ディレクトリ内に factories という新しいディレクトリを作ります。

$ rails g factory_bot:model user

(spec/factories/users.rb)

FactoryBot.define do
  factory :user do
    name { "tester" }
    email { "tester@example.com" }
    password { "password" }
  end
end

(spec/models/user_spec.rb)

it "有効なファクトリを持つこと" do
    expect(FactoryBot.build(:user)).to be_valid 
  end

(spec/models/user_spec.rb)

1) User 有効なファクトリを持つこと
     Failure/Error: expect(FactoryBot.build(:user)).to be_valid
     
     KeyError:
       Factory not registered: "user"
     # ./spec/models/user_spec.rb:47:in `block (2 levels) in <main>'
     # -e:1:in `<main>'
     # ------------------
     # --- Caused by: ---
     # KeyError:
     #   key not found: "user"
     #   ./spec/models/user_spec.rb:47:in `block (2 levels) in <main>'

(spec/models/user_spec.rb)

require 'rails_helper'

RSpec.describe User, type: :model do
  it "名前、メール、パスワードがあれば有効な状態であること" do
    user = User.new(
      name: "tester",
      email: "tester@example.com",
      password: "password",
    )
    expect(user).to be_valid 
  end

  it "名前がなければ無効な状態であること" do
    user = FactoryBot.build(:user, name: nil)
    user.valid?
    expect(user.errors[:name]).to include("を入力してください")
  end

  it "メールアドレスがなければ無効な状態であること" do
    user = FactoryBot.build(:user, email: nil)
    user.valid?
    expect(user.errors[:email]).to include("を入力してください")
  end

  it "重複したメールアドレスなら無効な状態であること" do
    FactoryBot.create(:user, email: "hogehoge@example.com")
    user = FactoryBot.build(:user, email: "hogehoge@example.com")
    user.valid?
    expect(user.errors[:email]).to include("はすでに存在します")
  end

  it "パスワードが6文字以上でなければ無効な状態であること" do
    user = FactoryBot.build(:user, password: "hoge")
    user.valid?
    expect(user.errors[:password]).to include("は6文字以上で入力してください")
  end

  it "有効なファクトリを持つこと" do
    expect(FactoryBot.build(:user)).to be_valid 
  end
end

(spec/foctories/user/blogs.rb)

FactoryBot.define do
  factory :user do
    name { "tester" }
    sequence(:email) { |n| "tester#{n}@example.com" }
    password { "password" }
  end
end

(spec/factories/user.rb)

it "複数のユーザーで何かする" do
    user1 = FactoryBot.create(:user) 
    user2 = FactoryBot.create(:user) 
    expect(true).to be_truthy
  end

blogファクトリを作成します。

$ rails g factory_bot:model blog

(spec/models/blog_spec.rb)

require 'rails_helper'

RSpec.describe Blog, type: :model do
  it "タイトル、内容があれば有効な状態であること" do
    expect(FactoryBot.build(:blog)).to be_valid
  end

  it "タイトルがなければ無効な状態であること" do
    blog = FactoryBot.build(:blog, title: nil)
    blog.valid?
    expect(blog.errors[:title]).to include("を入力してください")
  end

  it "内容がなければ無効な状態であること" do
    blog = FactoryBot.build(:blog, content: nil)
    blog.valid?
    expect(blog.errors[:content]).to include("を入力してください")
  end

  it "user_idがなければ無効な状態であること" do
    blog = FactoryBot.build(:blog, user_id: nil)
    blog.valid?
    expect(blog.errors[:user]).to include("を入力してください")
  end
end

ひとまず、モデルスペックは一通り書きました。 次回はblogのtitleとcontentにNN制約がついていなかったので、設定したいと思います。