RSpec

Checks that left braces for adjacent single line lets are aligned.

Examples

# bad let(:foobar) < blahblah >let(:baz) < bar >let(:a) < b ># good let(:foobar) < blahblah >let(:baz) < bar >let(:a)

References

RSpec/AlignRightLetBrace

Checks that right braces for adjacent single line lets are aligned.

Examples

# bad let(:foobar) < blahblah >let(:baz) < bar >let(:a) < b ># good let(:foobar) < blahblah >let(:baz) < bar >let(:a)

References

RSpec/AnyInstance

Check that instances are not being stubbed globally.

Prefer instance doubles over stubbing any instance of a class

Examples

# bad describe MyClass do before < allow_any_instance_of(MyClass).to receive(:foo) >end # good describe MyClass do let(:my_instance) < instance_double(MyClass) >before do allow(MyClass).to receive(:new).and_return(my_instance) allow(my_instance).to receive(:foo) end end

References

RSpec/AroundBlock

Checks that around blocks actually run the test.

Examples

# bad around do some_method end around do |test| some_method end # good around do |test| some_method test.call end around do |test| some_method test.run end

References

RSpec/Be

Check for expectations where be is used without argument.

The be matcher is too generic, as it pass on everything that is not nil or false. If that is the exact intend, use be_truthy . In all other cases it’s better to specify what exactly is the expected value.

Examples

# bad expect(foo).to be # good expect(foo).to be_truthy expect(foo).to be 1.0 expect(foo).to be(true)

References

RSpec/BeEmpty

Prefer using be_empty when checking for an empty array.

Examples

# bad expect(array).to contain_exactly expect(array).to match_array([]) # good expect(array).to be_empty

References

RSpec/BeEq

Check for expectations where be(…​) can replace eq(…​) .

The be matcher compares by identity while the eq matcher compares using == . Booleans and nil can be compared by identity and therefore the be matcher is preferable as it is a more strict test.

Safety

This cop is unsafe because it changes how values are compared.

Examples

# bad expect(foo).to eq(true) expect(foo).to eq(false) expect(foo).to eq(nil) # good expect(foo).to be(true) expect(foo).to be(false) expect(foo).to be(nil)

References

RSpec/BeEql

Check for expectations where be(…​) can replace eql(…​) .

The be matcher compares by identity while the eql matcher compares using eql? . Integers, floats, booleans, symbols, and nil can be compared by identity and therefore the be matcher is preferable as it is a more strict test.

This cop only looks for instances of expect(…​).to eql(…​) . We do not check to_not or not_to since !eql? is more strict than !equal? . We also do not try to flag eq because if a == b , and b is comparable by identity, a is still not necessarily the same type as b since the #== operator can coerce objects for comparison.

Safety

This cop is unsafe because it changes how values are compared.

Examples

# bad expect(foo).to eql(1) expect(foo).to eql(1.0) expect(foo).to eql(true) expect(foo).to eql(false) expect(foo).to eql(:bar) expect(foo).to eql(nil) # good expect(foo).to be(1) expect(foo).to be(1.0) expect(foo).to be(true) expect(foo).to be(false) expect(foo).to be(:bar) expect(foo).to be(nil)

References

RSpec/BeNil

Ensures a consistent style is used when matching nil .

You can either use the more specific be_nil matcher, or the more generic be matcher with a nil argument.

This cop can be configured using the EnforcedStyle option

Examples

EnforcedStyle: be_nil (default)

# bad expect(foo).to be(nil) # good expect(foo).to be_nil

EnforcedStyle: be

# bad expect(foo).to be_nil # good expect(foo).to be(nil)

Configurable attributes

References

RSpec/BeforeAfterAll

Check that before/after(:all/:context) isn’t being used.

Examples

# bad - Faster but risk of state leaking between examples describe MyClass do before(:all) < Widget.create >after(:context) < Widget.delete_all >end # good - Slower but examples are properly isolated describe MyClass do before(:each) < Widget.create >after(:each) < Widget.delete_all >end

