新型コロナウィルスの影響で会社から自宅待機を命じられました。
いい機会と思い、ModelSpec について学習したことをまとめました。
この記事で分かること
- バリデーションテストの考え方
- ModelSpec の基本的な記述の仕方
この記事でやらないこと
- gem の導入手順
- ModelSpec の説明
- 必要なファイルの準備
- let を使用した変数定義
- FactoryBot や Faker を使用した記述
目次
- 開発環境
- テストする Model のバリデーション
- RSpec の雛形を確認
- context ブロックにテストする項目を書き出す
- it ブロックに期待する結果を書く
- it ブロックが叶うように、 context ブロックで御膳立てをする
1. 開発環境
Rails 6.0.3.4
ruby 2.7.1
rspec-rails 4.0.1
2. テストする Model のバリデーション
validates :name, :account_name, :email, : presence: true
今回はこのようなバリデーションをテストしていきます。
「name, account_name, email カラムは必須の項目です」といった内容ですね。
3. RSpec の雛形を確認
こちらが RSpec の基本的な形になります。
target
にはテストしたい内容が入り、〇〇〇にはその結果が入ります。
イメージ的には以下のような感じですね。
expect( 1 + 1 ).to eq 2
また、.to
の直後の eq
はマッチャと呼ばれるもので様々な種類があるのですが、今回は説明を割愛します。詳しくは こちら の記事をご覧ください。
今回は以下の2種類のマッチャを使用します。
be_valid
... 「バリデーション が適切です」を意味するマッチャ。
be_invalid
... 「バリデーション が不適切です」を意味するマッチャ。
それでは実際に ModelSpec を書いていきましょう。
4. context ブロックにテストの条件を記述する。
「テストの条件」と聞くと難しく聞こえますが、「正常な場合と異常な場合をそれぞれテストする」と考えても OK です。
これらはそれぞれ「正常系テスト」「異常系テスト」と呼ばれます。
今回の場合だと、正常系テストは
name カラム、account_name カラム、email カラムが全て指定されている場合
になります。
反対に、異常系テストは
name カラムが指定されていない場合
account_name カラムが指定されていない場合
email カラムが指定されていない場合
になりますね。実際にコードを書いてみましょう。
require "rails_helper"
RSpec.describe User, type: :model do
describe "#validation" do
# 正常系
context "name, account_name, email が全て指定されている場合" do
it "" do
end
end
# 異常系
context "name が指定されていない場合" do
it "" do
end
end
#異常系
context "account_name が指定されていない場合" do
it "" do
end
end
# 異常系
context "email が指定されていない場合" do
it "" do
end
end
end
end
5. it ブロックに期待する結果を書く
it ブロックは期待する結果を書く場所でしたね。正常系テストは上手く通ればユーザーが作られる想定なので、そのまま書きましょう。
反対に異常系テストが上手く通るということは、エラー起こるということなので、こちらも同じように書きます。
require "rails_helper"
RSpec.describe User, type: :model do
describe "#validation" do
# 正常系
context "name, email, password, account_name が全て指定されている場合" do
it "ユーザーが作られる" do
end
end
# 異常系
context "name が指定されていない場合" do
it "エラーする" do
end
end
#異常系
context "account_name が指定されていない場合" do
it "エラーする" do
end
end
# 異常系
context "email が指定されていない場合" do
it "エラーする" do
end
end
end
end
さらに、 it ブロックの中身も書いていきましょう。正常系の場合は、以下になります。
expect( user ).to be_valid
変数 user
に User インスタンスを格納することを想定した記述になっています。この1行で、
user のバリデーションは適切である
といった意味になります。
異常系テストの場合は以下のようになりますね。
expect( user ).to be_invalid
それぞれ it ブロック内に記載していきましょう。
require "rails_helper"
RSpec.describe User, type: :model do
describe "#validation" do
# 正常系
context "name, email, password, account_name が全て指定されている場合" do
it "ユーザーが作られる" do
expect( user ).to be_valid
end
end
# 異常系
context "name が指定されていない場合" do
it "エラーする" do
expect( user ).to be_invalid
end
end
#異常系
context "account_name が指定されていない場合" do
it "エラーする" do
expect( user ).to be_invalid
end
end
# 異常系
context "email が指定されていない場合" do
it "エラーする" do
expect( user ).to be_invalid
end
end
end
end
6. it ブロックが叶うように、 context ブロックで御膳立てをする
ここまできたら、あとは it ブロック内が実現されるように context ブロック内を埋めていきましょう。まずは正常系テストから。正常系テストの条件は、
name カラム、account_name カラム、email カラムが全て指定されている場合
だったので、普通にインスタンスを作成すれば良さそうですね。
user = User.new(name: "user", account_name: "user_account_name", email: "user@example.com")
次に異常系テストです。一つだけ具体例をみてみましょう。
name カラムが指定されていない場合
これは name カラムを nil にしてあげれば良さそうです。
user = User.new(name: nil, account_name: "user_account_name", email: "user@example.com")
同じ要領で他の異常系テストも記述していきましょう。完成したものが以下になります。
require "rails_helper"
RSpec.describe User, type: :model do
describe "#validation" do
# 正常系
context "name, email, password, account_name が全て指定されている場合" do
user = User.new(name: "user", account_name: "user_account_name", email: "user@example.com")
it "ユーザーが作られる" do
expect( user ).to be_valid
end
end
# 異常系
context "name が指定されていない場合" do
user = User.new(name: nil, account_name: "user_account_name", email: "user@example.com")
it "エラーする" do
expect( user ).to be_invalid
end
end
#異常系
context "account_name が指定されていない場合" do
user = User.new(name: "user", account_name: nil, email: "user@example.com")
it "エラーする" do
expect( user ).to be_invalid
end
end
# 異常系
context "email が指定されていない場合" do
user = User.new(name: "user", account_name: "user_account_name", email: nil)
it "エラーする" do
expect( user ).to be_invalid
end
end
end
end
最後に
はい、ここまでお疲れ様でした。
今回の内容はあくまでも初歩的な内容だったかと思います。
今後は FactoryBot や Faker を組み合わせた内容をやっていく予定です。
最後まで読んでいただき、ありがとうございました!