引き続き、オリジナルアプリ実装していきます。
ユーザーモデル単体テスト実装 example、エクスペクテーションを記述 bundle exec rspec spec/models/user_spec.rb テストコードを実行してエラー発生
①何が問題でどうしたい
エラーを解決して正常系単体テストをクリアしたい
②現在(位置)
describe を 記述し、before と example を定義し、 単体テストを実行
③問題点
describe が存在しない
④仮説
エラーを調べた結果
Failure/Error: とは、テストが実行できなかった、
もしくは失敗したことを意味する接頭辞である
NoMethodError: とは、呼び出そうとしたメソッドが定義されていない、
メソッドが存在しない、
もしくはそのスコープに存在しないメソッドを呼び出そうとした。
NoMethodError: でエラーの根幹とされているのは、
undefined method `descride' for main:Object なので、
そこに describe が存在するか確かめに行く
⑤試したこと
よく見ると、 descride となっている
descride 'ユーザー新規登録' do
context '新規登録できる場合' do
it 'nicknameとpositionとaffiliationとpasswordとpassword_confirmationが存在すれば登録できる' do
expect(@user).to be_valid
end
end
正しくは、describe であるため、正しいスペルに修正した
この修正により、NoMethodError: は解決された。
しかし、新たに NoMethodError:
今度は、undefined method `valid?' for nil:NilClass
ということで valid? を見に行くことにしようとしたが、
現在は「正常系」の単体テストなので、 valid? という記述はどこにもしていない・・・
しかし、下記の記述に何かあることは確かなので調べに行く
spec/models/user_spec.rb
expect(@user).to be_valid は構文的に間違いないことを確認した
次に、疑わしいのは 情報を受け取っている @user
なので、@user を定義している場所を確認
spec/models/user_spec.rb
@user = FactoryBot.build(:user) 構文的に記述に問題はないことを確認
次に疑わしいのは、参照しているモデル :user
:user 元のモデルを確認
spec/factories/users.rb
構文的に記述に問題がないことを確認
情報の受け渡しの確認は終わったので、
次は、@user が正しく生成されているかを確認
ターミナル でコンソールを開く
rails c
値が全て存在するかを確認
@user = FactoryBot.build(:user)
FactoryBotによって生成されるインスタンスが、
バリデーションでエラーにならないか確認
@user.valid?
結果 true を確認できた
Rspecにおける@user インスタンスは正常に生成されていることを確認できたため
次は、メソッドに渡される直前の@user の中身を確認してみる
spec/models/user_spec.rb
puts @user.inspect # ここで@userの中身をコンソールに出力
expect(@user).to be_valid
ターミナルで
bundle exec rspec spec/models/user_spec.rb でテストを実行
実行結果は nil でした
Rspecにおける@user のインスタンスは正しく生成されているが、 テスト実行時には 中身がないということを確認
テスト前に@user インスタンスを生成しているのは、
before なので、正しくbeforeブロックが動き、 次にdescribeブロックが動いているかを確認
before do puts 'Start of before block' @user = FactoryBot.build(:user) puts @user.errors.full_messages puts 'End of before block' end end describe 'ユーザー新規登録' do puts 'Start of describe block' context '新規登録できる場合' do it 'nicknameとpositionとaffiliationとpasswordとpassword_confirmationが存在すれば登録できる' do puts 'Start of it block' @user = FactoryBot.build(:user) expect(@user).to be_valid puts 'End of it block' end puts 'End of describe block' end
ターミナルで
bundle exec rspec spec/models/user_spec.rb でテストを実行
実行結果は
mac@yunoMacBook-Air hibitumo % bundle exec rspec spec/models/user_spec.rb Start of describe block End of describe block ユーザー新規登録 新規登録できる場合 Start of it block nicknameとpositionとaffiliationとpasswordとpassword_confirmationが存在すれば登録できる (FAILED - 1) 新規登録できない場合
puts 'Start of before block' と puts 'End of before block' の出力も、
puts @user.errors.full_messages も出力されず、
beforeブロックをすっ飛ばして、
いきなり、Start of describe block から処理が始まっていることを確認
⑥結果
beforeブロックが動いていないことを確認
example に 直接 @user = FactoryBot.build(:user) を記述
it 'nicknameとpositionとaffiliationとpasswordとpassword_confirmationが存在すれば登録できる' do @user = FactoryBot.build(:user) expect(@user).to be_valid end
ターミナルで
bundle exec rspec spec/models/user_spec.rb でテストを実行
正常系モデル単体テストをクリアすることができた
原因:
何らかの原因でbeforeブロックが動かず、 その結果、@userインスタンスが生成されず、 エクスペクテーションに空の@user が渡されエラーとなった
解決方法:
example に 直接 @user = FactoryBot.build(:user) を記述
気付き:
なぜ、beforeブロックが動かなかったのかが気がかり
調べてみると、
RSpec のバージョンによって、before
ブロックの動作が異なることがあります。最新のバージョンにアップグレードすることで問題が解決する場合があります。
ということで、ふと 関係ないかもしれないが、 AWSを導入する時、初期設定時に、rails のバージョンを カリキュラムに合わせ 「3.2.0」でインストールしたが、もしかしたら、 「7.0.0」だったのではないか?という懸念を今、抱いている