Model Spec

概要

taskモデルのバリデーションに関するテストを作成する。
FactoryBotを使用しテストデータを作成する。

バリデーションエラーの発生と、エラーメッセージの内容を表示させる。
各バリデーションを削除した際、テストが失敗することを確認する。

FactoryBotの設定

FactoryBot.の省略
以下の設定を追加すると、factory_botメソッドの前にFactoryBot.を付ける必要がなくなる。
FactoryBot.create(:user)create(:user)と省略して書ける。

RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods
end

UserとTaskモデルのテストデータを作成

  FactoryBot.define do
  factory :task do
    sequence(:title, "title_1")
    content { 'Content' }
    status { 'todo' }
    deadline { Date.current.tomorrow }
    association :user
  end
end
  FactoryBot.define do
    factory :user do
      sequence(:email) { |n| "tester#{n}@example.com" }
      password { 'password' }
      password_confirmation { 'password' }
    end
  end

今回のUserとTaskのアソシエーションは1対多(belongs_to と has_many)である。
ユニーク制約のついているカラムではsequenceメソッドを使用する。
association :userでuserとの関連を定義。

sequenceメソッド

sequenceの第二引数で定義した文字にはループの度に.nextが実行される。

> "title_1".next
 => "title_2"

sequence(:title){|n| "title_#{n}"}sequence(:title, "title_1")のように書ける。

TaskのModel Spec

taskモデルのvalidationに関するテストを記述していく。

  • 全部の属性を登録したとき有効
  • titleがないときに無効
  • titleが重複したとき無効
require 'rails_helper'

RSpec.describe Task, type: :model do
  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 a 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 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
  end
end

describe' 'do...endでテスト内容の宣言。
今回はvalidationに関するテストを宣言している。

it " " do...endには、実行するテスト内容を記述する。

be_○○○マッチャ

Rspecでは、empty? のようにメソッド名が?で終わり、戻り値が true / false になるメソッドを be_empty のような形式で検証できる。
expect(task).to be_validで記述するのがexpect(期待する)で、ここでは
taskがto be_validすることを期待するというテストとなる。
be_validはマッチャと呼ばれる機能でexpectの引数にしたインスタンスにバリデーションエラーが発生しないことを検証する。(task.valid? が true になればパスする)

expect(task.errors).to be_emptyでtask.errorsがemptyであることを期待する。

省略

task = FactoryBot.build(:task, title: "", user: user)task = build(:task)と書ける。
FactoryBot.buildでTaskのFactoryにuserオブジェクトを指定。
設定ファイルへ追記しているので、FactoryBot.の部分は省略できる。
taskのFactoryにassociationを定義しているのでuserの記述を省略できる。

buildとcreateの違い

buildはテストデータをメモリ上に保存するが、createはデータベース上に保存する。
データベースへのアクセスが必要なテストの場合はcreateを使用し、必要でない場合はbuildを使えば良い
以下、idや作成日時を見るとbuildではnilとなっていて、createではデータベース上に保存されているので値が表示されている。
f:id:meo2:20210731174744p:plain