rails

【Rails】Rspecでvalidationのテストコードを書く!-後半

やべっち(@yabecchi312)です!

前回のこちらの記事の続きです。

【Rails】Rspecでvalidationのテストをしよう!-準備編

前回の記事ではRspecを書くための準備として解説してきましたが、これからfactory_girlのインスタンスを生成するためのコードと実際のバリデーションを調べるためのテストコードを書きます!

factory_girlを使ってインスタンス生成するためのコードを書く

実際に書いたのはこんな感じです。

/user.rb/
FactoryGirl.define do

  factory :user do
    name                  "yabe"
    email                 "kkk@gmail.com"
    password              "00000000"
    password_confirmation "00000000"
  end

end

これで、ダミーのnema,email,password,password_confirmationのインスタンスを生成することができるので、テストコードを短くすることができます。

それではRspecをuser_spec.rbに書いていきます!

モデルクラスのテストコードを書いてみよう!

/user_spec.rb/
require 'rails_helper'
describe User do
  describe '#create' do
    it "is valid with a nickname, email, password, password_confirmation" do
      user = build(:user)
      expect(user).to be_valid
    end
  
    it "is invalid without a name" do
      user = build(:user, name: "")
      user.valid?
      expect(user.errors[:name]).to include("を入力してください")
    end

    it "is invalid without a email" do
     user = build(:user, email: nil)
     user.valid?
     expect(user.errors[:email]).to include("を入力してください")
    end

    it "is invalid without a password" do
      user = build(:user, password: nil)
      user.valid?
      expect(user.errors[:password]).to include("を入力してください")
    end

    it "is invalid without a password_confirmation although with a password" do
      user = build(:user, password_confirmation: "")
      user.valid?
      expect(user.errors[:password_confirmation]).to include("とPasswordの入力が一致しません")
    end

    it "is invalid a name that has more than 11 characters" do
      user = build(:user, name: "aaaaaaaaaaa")
      user.valid?
      expect(user.errors[:name][0]).to include("は10文字以内で入力してください")
    end

    it "is invalid with a duplicate email address" do
      user = create(:user)
      another_user = build(:user, email: user.email)
      another_user.valid?
      expect(another_user.errors[:email]).to include("はすでに存在します")
    end

    it "is valid with a name that has less than 10 characters " do
      user = build(:user, name: "aaaaaaaaaa")
      expect(user).to be_valid
    end

    it "is invalid with a password that has less than 5 characters " do
      user = build(:user, password: "00000", password_confirmation: "00000")
      user.valid?
      expect(user.errors[:password][0]).to include("は6文字以上で入力してください")
    end

    it "is invalid a password that has more than 6 characters" do
      user = build(:user, password: "000000", password_confirmation: "000000")
      user.valid?
      expect(user).to be_valid
    end
  end
end

完成したコードはこちらで、ターミナルにbundle exec rspecとコマンドを打ち込むことで確かめることができます。

/ターミナル/
User
  #create
    is valid with a name, email, password, password_confirmation
    is invalid without a name
    is invalid without a email
    is invalid without a password
    is invalid without a password_confirmation although with a password
    is invalid a name that has more than 11 characters
    is invalid with a duplicate email address
    is valid with a name that has less than 10 characters
    is invalid with a password that has less than 5 characters
    is invalid a password that has more than 6 characters

Finished in 2.2 seconds (files took 3.84 seconds to load)
10 examples, 0 failures

英語ばかりでわかりにくいかもしれませんが、今回は上記全てに関して解説すると記述がかなり多くなってしまうので、下の3つをピックアップして解説します!

・nameとemail、passwordとpassword_confirmationが存在すれば登録できること
・nameが空では登録できないこと
・nameが11文字以上であれば登録できないこと
require 'rails_helper'
describe User do
  describe '#create' do

   #nameとemail、passwordとpassword_confirmationが存在すれば登録できること
    it "is valid with a name, email, password, password_confirmation" do
      user = build(:user)
      expect(user).to be_valid
    end

   #nameが空では登録できないこと
    it "is invalid without a name" do
      user = build(:user, name: "")
      user.valid?
      expect(user.errors[:name]).to include("を入力してください")
    end
  #nameが11文字以上であれば登録できないこと
   it "is invalid a name that has more than 11 characters" do
     user = build(:user, name: "aaaaaaaaaaa") 
     user.valid? 
     expect(user.errors[:name][0]).to include("は10文字以内で入力してください")
   end
end

最初にrequireでrails_helper.rbのファイルを読み込み、describe以下に記述。

describeとdoの間にメソッド記述する際は#を書くのが慣習です。

buildメソッド

buildメソッドはfactory_girlにおけるメソッドです。引数にシンボル型のクラスとname:””というキーと値を入れると、先程factories/user.rbで記述したインスタンスのnameを上書きすることができます。

valid?メソッド

このメソッドでバリデーションで保存できない状態であるかを確かめることができます。

errorsメソッド

valid?メソッドの返り値true/falseに対してerrorsメソッドを使用すると、バリデーションで保存できない状態である場合になぜできないのかを確認することができます。

includeマッチャ

includeの引数にとった値が、expectの引数にとった配列に含まれているかどうかを確認することができます。

今回は‘rails-i18n’というgemを導入してエラー文を日本語にしています。

be_validマッチャ

expectの引数にしたインスタンスが全てのバリデーションをクリアする場合にパスするバリデーションです。

これでname,email,password,password_confirmの全てがちゃんと登録できるか確認することができます。

これらのメソッドやマッチャを組み合わせてRspecで記述します。

あとはターミナルでbundle exec rspecというコマンドを打つと

/ターミナル/
User
  #create
    is valid with a name, email, password, password_confirmation
    is invalid without a name
    is invalid a name that has more than 11 characters

Finished in 2.2 seconds (files took 3.84 seconds to load)
3examples, 0 failures

このようにit以下に記述したものクリアした場合に表示され、0 failuresとなります。

もし仮にRspecの記述を一つ間違えると、1 failuresとなってしまいますが、どこが間違えているのかエラー文が出るために確認することが出来ます。

例えば、includeの引数の中を間違えたりすると、

このように“は10文字以内で入力してください”というのが本来でるエラー文のはずが、“11文字”にしてしまったためfailureになりました。

わかりやすいですね!

これでvalidationのテストが一通り出来たかと思います!

まとめ

・validationのテストコードはメソッドやマッチャを理解して入れば記述はなんとなく似ているので結構簡単にできる!

・テストするはずなのにテストコードの記述を間違えてしまうことが結構ある。(自分だけ?)

・今度はCapybaraを使用して、E2Eテスト方法をまとめます!

「天職」の見つけ方がわかる