今回はRSpecのコード内でインスタンス変数を定義したことによるRubocop警告、その対処方法について解説したいと思います。beforeブロック内でインスタンス変数を定義し、そのインスタンス変数をそれぞれのテスト内で使用しているコードをよく見かけますが、それらはRubocop的にNGな方法ですので注意してください。
概要
RSpecのコード内でインスタンス変数をし、Rubocopの検証を実行することで以下のような警告が吐かれてしまいます。
'Avoid instance variables – use let, ' \
'a method call, or a local variable (if possible).'
対処方法
Rubocopのリファレンスを見てみると、対処例が記載されています。
悪い例ではbeforeブロック内でインスタンス変数を定義し利用しているのに対し、良い例ではインスタンス変数をletに置き換えていますね。
# 悪い例
describe MyClass do
before { @foo = [] }
it { expect(@foo).to be_empty }
end
# 良い例
describe MyClass do
let(:foo) { [] }
it { expect(foo).to be_empty }
end
このことを用いて、以下のコード(System Spec)でも書き換えを行なってみます。
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'Accountss', type: :system, js: true do
before do
@account = create(:account)
end
context 'Success' do
it 'has a valid email and password' do
login(@account)
expect(page).to have_current_path authenticated_root_path, ignore_query: true
end
end
end
これを書き換えると以下のようなコードになります。
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'Accounts', type: :system, js: true do
context 'Success' do
let(:account) { create(:account) }
it 'has a valid email and password' do
login(account)
expect(page).to have_current_path authenticated_root_path, ignore_query: true
end
end
end
beforeブロック内で定義しているインスタンス変数をletに置き換えることでよりスッキリしたコードになりました。(もちろんRubocopの警告も出なくなります)
注意点
letは非常に便利なヘルパーメソッドですが、「遅延初期化」という実装する上で大きな注意点があります。
以下のようなコードはletの遅延初期化によってテストがパスしないため、このような場合はletではなくlet!を用いるようにしましょう。
let(:account) { Account.create(name: '田中太郎', loggable_type: '一般') }
it 'アカウント取得ができること' do
expect(Account.first).to eq account
end
参考
今回はRSpecのコード内でインスタンス変数を定義したことによるRubocop警告、その対処方法について解説しました。よく書きがちなコードですが、今後気をつけていただけたらと思います。