LoginSignup
0
0

More than 3 years have passed since last update.

【RSpec】letの利点が分からないので、letとbefore両方試してみた

Last updated at Posted at 2020-12-02

はじめに

RSpec学習中に「letとbeforeなら、letを使ったほうが無難」ということを耳にしました。しっかり理解した上で、letを使いたいと思いletとbeforeの違いを調べたところ、淡白な解説を読むよりも、具体例を示したほうが一目瞭然であることに気づき、備忘録としてまとめることにしました。

そこで、本記事ではuserモデルの単体テストを例に、beforeとletを使用した時の挙動の違いを示します。

使用技術

  • gem
    • devise
    • factory_bot
    • rspec

準備

  • deviseで、ユーザモデルを作成 (https://qiita.com/Hal_mai/items/350c400e8763ce0487a3)
  • factory_botで、テストデータを用意
  • passwordは、存在チェックのvalidationがかけられているため、敢えて空白を代入し、保存時にエラーが出る前提のuserデータを用意しました。

テストデータ(user)

FactoryBot.define do
  factory :user do
    name { "User1" }
    email { "email@sample.com" }
    #validationでエラーが出る様にあえて空白を代入
    password { "" }
  end
end

beforeを用いた場合のrspec


require 'rails_helper'

RSpec.describe User, type: :model do

  #------------beforeを用いた場合-----------
  before do
    @user = build(:user)
  end
  #---------------------------------------

  #正常系
  it "is valid with adequet name, email and password" do
    user = @user
    expect(user).to be_valid
  end

  #異常系
  it 'is invalid without a name' do
    user = @user
    user.name = ""
    user.valid?
    expect(user.errors.messages[:name]).to include("を入力してください")
  end

end

letを用いた場合のrspec


require 'rails_helper'

RSpec.describe User, type: :model do

  #------------letを用いた場合-----------
  let(:user) { build(:user)  }
  #---------------------------------------

  #正常系
  it "is valid with adequet name, email and password" do
    user = @user
    expect(user).to be_valid
  end

  #異常系
  it 'is invalid without a name' do
    user = @user
    user.name = ""
    user.valid?
    expect(user.errors.messages[:name]).to include("を入力してください")
  end

end

テスト結果

beforeを用いた場合

F.

Failures:

  1) User is valid with adequet name, email and password
     Failure/Error: expect(user).to be_valid
       expected #<User id: nil, email: "email1@sample.com", name: "User1", created_at: nil, updated_at: nil> to be valid, but got errors: パスワードを入力してください
     # ./spec/models/user_spec.rb:13:in `block (2 levels) in <top (required)>'

Finished in 0.99262 seconds (files took 11.68 seconds to load)
2 examples, 1 failure

letを用いた場合

FF

Failures:

  1) User is valid with adequet name, email and password
     Failure/Error: expect(user).to be_valid

     NoMethodError:
       undefined method `valid?' for nil:NilClass
     # ./spec/models/user_spec.rb:11:in `block (2 levels) in <top (required)>'

  2) User is invalid without a name
     Failure/Error: user.name = ""

     NoMethodError:
       undefined method `name=' for nil:NilClass
     # ./spec/models/user_spec.rb:17:in `block (2 levels) in <top (required)>'

Finished in 0.16009 seconds (files took 12.2 seconds to load)
2 examples, 2 failures

beforeを用いた場合は、2件中1件のテストケースが成功してしまっています。また、エラーの原因がコンソールから分かりません。
一方、letを用いた場合は、2件ともテストケースが失敗しており、かつNoMethodErrornameに異常があることが一目瞭然です。

参考文献

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0