Class: RuboCop::Cop::RSpec::LeakyLocalVariable

Inherits:
Base
  • Object
show all
Defined in:
lib/rubocop/cop/rspec/leaky_local_variable.rb

Overview

Checks for local variables from outer scopes used inside examples.

Local variables assigned outside an example but used within it act as shared state, which can make tests non-deterministic.

Examples:

# bad - outside variable used in a hook
user = create(:user)

before { user.update(admin: true) }

# good
let(:user) { create(:user) }

before { user.update(admin: true) }

# bad - outside variable used in an example
user = create(:user)

it 'is persisted' do
  expect(user).to be_persisted
end

# good
let(:user) { create(:user) }

it 'is persisted' do
  expect(user).to be_persisted
end

# also good - assigning the variable within the example
it 'is persisted' do
  user = create(:user)

  expect(user).to be_persisted
end

# bad - outside variable passed to included examples
attrs = ['foo', 'bar']

it_behaves_like 'some examples', attrs

# good
it_behaves_like 'some examples' do
  let(:attrs) { ['foo', 'bar'] }
end

# good - when variable is used only as example description
attribute = 'foo'

it "#{attribute} is persisted" do
  expectations
end

# good - when variable is used only to include other examples
examples = foo ? 'some examples' : 'other examples'

it_behaves_like examples, another_argument

Constant Summary collapse

MSG =
'Do not use local variables defined outside of ' \
'examples inside of them.'

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

inherited, #on_new_investigation

Methods included from RSpec::Language

#example?, #example_group?, #example_group_with_body?, #explicit_rspec?, #hook?, #include?, #let?, #rspec?, #shared_group?, #spec_group?, #subject?

Class Method Details

.joining_forcesObject



79
80
81
# File 'lib/rubocop/cop/rspec/leaky_local_variable.rb', line 79

def self.joining_forces
  VariableForce
end

Instance Method Details

#after_leaving_scope(scope, _variable_table) ⇒ Object



83
84
85
# File 'lib/rubocop/cop/rspec/leaky_local_variable.rb', line 83

def after_leaving_scope(scope, _variable_table)
  scope.variables.each_value { |variable| check_references(variable) }
end

#example_method?(node) ⇒ Object



70
71
72
# File 'lib/rubocop/cop/rspec/leaky_local_variable.rb', line 70

def_node_matcher :example_method?, "(send nil? #Examples.all _)\n"

#includes_method?(node) ⇒ Object



75
76
77
# File 'lib/rubocop/cop/rspec/leaky_local_variable.rb', line 75

def_node_matcher :includes_method?, "(send nil? #Includes.all ...)\n"