Skip to content

RSpec/LeakyConstantDeclaration should allow self::Constant #1999

@jacob-carlborg-apoex

Description

@jacob-carlborg-apoex

I think constants should be allowed to be declared inside RSpec example groups (blocks) if they are prefixed with self::. That means they will be declared in the scope of the class that RSpec generates from the example group and not leak between examples.

Alternatives are using anonymous classes, which work most of the time, but not when something depends on the name of a constant. stub_const could be used for that, but it will not give the exact same behavior since constants created using stub_const are global, while using the self:: syntax the constant is only available inside the example group.


Expected behavior

RuboCop RSpec should not report a violation for the RSpec/LeakyConstantDeclaration cop.

Actual behavior

RuboCop reported a violation for the RSpec/LeakyConstantDeclaration cop.

Steps to reproduce the problem

$ cat .rubocop.yml                                                                                                                                                                                                                                                                                          
require: rubocop-rspec

AllCops:
  NewCops: enable

Lint/ConstantDefinitionInBlock:
  Enabled: false

Style/ClassAndModuleChildren:
  Enabled: false
$ cat spec/foo_spec.rb
# frozen_string_literal: true

class Foo
  p 1
end

RSpec.describe Foo do
  class self::Bar
    p 2
  end

  it 'foos' do
    a = 1
    b = 1
    expect(a).to eq(b)
  end
end
$ rubocop --debug
For /Users/jacobcarlborg/tmp/foo: configuration from /Users/jacobcarlborg/tmp/foo/.rubocop.yml
configuration from /Users/jacobcarlborg/.rvm/gems/ruby-3.3.1@tmp/gems/rubocop-rspec-3.2.0/config/default.yml
configuration from /Users/jacobcarlborg/.rvm/gems/ruby-3.3.1@tmp/gems/rubocop-rspec-3.2.0/config/default.yml
Default configuration from /Users/jacobcarlborg/.rvm/gems/ruby-3.3.1@tmp/gems/rubocop-1.68.0/config/default.yml
Use parallel by default.
Skipping parallel inspection: only a single file needs inspection
Inspecting 1 file
Scanning /Users/jacobcarlborg/tmp/foo/spec/foo_spec.rb
Loading cache from /Users/jacobcarlborg/.cache/rubocop_cache/2dcfb942ca93a0dc63eb61016a124149aef2bdf0/6d7a3b621ca1730e04accd938619e4bdab66cfb1/4d38f5d19f98ec6a78dfe1fbc7ac728ab6b24e61
C

Offenses:

spec/foo_spec.rb:8:3: C: RSpec/LeakyConstantDeclaration: Stub class constant instead of declaring explicitly.
  class Bar ...
  ^^^^^^^^^

1 file inspected, 1 offense detected
Finished in 0.11534700001357123 seconds

RuboCop RSpec version

$ rubocop -V                                                                                                                                                                                                                                                                                                
1.68.0 (using Parser 3.3.6.0, rubocop-ast 1.36.1, analyzing as Ruby 2.7, running on ruby 3.3.1) [arm64-darwin23]
  - rubocop-rspec 3.2.0

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