学習記録

アウトプット用に作りました

Model Spec

モデルスペックに含めるテスト

  • 有効な属性で初期化された場合は、モデルの状態が有効になっていること。正常系のテスト。

  • バリデーションを失敗させるデータであれば、モデルの状態が無効になっていること。異常系のテスト。

  • クラスメソッドとインスタンスメソッド、スコープが期待通りに動作すること。


モデルスペックを作成する

※ 前提条件としてRSpecとFactoryBotをインストールしていること。

$ rails generate rspec:model user

上記のコマンドで生成されるファイル
① spec/models/user_spec.rb
② spec/factories/users.rb
FactoryBotのgemが入っていると自動的に②のファイルが作られます。

spec/models/user_spec.rbのファイルの中身を確認します。

require 'rails_helper'

RSpec.describe User, type: :model do
  pending "add some examples to (or delete) #{__FILE__}"
end

require 'rails_helper'はテストスイート内のほぼ全てのファイルで必要です。この記述によってRSpecに対して、ファイル内のテストを実行するためにRailsアプリケーションの読み込みが必要であると伝えています。

FactoryBotを使ってテストデータを作成します。FactoryBotに関してはこちらを参照してください。

factories/users.rb

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


準備は完了したので、Userモデルのバリデーションに関するテストを作成します。

まずテストケースを作成していきます。
テストケースは英語でも日本語でもわかりやすく書いていればどちらでも大丈夫です。

require 'rails_helper'

RSpec.describe User, type: :model do
  describe 'validation' do
    it "メール、パスワードがあれば有効な状態であること" 
    it "メールアドレスがなければ無効な状態であること"
    it "重複したメールアドレスなら無効な状態であること"
    it '異なるメールアドレスなら有効な状態であること'
  end
end

describeはテストのグループ化宣言です。
モデルスペックではモデルのクラス名やメソッド名などを記入します。
itはテストをexampleという単位にまとめる役割です。
describeの中には複数のexample(it)を書くことができます。


それではテストケースを実装していきます。

require 'rails_helper'

RSpec.describe User, type: :model do
  describe 'validation' do
    it "メール、パスワードがあれば有効な状態であること"  do
      user = build(:user)
      expect(user).to be_valid
      expect(user.errors).to be_empty
    end
    it "メールアドレスがなければ無効な状態であること" do
      user_without_email = build(:user, email: '')
      expect(user_without_email).to be_invalid
      expect(user_without_email.errors[:email]).to eq ["can't be blank"]
    end
    it "重複したメールアドレスなら無効な状態であること" do
      user = create(:user)
      user_with_duplicated_email = build(:user, email: user.email)
      expect(user_with_duplicated_email).to be_invalid
      expect(user_with_duplicated_email.errors[:email]).to eq ["has already been taken"]
    end
    it '異なるメールアドレスなら有効な状態であること' do
      user = create(:user)
      user_with_another_email = build(:user, email: 'another_email')
      expect(user_with_another_email).to be_valid
      expect(user_with_another_email.errors).to be_empty
    end
  end
end

上記のコードで出てきたbe_valideqなどはマッチャというものです。

expect(user).to be_valid

このコードのtoは「~であること」 を期待しているという意味です。
be_validuser.valid?trueであるということを意味しています。

expect(user_without_email.errors[:email]).to eq ["can't be blank"]

このコードのeqは「等しい」かどうかを検証しますという意味です。

参考 : 使えるRSpec入門・その2「使用頻度の高いマッチャを使いこなす」 - Qiita