Configurable attributes

**/spec/spec_helper.rb , **/spec/rails_helper.rb , **/spec/support/**/*.rb

References

RSpec/ChangeByZero

Prefer negated matchers over to change.by(0) .

In the case of composite expectations, cop suggest using the negation matchers of RSpec::Matchers#change .

By default the cop does not support autocorrect of compound expectations, but if you set the negated matcher for change , e.g. not_change with the NegatedMatcher option, the cop will perform the autocorrection.

Examples

NegatedMatcher: ~ (default)

# bad expect < run >.to change(Foo, :bar).by(0) expect < run >.to change < Foo.bar >.by(0) # bad - compound expectations (does not support autocorrection) expect < run >.to change(Foo, :bar).by(0) .and change(Foo, :baz).by(0) expect < run >.to change < Foo.bar >.by(0) .and change < Foo.baz >.by(0) # good expect < run >.not_to change(Foo, :bar) expect < run >.not_to change < Foo.bar ># good - compound expectations define_negated_matcher :not_change, :change expect < run >.to not_change(Foo, :bar) .and not_change(Foo, :baz) expect < run >.to not_change < Foo.bar >.and not_change

NegatedMatcher: not_change

# bad (support autocorrection to good case) expect < run >.to change(Foo, :bar).by(0) .and change(Foo, :baz).by(0) expect < run >.to change < Foo.bar >.by(0) .and change < Foo.baz >.by(0) # good define_negated_matcher :not_change, :change expect < run >.to not_change(Foo, :bar) .and not_change(Foo, :baz) expect < run >.to not_change < Foo.bar >.and not_change

Configurable attributes

References

RSpec/ClassCheck

Enforces consistent use of be_a or be_kind_of .

Examples

EnforcedStyle: be_a (default)

# bad expect(object).to be_kind_of(String) expect(object).to be_a_kind_of(String) # good expect(object).to be_a(String) expect(object).to be_an(String)

EnforcedStyle: be_kind_of

# bad expect(object).to be_a(String) expect(object).to be_an(String) # good expect(object).to be_kind_of(String) expect(object).to be_a_kind_of(String)

Configurable attributes

References

RSpec/ContainExactly

Checks where contain_exactly is used.

This cop checks for the following: - Prefer match_array when matching array values. - Prefer be_empty when using contain_exactly with no arguments.

Examples

# bad it < is_expected.to contain_exactly(*array1, *array2) ># good it < is_expected.to match_array(array1 + array2) ># good it

References

RSpec/ContextMethod

context should not be used for specifying methods.

Examples

# bad context '#foo_bar' do # . end context '.foo_bar' do # . end # good describe '#foo_bar' do # . end describe '.foo_bar' do # . end

References

RSpec/ContextWording

Checks that context docstring starts with an allowed prefix.

The default list of prefixes is minimal. Users are encouraged to tailor the configuration to meet project needs. Other acceptable prefixes may include if , unless , for , before , after , or during . They may consist of multiple words if desired.

This cop can be customized allowed context description pattern with AllowedPatterns . By default, there are no checking by pattern.

Examples

Prefixes configuration

# .rubocop.yml # RSpec/ContextWording: # Prefixes: # - when # - with # - without # - if # - unless # - for
# bad context 'the display name not present' do # . end # good context 'when the display name is not present' do # . end

AllowedPatterns configuration

# .rubocop.yml # RSpec/ContextWording: # AllowedPatterns: # - とき$
# bad context '条件を満たす' do # . end # good context '条件を満たすとき' do # . end

Configurable attributes

when , with , without

References

RSpec/DescribeClass

Check that the first argument to the top-level describe is a constant.

It can be configured to ignore strings when certain metadata is passed.

Ignores Rails and Aruba type metadata by default.

Examples

IgnoredMetadata configuration

