モデルスペック

導入

モデルスペックの作成

rails g rspec:model taskでタスクモデルを作成

FactoryBotの設定

emailとtitleはユニーク制約がついている

spec/factories/users.rb
FactoryBot.define do
  factory :user do
    sequence(:email) { |n| "tester#{n}@example.com" }
    password { 'password' }
    password_confirmation { 'password' }
  end
end

sequenceとは、連番データを作成できるもの
ユニークな値にすることができる

spec/factories/tasks.rb
FactoryBot.define do
  factory :task do
    sequence(:title, "title_1")
    content { 'Content' }
    status { 'todo' } #enumで定数を設定している。
    deadline { Date.current.tomorrow }
    association :user
  end
end

sequence(:title, "title_1")の部分は、sequenceはブロックを渡さず第2引数を渡すと、.nextが呼ばれる。変えたい場所が末尾の場合のみ使える書き方 なのかなと思う

FactoryBotは、FactoryBot.create(略)のように記述するが、以下の設定をしておくと、FactoryBotを省略できる

spec/rails_helper.rb
RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods #追記
end

テストコード記述

spec/models/task_spec.rb
require 'rails_helper'

RSpec.describe Task, type: :model do
  pending "add some examples to (or delete) #{__FILE__}"
  describe 'validation' do
    it 'is valid with all attributes' do
      task = build(:task)
      expect(task).to be_valid
      expect(task.errors).to be_empty
    end

    it 'is invalid without title' do
      task_without_title = build(:task, title: "")
      expect(task_without_title).to be_invalid
      expect(task_without_title.errors[:title]).to eq ["can't be blank"]
    end

    it 'is invalid without status' do
      task_without_status = build(:task, status: nil)
      expect(task_without_status).to be_invalid
      expect(task_without_status.errors[:status]).to eq ["can't be blank"]
    end

    it 'is invalid with a duplicate title' do
      task = create(:task)
      task_with_duplicated_title = build(:task, title: task.title)
      expect(task_with_duplicated_title).to be_invalid
      expect(task_with_duplicated_title.errors[:title]).to eq ["has already been taken"]
    end

    it 'is valid with another title' do
      task = create(:task)
      task_with_another_title = build(:task, title: 'another_title')
      expect(task_with_another_title).to be_valid
      expect(task_with_another_title.errors).to be_empty
    end
  end
end

validとinvalid

valid

バリデーションが実行された結果 エラーが無い場合trueを返し,エラーが発生した場合falseを返す

invalid

validとは逆の結果を返す エラーが発生した場合true,エラーが無い場合falseを返す