今回はRSpec初学者の方がRailsアプリケーションのテストの際にRSpecを使用してモデルの単体テスト行う事を想定して記事を書きあげました。
モデルはアプリケーションのコアとなる部分になるため、モデルのテストは大変重要な工程になります。
しかしテストを学習し始めたばかりの頃は、テストって何を書いたら良いのか分からないという事もあるかと思います。
そんな時は次のような事を中心にテストを作成してみると良いかもしれません。
-
有効な属性で初期化された場合は、モデルの状態が有効(valid)になっていること
-
バリデーションを失敗させるデータであれば、モデルの状態が有効になっていないこと
-
クラスメソッドとインスタンスメソッドが期待通りに動作すること
今回はこの3点のポイントに沿って実際にテストコードを書いていきたいと思います。
まずはユーザー登録機能をもったUserモデルの単純なテストコードです。
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
validates :nickname presence: true
has_many :tweets
・・・省略
end
※deviseのvalidatableモジュールによりメールアドレスとパスワードに関して必要な全ての検証を作成されます。
検証内容としては、メールアドレスが存在すること、ユニークであること、形式が有効であること。パスワードに関しても存在すること、長さなどが検証対象です。
require 'rails_helper'
RSpec.describe User, type: :model do
# beforeメソッドでユーザーのインスタンスを予め用意
before do
@user = User.new(
nickname: "Taro",
email: "rspectest@.com",
password: "rspec1111",
password_confirmation: password
)
end
describe User do
# ニックネーム、メールアドレス、パスワードがあれば登録できること
it "is valid with a nickname, email, and password" do
expect(@user).to be_valid
end
# ニックネームがなければ無効な状態であること
it "is invalid without a nickname" do
@user.nickname = ""
@user.valid?
expect(@user.errors[:nickname]).include("can't be blank")
end
# メールアドレスがなければ無効な状態であること
it "is invalid without an email address" do
@user.email = ""
@user.valid?
expect(@user.errors[:email]).include("can't be blank")
end
# パスワードがなければ無効な状態であること do
it "is invalid without an password" do
@user.password = ""
@user.valid?
expect(@user.errors[:password]).include("can't be blank")
end
# 重複したメールアドレスで登録すると無効な状態であること
it "is invalid with a duplicate email address" do
@user.save
another_user = User.new(
nickname: "Jiro",
email: "rspectest@.com",
password: "rspec2222",
password_confirmation: password
)
another_user.valid?
expect(another_user.errors[:email]).include("has already been taken")
end
end
end
上記のテストで以下の部分のことが正しいかどうかをテストしました。
-
有効な属性で初期化された場合は、モデルの状態が有効(valid)になっていること(ニックネーム、メールアドレス、パスワードがあれば登録できること)
-
バリデーションを失敗させるデータであれば、モデルの状態が有効になっていないこと (その他のテスト部分)
最後に投稿用のTweetモデルとしてクラスメソッドのテストを書いてみます。
belongs_to :user
# 投稿検索用のメソッド
def self.search_by_tweet(search)
return Tweet.where("content LIKE ?", "%#{search}%")
end
・・・省略
require 'rails_helper'
RSpec.describe Tweet, type: :model do
# 検索文字列に一致する投稿を返すこと
it "returns tweets that match the search term" do
user = User.create(
nickname: "Taro",
email: "rspectest@.com",
password: "rspec1111",
password_confirmation: password
)
tweet = user.tweets.create( content: "success", user: user)
expect(Tweet.search_by_tweet("success")).to include(tweet)
expect(Note.search_by_tweet("hoge")).to_not include(tweet)
end
end
こちらでモデルで定義したクラスメソッドが機能しているかどうかをテストしました。
他にもたくさんテストすべき箇所はたくさんありますが、今回はモデル単体テストの全体イメージを掴むことを目的とした為、大部分を省略させて頂いて頂きました。
最後まで当記事を読んで頂きありがとうございました。