# .rubocop.yml # RSpec/DescribeClass: # IgnoredMetadata: # type: # - request # - controller
# bad describe 'Do something' do end # good describe TestedClass do subject < described_class >end describe 'TestedClass::VERSION' do subject < Object.const_get(self.class.description) >end describe "A feature example", type: :feature do end

Configurable attributes

**/spec/features/**/* , **/spec/requests/**/* , **/spec/routing/**/* , **/spec/system/**/* , **/spec/views/**/*

References

RSpec/DescribeMethod

Checks that the second argument to describe specifies a method.

Examples

# bad describe MyClass, 'do something' do end # good describe MyClass, '#my_instance_method' do end describe MyClass, '.my_class_method' do end

References

RSpec/DescribeSymbol

Avoid describing symbols.

Examples

# bad describe :my_method do # . end # good describe '#my_method' do # . end

References

RSpec/DescribedClass

Checks that tests use described_class .

If the first argument of describe is a class, the class is exposed to each example via described_class.

This cop can be configured using the EnforcedStyle , SkipBlocks and OnlyStaticConstants options. OnlyStaticConstants is only relevant when EnforcedStyle is described_class .

There’s a known caveat with rspec-rails’s controller helper that runs its block in a different context, and described_class is not available to it. SkipBlocks option excludes detection in all non-RSpec related blocks.

To narrow down this setting to only a specific directory, it is possible to use an overriding configuration file local to that directory.

Examples

EnforcedStyle: described_class (default)

# bad describe MyClass do subject < MyClass.do_something >end # good describe MyClass do subject < described_class.do_something >end

OnlyStaticConstants: true (default)

# good describe MyClass do subject < MyClass::CONSTANT >end

OnlyStaticConstants: false

# bad describe MyClass do subject < MyClass::CONSTANT >end

EnforcedStyle: explicit

# bad describe MyClass do subject < described_class.do_something >end # good describe MyClass do subject < MyClass.do_something >end

SkipBlocks: true

# spec/controllers/.rubocop.yml # RSpec/DescribedClass: # SkipBlocks: true # acceptable describe MyConcern do controller(ApplicationController) do include MyConcern end end

Configurable attributes

References

RSpec/DescribedClassModuleWrapping

Avoid opening modules and defining specs within them.

Examples

# bad module MyModule RSpec.describe MyClass do # . end end # good RSpec.describe MyModule::MyClass do # . end

References

RSpec/Dialect

Enforces custom RSpec dialects.

A dialect can be based on the following RSpec methods:

By default all of the RSpec methods and aliases are allowed. By setting a config like:

RSpec/Dialect: PreferredMethods: context: describe

If you were previously using the RSpec/Capybara/FeatureMethods cop and want to keep disabling all Capybara-specific methods that have the same native RSpec method (e.g. are just aliases), use the following config:

RSpec/Dialect: PreferredMethods: background: :before scenario: :it xscenario: :xit given: :let given!: :let! feature: :describe

You can expect the following behavior:

Examples

# bad context 'display name presence' do # . end # good describe 'display name presence' do # . end

Configurable attributes

References

RSpec/DuplicatedMetadata

Avoid duplicated metadata.

Examples

# bad describe 'Something', :a, :a # good describe 'Something', :a

References

RSpec/EmptyExampleGroup

Command-line only (Unsafe)

Checks if an example group does not include any tests.

Examples

usage

# bad describe Bacon do let(:bacon) < Bacon.new(chunkiness) >let(:chunkiness) < false >context 'extra chunky' do # flagged by rubocop let(:chunkiness) < true >end it 'is chunky' do expect(bacon.chunky?).to be_truthy end end # good describe Bacon do let(:bacon) < Bacon.new(chunkiness) >let(:chunkiness) < false >it 'is chunky' do expect(bacon.chunky?).to be_truthy end end # good describe Bacon do pending 'will add tests later' end

References

RSpec/EmptyHook

Checks for empty before and after hooks.

Examples

# bad before <> after do; end before(:all) do end after(:all) < ># good before < create_users >after do cleanup_users end before(:all) do create_feed end after(:all)

References

RSpec/EmptyLineAfterExample

Checks if there is an empty line after example blocks.

Examples

# bad RSpec.describe Foo do it 'does this' do end it 'does that' do end end # good RSpec.describe Foo do it 'does this' do end it 'does that' do end end # fair - it's ok to have non-separated one-liners RSpec.describe Foo do it < one >it < two >end

with AllowConsecutiveOneLiners configuration

# rubocop.yml # RSpec/EmptyLineAfterExample: # AllowConsecutiveOneLiners: false # bad RSpec.describe Foo do it < one >it < two >end

Configurable attributes

References

RSpec/EmptyLineAfterExampleGroup

Checks if there is an empty line after example group blocks.

Examples

# bad RSpec.describe Foo do describe '#bar' do end describe '#baz' do end end # good RSpec.describe Foo do describe '#bar' do end describe '#baz' do end end

References

RSpec/EmptyLineAfterFinalLet

Checks if there is an empty line after the last let block.

Examples

# bad let(:foo) < bar >let(:something) < other >it < does_something ># good let(:foo) < bar >let(:something) < other >it

References

RSpec/EmptyLineAfterHook

Checks if there is an empty line after hook blocks.

AllowConsecutiveOneLiners configures whether adjacent one-line definitions are considered an offense.

Examples

# bad before < do_something >it < does_something ># bad after < do_something >it < does_something ># bad around < |test| test.run >it < does_something ># good after < do_something >it < does_something ># fair - it's ok to have non-separated one-liners hooks around < |test| test.run >after < do_something >it

with AllowConsecutiveOneLiners configuration

# rubocop.yml # RSpec/EmptyLineAfterHook: # AllowConsecutiveOneLiners: false # bad around < |test| test.run >after < do_something >it < does_something ># good around < |test| test.run >after < do_something >it

Configurable attributes

References

RSpec/EmptyLineAfterSubject

Checks if there is an empty line after subject block.

Examples

# bad subject(:obj) < described_class >let(:foo) < bar ># good subject(:obj) < described_class >let(:foo)

References

RSpec/EmptyMetadata

Avoid empty metadata hash.

Examples

EnforcedStyle: symbol (default)

# bad describe 'Something', <> # good describe 'Something'

References

RSpec/EmptyOutput

Check that the output matcher is not called with an empty string.

Examples

# bad expect < foo >.to output('').to_stdout expect < bar >.not_to output('').to_stderr # good expect < foo >.not_to output.to_stdout expect < bar >.to output.to_stderr

References

RSpec/Eq

Use eq instead of be == to compare objects.

Examples

# bad expect(foo).to be == 42 # good expect(foo).to eq 42

References

RSpec/ExampleLength

Checks for long examples.

A long example is usually more difficult to understand. Consider extracting out some behavior, e.g. with a let block, or a helper method.

You can set constructs you want to fold with CountAsOne . Available are: 'array', 'hash', 'heredoc', and 'method_call'. Each construct will be counted as one line regardless of its actual size.

Examples

# bad it do service = described_class.new more_setup more_setup result = service.call expect(result).to be(true) end # good it do service = described_class.new result = service.call expect(result).to be(true) end

CountAsOne: ['array', 'heredoc', 'method_call']

it do array = [ # +1 1, 2 ] hash = < # +3 key: 'value' >msg = 

Configurable attributes

References

RSpec/ExampleWithoutDescription

Checks for examples without a description.

RSpec allows for auto-generated example descriptions when there is no description provided or the description is an empty one. It is acceptable to use specify without a description

This cop removes empty descriptions. It also defines whether auto-generated description is allowed, based on the configured style.

This cop can be configured using the EnforcedStyle option

Examples

# always good specify do result = service.call expect(result).to be(true) end

EnforcedStyle: always_allow (default)

# bad it('') < is_expected.to be_good >specify '' do result = service.call expect(result).to be(true) end # good it < is_expected.to be_good >specify do result = service.call expect(result).to be(true) end

EnforcedStyle: single_line_only

# bad it('') < is_expected.to be_good >it do result = service.call expect(result).to be(true) end # good it

EnforcedStyle: disallow

# bad it < is_expected.to be_good >it do result = service.call expect(result).to be(true) end

Configurable attributes

always_allow , single_line_only , disallow

References

RSpec/ExampleWording

Checks for common mistakes in example descriptions.

This cop will correct docstrings that begin with 'should' and 'it'. This cop will also look for insufficient examples and call them out.

The autocorrect is experimental - use with care! It can be configured with CustomTransform (e.g. have ⇒ has) and IgnoredWords (e.g. only).

Use the DisallowedExamples setting to prevent unclear or insufficient descriptions. Please note that this config will not be treated as case sensitive.

Examples

# bad it 'should find nothing' do end it 'will find nothing' do end # good it 'finds nothing' do end
# bad it 'it does things' do end # good it 'does things' do end

DisallowedExamples: ['works'] (default)

# bad it 'works' do end # good it 'marks the task as done' do end

Configurable attributes

References

RSpec/ExcessiveDocstringSpacing

Checks for excessive whitespace in example descriptions.

Examples

# bad it ' has excessive spacing ' do end # good it 'has excessive spacing' do end
# bad context ' when a condition is met ' do end # good context 'when a condition is met' do end

References

RSpec/ExpectActual

Checks for expect(…​) calls containing literal values.

Autocorrection is performed when the expected is not a literal.

Examples

# bad expect(5).to eq(price) expect(/foo/).to eq(pattern) expect("John").to eq(name) # good expect(price).to eq(5) expect(pattern).to eq(/foo/) expect(name).to eq("John") # bad (not supported autocorrection) expect(false).to eq(true)

Configurable attributes

References

RSpec/ExpectChange

Checks for consistent style of change matcher.

Enforces either passing object and attribute as arguments to the matcher or passing a block that reads the attribute value.

This cop can be configured using the EnforcedStyle option.

Examples

EnforcedStyle: method_call (default)

# bad expect < run >.to change < Foo.bar >expect < run >.to change < foo.baz ># good expect < run >.to change(Foo, :bar) expect < run >.to change(foo, :baz) # also good when there are arguments or chained method calls expect < run >.to change < Foo.bar(:count) >expect < run >.to change

EnforcedStyle: block

# bad expect < run >.to change(Foo, :bar) # good expect < run >.to change

Configurable attributes

References

RSpec/ExpectInHook

Do not use expect in hooks such as before .

Examples

# bad before do expect(something).to eq 'foo' end # bad after do expect_any_instance_of(Something).to receive(:foo) end # good it do expect(something).to eq 'foo' end

References

RSpec/ExpectInLet

Do not use expect in let.

Examples

# bad let(:foo) do expect(something).to eq 'foo' end # good it do expect(something).to eq 'foo' end

References

RSpec/ExpectOutput

Checks for opportunities to use expect < …​ >.to output .

Examples

# bad $stdout = StringIO.new my_app.print_report $stdout = STDOUT expect($stdout.string).to eq('Hello World') # good expect < my_app.print_report >.to output('Hello World').to_stdout

References

RSpec/Focus

Checks if examples are focused.

This cop does not support autocorrection in some cases.

Examples

# bad describe MyClass, focus: true do end describe MyClass, :focus do end fdescribe MyClass do end # good describe MyClass do end # bad fdescribe 'test' do; end # good describe 'test' do; end # bad fdescribe 'test' do; end # good describe 'test' do; end # bad shared_examples 'test', focus: true do; end # good shared_examples 'test' do; end # bad shared_context 'test', focus: true do; end # good shared_context 'test' do; end # bad (does not support autocorrection) focus 'test' do; end

References

RSpec/HookArgument

Checks the arguments passed to before , around , and after .

This cop checks for consistent style when specifying RSpec hooks which run for each example. There are three supported styles: "implicit", "each", and "example." All styles have the same behavior.

Examples

EnforcedStyle: implicit (default)

# bad before(:each) do # . end # bad before(:example) do # . end # good before do # . end

EnforcedStyle: each

# bad before(:example) do # . end # bad before do # . end # good before(:each) do # . end

EnforcedStyle: example

# bad before(:each) do # . end # bad before do # . end # good before(:example) do # . end

Configurable attributes

implicit , each , example

References

RSpec/HooksBeforeExamples

Checks for before/around/after hooks that come after an example.

Examples

# bad it 'checks what foo does' do expect(foo).to be end before < prepare >after < clean_up ># good before < prepare >after < clean_up >it 'checks what foo does' do expect(foo).to be end

References

RSpec/IdenticalEqualityAssertion

Checks for equality assertions with identical expressions on both sides.

Examples

# bad expect(foo.bar).to eq(foo.bar) expect(foo.bar).to eql(foo.bar) # good expect(foo.bar).to eq(2) expect(foo.bar).to eql(2)

References

RSpec/ImplicitBlockExpectation

Check that implicit block expectation syntax is not used.

Prefer using explicit block expectations.

Examples

# bad subject < -> < do_something >> it < is_expected.to change(something).to(new_value) ># good it 'changes something to a new value' do expect < do_something >.to change(something).to(new_value) end

References

RSpec/ImplicitExpect

Check that a consistent implicit expectation style is used.

This cop can be configured using the EnforcedStyle option and supports the --auto-gen-config flag.

Examples

EnforcedStyle: is_expected (default)

# bad it < should be_truthy ># good it

EnforcedStyle: should

# bad it < is_expected.to be_truthy ># good it

Configurable attributes

References

RSpec/ImplicitSubject

Checks for usage of implicit subject ( is_expected / should ).

This cop can be configured using the EnforcedStyle option

Examples

EnforcedStyle: single_line_only (default)

# bad it do is_expected.to be_truthy end # good it < is_expected.to be_truthy >it do expect(subject).to be_truthy end

EnforcedStyle: single_statement_only

# bad it do foo = 1 is_expected.to be_truthy end # good it do foo = 1 expect(subject).to be_truthy end it do is_expected.to be_truthy end

EnforcedStyle: disallow

# bad it < is_expected.to be_truthy ># good it

EnforcedStyle: require_implicit

# bad it < expect(subject).to be_truthy ># good it < is_expected.to be_truthy ># bad it do expect(subject).to be_truthy end # good it do is_expected.to be_truthy end # good it

Configurable attributes

single_line_only , single_statement_only , disallow , require_implicit

References

RSpec/IndexedLet

Do not set up test data using indexes (e.g., item_1 , item_2 ).

It makes reading the test harder because it’s not clear what exactly is tested by this particular example.

The configurable options AllowedIdentifiers and AllowedPatterns will also read those set in Naming/VariableNumber .

Examples

Max: 1 (default)

# bad let(:item_1) < create(:item) >let(:item_2) < create(:item) >let(:item1) < create(:item) >let(:item2) < create(:item) ># good let(:visible_item) < create(:item, visible: true) >let(:invisible_item)

Max: 2

# bad let(:item_1) < create(:item) >let(:item_2) < create(:item) >let(:item_3) < create(:item) ># good let(:item_1) < create(:item) >let(:item_2)

AllowedIdentifiers: ['item_1', 'item_2']

# good let(:item_1) < create(:item) >let(:item_2)

AllowedPatterns: ['item']

# good let(:item_1) < create(:item) >let(:item_2)

Configurable attributes

References

RSpec/InstanceSpy

Checks for instance_double used with have_received .

Examples

# bad it do foo = instance_double(Foo).as_null_object expect(foo).to have_received(:bar) end # good it do foo = instance_spy(Foo) expect(foo).to have_received(:bar) end

References

RSpec/InstanceVariable

Checks for instance variable usage in specs.

This cop can be configured with the option AssignmentOnly which will configure the cop to only register offenses on instance variable usage if the instance variable is also assigned within the spec

Examples

# bad describe MyClass do before < @foo = [] >it < expect(@foo).to be_empty >end # good describe MyClass do let(:foo) < [] >it < expect(foo).to be_empty >end

with AssignmentOnly configuration

# rubocop.yml # RSpec/InstanceVariable: # AssignmentOnly: true # bad describe MyClass do before < @foo = [] >it < expect(@foo).to be_empty >end # allowed describe MyClass do it < expect(@foo).to be_empty >end # good describe MyClass do let(:foo) < [] >it < expect(foo).to be_empty >end

Configurable attributes

References

RSpec/IsExpectedSpecify

Check for specify with is_expected and one-liner expectations.

Examples

# bad specify < is_expected.to be_truthy ># good it < is_expected.to be_truthy ># good specify do # . end specify

References

RSpec/ItBehavesLike

Checks that only one it_behaves_like style is used.

Examples

EnforcedStyle: it_behaves_like (default)

# bad it_should_behave_like 'a foo' # good it_behaves_like 'a foo'

EnforcedStyle: it_should_behave_like

# bad it_behaves_like 'a foo' # good it_should_behave_like 'a foo'

Configurable attributes

References

RSpec/IteratedExpectation

Check that all matcher is used instead of iterating over an array.

Examples

# bad it 'validates users' do [user1, user2, user3].each < |user| expect(user).to be_valid >end # good it 'validates users' do expect([user1, user2, user3]).to all(be_valid) end

References

RSpec/LeadingSubject

Enforce that subject is the first definition in the test.

Examples

# bad let(:params) < blah >subject < described_class.new(params) >before < do_something >subject < described_class.new(params) >it < expect_something >subject < described_class.new(params) >it < expect_something_else ># good subject < described_class.new(params) >let(:params) < blah ># good subject < described_class.new(params) >before < do_something ># good subject < described_class.new(params) >it < expect_something >it

References

RSpec/LeakyConstantDeclaration

Checks that no class, module, or constant is declared.

Constants, including classes and modules, when declared in a block scope, are defined in global namespace, and leak between examples.

If several examples may define a DummyClass , instead of being a blank slate class as it will be in the first example, subsequent examples will be reopening it and modifying its behavior in unpredictable ways. Even worse when a class that exists in the codebase is reopened.

Anonymous classes are fine, since they don’t result in global namespace name clashes.

Examples

Constants leak between examples

# bad describe SomeClass do OtherClass = Struct.new CONSTANT_HERE = 'I leak into global namespace' end # good describe SomeClass do before do stub_const('OtherClass', Struct.new) stub_const('CONSTANT_HERE', 'I only exist during this example') end end
# bad describe SomeClass do class FooClass < described_class def double_that some_base_method * 2 end end it < expect(FooClass.new.double_that).to eq(4) >end # good - anonymous class, no constant needs to be defined describe SomeClass do let(:foo_class) do Class.new(described_class) do def double_that some_base_method * 2 end end end it < expect(foo_class.new.double_that).to eq(4) >end # good - constant is stubbed describe SomeClass do before do foo_class = Class.new(described_class) do def do_something end end stub_const('FooClass', foo_class) end it < expect(FooClass.new.double_that).to eq(4) >end
# bad describe SomeClass do module SomeModule class SomeClass def do_something end end end end # good describe SomeClass do before do foo_class = Class.new(described_class) do def do_something end end stub_const('SomeModule::SomeClass', foo_class) end end

References