Skip to content

Cop Idea: RSpecRails/NoUpdateInBefore Cop #75

@naofumi-fujii

Description

@naofumi-fujii

Cop Idea RSpecRails/NoUpdateInBefore Cop

Summary

A new RuboCop cop that detects and prevents updating let/let! variables inside before blocks in RSpec tests. This pattern makes tests harder to read and understand by hiding the test setup state.

Motivation

When test data is mutated in before blocks, it becomes difficult to understand what exactly is being tested in each context. Readers need to mentally track the initial state from the let declaration and then apply modifications from the before block to understand the actual test state.

Bad Example

let(:setting) { Setting.first }

before do
  setting.update!(enabled: true)
end

it 'does something' do
  # What is the state of setting here?
  # You need to look at both the let and before blocks
end

Good Example

context 'when setting is enabled' do
  let(:setting) { create(:setting, enabled: true) }

  it 'does something' do
    # Clear: setting is enabled, defined right here
  end
end

Implementation Details

The cop detects calls to the following Active Record update methods on let/let! variables within before blocks:

  • update
  • update!
  • update_attribute
  • update_attributes
  • update_column
  • update_columns

What is Detected

# Offense: updating let variable in before
let(:user) { create(:user) }

before do
  user.update!(name: 'John')  # ❌ Detected
end

What is Allowed

# No offense: updating non-let variable
before do
  Setting.first.update!(enabled: true)  # ✅ Allowed
end

# No offense: updating in test body
it 'updates user' do
  user.update!(name: 'John')  # ✅ Allowed
end

# No offense: calling non-update methods
before do
  user.reload  # ✅ Allowed
end

Configuration

RSpecRails/NoUpdateInBefore:
  Enabled: true
  Include:
    - 'spec/**/*_spec.rb'

Cop Message

Do not update let/let! variable `%{variable}` in before block.
Define data explicitly in each context instead.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions