nevir/rubocop-rspec

View on GitHub
docs/modules/ROOT/pages/cops_rspec.adoc

Summary

Maintainability
Test Coverage
////
  Do NOT edit this file by hand directly, as it is automatically generated.

  Please make any necessary changes to the cop documentation within the source files themselves.
////

= RSpec

== RSpec/AlignLeftLetBrace

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Disabled
| Yes
| Always
| 1.16
| -
|===

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

=== Examples

[source,ruby]
----
# bad
let(:foobar) { blahblah }
let(:baz) { bar }
let(:a) { b }

# good
let(:foobar) { blahblah }
let(:baz)    { bar }
let(:a)      { b }
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AlignLeftLetBrace

== RSpec/AlignRightLetBrace

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Disabled
| Yes
| Always
| 1.16
| -
|===

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

=== Examples

[source,ruby]
----
# bad
let(:foobar) { blahblah }
let(:baz)    { bar }
let(:a)      { b }

# good
let(:foobar) { blahblah }
let(:baz)    { bar      }
let(:a)      { b        }
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AlignRightLetBrace

== RSpec/AnyInstance

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.4
| -
|===

Check that instances are not being stubbed globally.

Prefer instance doubles over stubbing any instance of a class

=== Examples

[source,ruby]
----
# 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

* https://rspec.rubystyle.guide/#any_instance_of
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AnyInstance

== RSpec/AroundBlock

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.11
| -
|===

Checks that around blocks actually run the test.

=== Examples

[source,ruby]
----
# 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

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AroundBlock

== RSpec/Be

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.25
| -
|===

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

[source,ruby]
----
# bad
expect(foo).to be

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

=== References

* https://rspec.rubystyle.guide/#be-matcher
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Be

== RSpec/BeEmpty

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Command-line only
| 2.20
| <<next>>
|===

Prefer using `be_empty` when checking for an empty array.

=== Examples

[source,ruby]
----
# bad
expect(array).to contain_exactly
expect(array).to match_array([])

# good
expect(array).to be_empty
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeEmpty

== RSpec/BeEq

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| No
| Always (Unsafe)
| 2.9.0
| 2.16
|===

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

[source,ruby]
----
# 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

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeEq

== RSpec/BeEql

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| No
| Always (Unsafe)
| 1.7
| 2.16
|===

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

[source,ruby]
----
# 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

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeEql

== RSpec/BeNil

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 2.9.0
| 2.10.0
|===

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)

[source,ruby]
----
# bad
expect(foo).to be(nil)

# good
expect(foo).to be_nil
----

==== `EnforcedStyle: be`

[source,ruby]
----
# bad
expect(foo).to be_nil

# good
expect(foo).to be(nil)
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| EnforcedStyle
| `be_nil`
| `be`, `be_nil`
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeNil

== RSpec/BeforeAfterAll

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.12
| 2.23
|===

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

=== Examples

[source,ruby]
----
# 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

|===
| Name | Default value | Configurable values

| Exclude
| `+**/spec/spec_helper.rb+`, `+**/spec/rails_helper.rb+`, `+**/spec/support/**/*.rb+`
| Array
|===

=== References

* https://rspec.rubystyle.guide/#avoid-hooks-with-context-scope
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeforeAfterAll

== RSpec/ChangeByZero

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 2.11
| 2.14
|===

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)

[source,ruby]
----
# 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 { Foo.baz }
----

==== NegatedMatcher: not_change

[source,ruby]
----
# 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 { Foo.baz }
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| NegatedMatcher
| `<none>`
| 
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ChangeByZero

== RSpec/ClassCheck

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 2.13
| -
|===

Enforces consistent use of `be_a` or `be_kind_of`.

=== Examples

==== EnforcedStyle: be_a (default)

[source,ruby]
----
# 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

[source,ruby]
----
# 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

|===
| Name | Default value | Configurable values

| EnforcedStyle
| `be_a`
| `be_a`, `be_kind_of`
|===

=== References

* https://rubystyle.guide#is-a-vs-kind-of
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ClassCheck

== RSpec/ContainExactly

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 2.19
| -
|===

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

[source,ruby]
----
# bad
it { is_expected.to contain_exactly(*array1, *array2) }

# good
it { is_expected.to match_array(array1 + array2) }

# good
it { is_expected.to contain_exactly(content, *array) }
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ContainExactly

== RSpec/ContextMethod

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 1.36
| -
|===

`context` should not be used for specifying methods.

=== Examples

[source,ruby]
----
# bad
context '#foo_bar' do
  # ...
end

context '.foo_bar' do
  # ...
end

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

describe '.foo_bar' do
  # ...
end
----

=== References

* https://rspec.rubystyle.guide/#example-group-naming
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ContextMethod

== RSpec/ContextWording

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.20
| 2.13
|===

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

[source,ruby]
----
# .rubocop.yml
# RSpec/ContextWording:
#   Prefixes:
#     - when
#     - with
#     - without
#     - if
#     - unless
#     - for
----

[source,ruby]
----
# bad
context 'the display name not present' do
  # ...
end

# good
context 'when the display name is not present' do
  # ...
end
----

==== `AllowedPatterns` configuration

[source,ruby]
----
# .rubocop.yml
# RSpec/ContextWording:
#   AllowedPatterns:
#     - とき$
----

[source,ruby]
----
# bad
context '条件を満たす' do
  # ...
end

# good
context '条件を満たすとき' do
  # ...
end
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| Prefixes
| `when`, `with`, `without`
| Array

| AllowedPatterns
| `[]`
| Array
|===

=== References

* https://rspec.rubystyle.guide/#context-descriptions
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ContextWording
* http://www.betterspecs.org/#contexts

== RSpec/DescribeClass

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.0
| 2.7
|===

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

[source,ruby]
----
# .rubocop.yml
# RSpec/DescribeClass:
#   IgnoredMetadata:
#     type:
#       - request
#       - controller
----

[source,ruby]
----
# 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

|===
| Name | Default value | Configurable values

| Exclude
| `+**/spec/features/**/*+`, `+**/spec/requests/**/*+`, `+**/spec/routing/**/*+`, `+**/spec/system/**/*+`, `+**/spec/views/**/*+`
| Array

| IgnoredMetadata
| `{"type"=>["channel", "controller", "helper", "job", "mailer", "model", "request", "routing", "view", "feature", "system", "mailbox", "aruba", "task"]}`
| 
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeClass

== RSpec/DescribeMethod

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.0
| -
|===

Checks that the second argument to `describe` specifies a method.

=== Examples

[source,ruby]
----
# bad
describe MyClass, 'do something' do
end

# good
describe MyClass, '#my_instance_method' do
end

describe MyClass, '.my_class_method' do
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeMethod

== RSpec/DescribeSymbol

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.15
| -
|===

Avoid describing symbols.

=== Examples

[source,ruby]
----
# bad
describe :my_method do
  # ...
end

# good
describe '#my_method' do
  # ...
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeSymbol
* https://github.com/rspec/rspec-core/issues/1610

== RSpec/DescribedClass

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always (Unsafe)
| 1.0
| 2.27
|===

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)

[source,ruby]
----
# bad
describe MyClass do
  subject { MyClass.do_something }
end

# good
describe MyClass do
  subject { described_class.do_something }
end
----

==== `OnlyStaticConstants: true` (default)

[source,ruby]
----
# good
describe MyClass do
  subject { MyClass::CONSTANT }
end
----

==== `OnlyStaticConstants: false`

[source,ruby]
----
# bad
describe MyClass do
  subject { MyClass::CONSTANT }
end
----

==== `EnforcedStyle: explicit`

[source,ruby]
----
# bad
describe MyClass do
  subject { described_class.do_something }
end

# good
describe MyClass do
  subject { MyClass.do_something }
end
----

==== `SkipBlocks: true`

[source,ruby]
----
# spec/controllers/.rubocop.yml
# RSpec/DescribedClass:
#   SkipBlocks: true

# acceptable
describe MyConcern do
  controller(ApplicationController) do
    include MyConcern
  end
end
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| SkipBlocks
| `false`
| Boolean

| EnforcedStyle
| `described_class`
| `described_class`, `explicit`

| OnlyStaticConstants
| `true`
| Boolean
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribedClass

== RSpec/DescribedClassModuleWrapping

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Disabled
| Yes
| No
| 1.37
| -
|===

Avoid opening modules and defining specs within them.

=== Examples

[source,ruby]
----
# bad
module MyModule
  RSpec.describe MyClass do
    # ...
  end
end

# good
RSpec.describe MyModule::MyClass do
  # ...
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribedClassModuleWrapping
* https://github.com/rubocop/rubocop-rspec/issues/735

== RSpec/Dialect

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Disabled
| Yes
| Always
| 1.33
| -
|===

Enforces custom RSpec dialects.

A dialect can be based on the following RSpec methods:

- describe, context, feature, example_group
- xdescribe, xcontext, xfeature
- fdescribe, fcontext, ffeature
- shared_examples, shared_examples_for, shared_context
- it, specify, example, scenario, its
- fit, fspecify, fexample, fscenario, focus
- xit, xspecify, xexample, xscenario, skip
- pending
- prepend_before, before, append_before,
- around
- prepend_after, after, append_after
- let, let!
- subject, subject!
- expect, is_expected, expect_any_instance_of

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

[source,ruby]
----
# bad
context 'display name presence' do
  # ...
end

# good
describe 'display name presence' do
  # ...
end
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| PreferredMethods
| `{}`
| 
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Dialect

== RSpec/DuplicatedMetadata

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 2.16
| -
|===

Avoid duplicated metadata.

=== Examples

[source,ruby]
----
# bad
describe 'Something', :a, :a

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

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DuplicatedMetadata

== RSpec/EmptyExampleGroup

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Command-line only (Unsafe)
| 1.7
| <<next>>
|===

Checks if an example group does not include any tests.

=== Examples

==== usage

[source,ruby]
----
# 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

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyExampleGroup

== RSpec/EmptyHook

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Command-line only
| 1.39
| <<next>>
|===

Checks for empty before and after hooks.

=== Examples

[source,ruby]
----
# 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) { cleanup_feed }
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyHook

== RSpec/EmptyLineAfterExample

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 1.36
| -
|===

Checks if there is an empty line after example blocks.

=== Examples

[source,ruby]
----
# 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

[source,ruby]
----
# rubocop.yml
# RSpec/EmptyLineAfterExample:
#   AllowConsecutiveOneLiners: false

# bad
RSpec.describe Foo do
  it { one }
  it { two }
end
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowConsecutiveOneLiners
| `true`
| Boolean
|===

=== References

* https://rspec.rubystyle.guide/#empty-lines-around-examples
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterExample

== RSpec/EmptyLineAfterExampleGroup

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 1.27
| -
|===

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

=== Examples

[source,ruby]
----
# 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

* https://rspec.rubystyle.guide/#empty-lines-between-describes
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterExampleGroup

== RSpec/EmptyLineAfterFinalLet

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 1.14
| -
|===

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

=== Examples

[source,ruby]
----
# bad
let(:foo) { bar }
let(:something) { other }
it { does_something }

# good
let(:foo) { bar }
let(:something) { other }

it { does_something }
----

=== References

* https://rspec.rubystyle.guide/#empty-line-after-let
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterFinalLet

== RSpec/EmptyLineAfterHook

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 1.27
| 2.13
|===

Checks if there is an empty line after hook blocks.

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

=== Examples

[source,ruby]
----
# 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 { does_something }
----

==== with AllowConsecutiveOneLiners configuration

[source,ruby]
----
# 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 { does_something }
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowConsecutiveOneLiners
| `true`
| Boolean
|===

=== References

* https://rspec.rubystyle.guide/#empty-line-after-let
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterHook

== RSpec/EmptyLineAfterSubject

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 1.14
| -
|===

Checks if there is an empty line after subject block.

=== Examples

[source,ruby]
----
# bad
subject(:obj) { described_class }
let(:foo) { bar }

# good
subject(:obj) { described_class }

let(:foo) { bar }
----

=== References

* https://rspec.rubystyle.guide/#empty-line-after-let
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterSubject

== RSpec/EmptyMetadata

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Command-line only
| 2.24
| <<next>>
|===

Avoid empty metadata hash.

=== Examples

==== EnforcedStyle: symbol (default)

[source,ruby]
----
# bad
describe 'Something', {}

# good
describe 'Something'
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyMetadata

== RSpec/EmptyOutput

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 2.29
| -
|===

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

=== Examples

[source,ruby]
----
# 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

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyOutput

== RSpec/Eq

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 2.24
| -
|===

Use `eq` instead of `be ==` to compare objects.

=== Examples

[source,ruby]
----
# bad
expect(foo).to be == 42

# good
expect(foo).to eq 42
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Eq

== RSpec/ExampleLength

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.5
| 2.3
|===

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

[source,ruby]
----
# 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']

[source,ruby]
----
it do
  array = [         # +1
    1,
    2
  ]

  hash = {          # +3
    key: 'value'
  }

  msg = <<~HEREDOC  # +1
    Heredoc
    content.
  HEREDOC

  foo(            # +1
    1,
    2
  )
end               # 6 points
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| Max
| `5`
| Integer

| CountAsOne
| `[]`
| Array
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleLength

== RSpec/ExampleWithoutDescription

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.22
| -
|===

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

[source,ruby]
----
# always good
specify do
  result = service.call
  expect(result).to be(true)
end
----

==== `EnforcedStyle: always_allow` (default)

[source,ruby]
----
# 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`

[source,ruby]
----
# bad
it('') { is_expected.to be_good }
it do
  result = service.call
  expect(result).to be(true)
end

# good
it { is_expected.to be_good }
----

==== `EnforcedStyle: disallow`

[source,ruby]
----
# bad
it { is_expected.to be_good }
it do
  result = service.call
  expect(result).to be(true)
end
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| EnforcedStyle
| `always_allow`
| `always_allow`, `single_line_only`, `disallow`
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleWithoutDescription

== RSpec/ExampleWording

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 1.0
| 2.13
|===

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

[source,ruby]
----
# bad
it 'should find nothing' do
end

it 'will find nothing' do
end

# good
it 'finds nothing' do
end
----

[source,ruby]
----
# bad
it 'it does things' do
end

# good
it 'does things' do
end
----

==== `DisallowedExamples: ['works']` (default)

[source,ruby]
----
# bad
it 'works' do
end

# good
it 'marks the task as done' do
end
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| CustomTransform
| `{"be"=>"is", "BE"=>"IS", "have"=>"has", "HAVE"=>"HAS"}`
| 

| IgnoredWords
| `[]`
| Array

| DisallowedExamples
| `works`
| Array
|===

=== References

* https://rspec.rubystyle.guide/#should-in-example-docstrings
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleWording
* http://betterspecs.org/#should

== RSpec/ExcessiveDocstringSpacing

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 2.5
| -
|===

Checks for excessive whitespace in example descriptions.

=== Examples

[source,ruby]
----
# bad
it '  has  excessive   spacing  ' do
end

# good
it 'has excessive spacing' do
end
----

[source,ruby]
----
# bad
context '  when a condition   is met  ' do
end

# good
context 'when a condition is met' do
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExcessiveDocstringSpacing

== RSpec/ExpectActual

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 1.7
| 2.23
|===

Checks for `expect(...)` calls containing literal values.

Autocorrection is performed when the expected is not a literal.

=== Examples

[source,ruby]
----
# 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

|===
| Name | Default value | Configurable values

| Exclude
| `+**/spec/routing/**/*+`
| Array
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectActual

== RSpec/ExpectChange

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always (Unsafe)
| 1.22
| 2.5
|===

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)

[source,ruby]
----
# 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 { user.reload.name }
----

==== `EnforcedStyle: block`

[source,ruby]
----
# bad
expect { run }.to change(Foo, :bar)

# good
expect { run }.to change { Foo.bar }
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| EnforcedStyle
| `method_call`
| `method_call`, `block`
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectChange

== RSpec/ExpectInHook

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.16
| -
|===

Do not use `expect` in hooks such as `before`.

=== Examples

[source,ruby]
----
# 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

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectInHook

== RSpec/ExpectInLet

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 2.30
| -
|===

Do not use `expect` in let.

=== Examples

[source,ruby]
----
# bad
let(:foo) do
  expect(something).to eq 'foo'
end

# good
it do
  expect(something).to eq 'foo'
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectInLet

== RSpec/ExpectOutput

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.10
| -
|===

Checks for opportunities to use `expect { ... }.to output`.

=== Examples

[source,ruby]
----
# 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

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectOutput

== RSpec/Focus

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Command-line only
| 1.5
| <<next>>
|===

Checks if examples are focused.

This cop does not support autocorrection in some cases.

=== Examples

[source,ruby]
----
# 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

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Focus

== RSpec/HookArgument

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 1.7
| -
|===

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)

[source,ruby]
----
# bad
before(:each) do
  # ...
end

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

# good
before do
  # ...
end
----

==== `EnforcedStyle: each`

[source,ruby]
----
# bad
before(:example) do
  # ...
end

# bad
before do
  # ...
end

# good
before(:each) do
  # ...
end
----

==== `EnforcedStyle: example`

[source,ruby]
----
# bad
before(:each) do
  # ...
end

# bad
before do
  # ...
end

# good
before(:example) do
  # ...
end
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| EnforcedStyle
| `implicit`
| `implicit`, `each`, `example`
|===

=== References

* https://rspec.rubystyle.guide/#redundant-beforeeach
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/HookArgument

== RSpec/HooksBeforeExamples

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Command-line only
| 1.29
| <<next>>
|===

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

=== Examples

[source,ruby]
----
# 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

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/HooksBeforeExamples

== RSpec/IdenticalEqualityAssertion

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 2.4
| -
|===

Checks for equality assertions with identical expressions on both sides.

=== Examples

[source,ruby]
----
# 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

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IdenticalEqualityAssertion

== RSpec/ImplicitBlockExpectation

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.35
| -
|===

Check that implicit block expectation syntax is not used.

Prefer using explicit block expectations.

=== Examples

[source,ruby]
----
# 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

* https://rspec.rubystyle.guide/#implicit-block-expectations
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ImplicitBlockExpectation

== RSpec/ImplicitExpect

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 1.8
| -
|===

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)

[source,ruby]
----
# bad
it { should be_truthy }

# good
it { is_expected.to be_truthy }
----

==== `EnforcedStyle: should`

[source,ruby]
----
# bad
it { is_expected.to be_truthy }

# good
it { should be_truthy }
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| EnforcedStyle
| `is_expected`
| `is_expected`, `should`
|===

=== References

* https://rspec.rubystyle.guide/#use-expect
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ImplicitExpect

== RSpec/ImplicitSubject

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 1.29
| 2.13
|===

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

This cop can be configured using the `EnforcedStyle` option

=== Examples

==== `EnforcedStyle: single_line_only` (default)

[source,ruby]
----
# 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`

[source,ruby]
----
# 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`

[source,ruby]
----
# bad
it { is_expected.to be_truthy }

# good
it { expect(subject).to be_truthy }
----

==== `EnforcedStyle: require_implicit`

[source,ruby]
----
# 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 { expect(named_subject).to be_truthy }
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| EnforcedStyle
| `single_line_only`
| `single_line_only`, `single_statement_only`, `disallow`, `require_implicit`
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ImplicitSubject

== RSpec/IndexedLet

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 2.20
| 2.23
|===

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)`

[source,ruby]
----
# 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) { create(:item, visible: false) }
----

==== `Max: 2`

[source,ruby]
----
# 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) { create(:item) }
----

==== `AllowedIdentifiers: ['item_1', 'item_2']`

[source,ruby]
----
# good
let(:item_1) { create(:item) }
let(:item_2) { create(:item) }
----

==== `AllowedPatterns: ['item']`

[source,ruby]
----
# good
let(:item_1) { create(:item) }
let(:item_2) { create(:item) }
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| Max
| `1`
| Integer

| AllowedIdentifiers
| `[]`
| Array

| AllowedPatterns
| `[]`
| Array
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IndexedLet

== RSpec/InstanceSpy

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 1.12
| -
|===

Checks for `instance_double` used with `have_received`.

=== Examples

[source,ruby]
----
# 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

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/InstanceSpy

== RSpec/InstanceVariable

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.0
| 1.7
|===

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

[source,ruby]
----
# 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

[source,ruby]
----
# 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

|===
| Name | Default value | Configurable values

| AssignmentOnly
| `false`
| Boolean
|===

=== References

* https://rspec.rubystyle.guide/#instance-variables
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/InstanceVariable

== RSpec/IsExpectedSpecify

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 2.27
| -
|===

Check for `specify` with `is_expected` and one-liner expectations.

=== Examples

[source,ruby]
----
# bad
specify { is_expected.to be_truthy }

# good
it { is_expected.to be_truthy }

# good
specify do
  # ...
end
specify { expect(sqrt(4)).to eq(2) }
----

=== References

* https://rspec.rubystyle.guide/#it-and-specify
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IsExpectedSpecify

== RSpec/ItBehavesLike

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 1.13
| -
|===

Checks that only one `it_behaves_like` style is used.

=== Examples

==== `EnforcedStyle: it_behaves_like` (default)

[source,ruby]
----
# bad
it_should_behave_like 'a foo'

# good
it_behaves_like 'a foo'
----

==== `EnforcedStyle: it_should_behave_like`

[source,ruby]
----
# bad
it_behaves_like 'a foo'

# good
it_should_behave_like 'a foo'
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| EnforcedStyle
| `it_behaves_like`
| `it_behaves_like`, `it_should_behave_like`
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ItBehavesLike

== RSpec/IteratedExpectation

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.14
| -
|===

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

=== Examples

[source,ruby]
----
# 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

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IteratedExpectation

== RSpec/LeadingSubject

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 1.7
| 1.14
|===

Enforce that subject is the first definition in the test.

=== Examples

[source,ruby]
----
# 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 { expect_something_else }
----

=== References

* https://rspec.rubystyle.guide/#leading-subject
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LeadingSubject

== RSpec/LeakyConstantDeclaration

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.35
| -
|===

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

[source,ruby]
----
# 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
----

[source,ruby]
----
# 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
----

[source,ruby]
----
# 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

* https://rspec.rubystyle.guide/#declare-constants
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LeakyConstantDeclaration
* https://rspec.info/features/3-12/rspec-mocks/mutating-constants

== RSpec/LetBeforeExamples

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Command-line only
| 1.16
| <<next>>
|===

Checks for `let` definitions that come after an example.

=== Examples

[source,ruby]
----
# bad
let(:foo) { bar }

it 'checks what foo does' do
  expect(foo).to be
end

let(:some) { other }

it 'checks what some does' do
  expect(some).to be
end

# good
let(:foo) { bar }
let(:some) { other }

it 'checks what foo does' do
  expect(foo).to be
end

it 'checks what some does' do
  expect(some).to be
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LetBeforeExamples

== RSpec/LetSetup

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.7
| -
|===

Checks unreferenced `let!` calls being used for test setup.

=== Examples

[source,ruby]
----
# bad
let!(:my_widget) { create(:widget) }

it 'counts widgets' do
  expect(Widget.count).to eq(1)
end

# good
it 'counts widgets' do
  create(:widget)
  expect(Widget.count).to eq(1)
end

# good
before { create(:widget) }

it 'counts widgets' do
  expect(Widget.count).to eq(1)
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LetSetup

== RSpec/MatchArray

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 2.19
| -
|===

Checks where `match_array` is used.

This cop checks for the following:
- Prefer `contain_exactly` when matching an array with values.
- Prefer `eq` when using `match_array` with an empty array literal.

=== Examples

[source,ruby]
----
# bad
it { is_expected.to match_array([content1, content2]) }

# good
it { is_expected.to contain_exactly(content1, content2) }

# good
it { is_expected.to match_array([content] + array) }

# good
it { is_expected.to match_array(%w(tremble in fear foolish mortals)) }
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MatchArray

== RSpec/MessageChain

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.7
| -
|===

Check that chains of messages are not being stubbed.

=== Examples

[source,ruby]
----
# bad
allow(foo).to receive_message_chain(:bar, :baz).and_return(42)

# good
thing = Thing.new(baz: 42)
allow(foo).to receive(:bar).and_return(thing)
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MessageChain

== RSpec/MessageExpectation

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Disabled
| Yes
| No
| 1.7
| 1.8
|===

Checks for consistent message expectation style.

This cop can be configured in your configuration using the
`EnforcedStyle` option and supports `--auto-gen-config`.

=== Examples

==== `EnforcedStyle: allow` (default)

[source,ruby]
----
# bad
expect(foo).to receive(:bar)

# good
allow(foo).to receive(:bar)
----

==== `EnforcedStyle: expect`

[source,ruby]
----
# bad
allow(foo).to receive(:bar)

# good
expect(foo).to receive(:bar)
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| EnforcedStyle
| `allow`
| `allow`, `expect`
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MessageExpectation

== RSpec/MessageSpies

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.9
| -
|===

Checks that message expectations are set using spies.

This cop can be configured in your configuration using the
`EnforcedStyle` option and supports `--auto-gen-config`.

=== Examples

==== `EnforcedStyle: have_received` (default)

[source,ruby]
----
# bad
expect(foo).to receive(:bar)
do_something

# good
allow(foo).to receive(:bar) # or use instance_spy
do_something
expect(foo).to have_received(:bar)
----

==== `EnforcedStyle: receive`

[source,ruby]
----
# bad
allow(foo).to receive(:bar)
do_something
expect(foo).to have_received(:bar)

# good
expect(foo).to receive(:bar)
do_something
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| EnforcedStyle
| `have_received`
| `have_received`, `receive`
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MessageSpies

== RSpec/MetadataStyle

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 2.24
| -
|===

Use consistent metadata style.

This cop does not support autocorrection in the case of
`EnforcedStyle: hash` where the trailing metadata type is ambiguous.
(e.g. `describe 'Something', :a, b`)

=== Examples

==== EnforcedStyle: symbol (default)

[source,ruby]
----
# bad
describe 'Something', a: true

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

==== EnforcedStyle: hash

[source,ruby]
----
# bad
describe 'Something', :a

# good
describe 'Something', a: true
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| EnforcedStyle
| `symbol`
| `hash`, `symbol`
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MetadataStyle

== RSpec/MissingExampleGroupArgument

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.28
| -
|===

Checks that the first argument to an example group is not empty.

=== Examples

[source,ruby]
----
# bad
describe do
end

RSpec.describe do
end

# good
describe TestedClass do
end

describe "A feature example" do
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MissingExampleGroupArgument

== RSpec/MultipleDescribes

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.0
| -
|===

Checks for multiple top-level example groups.

Multiple descriptions for the same class or module should either
be nested or separated into different test files.

=== Examples

[source,ruby]
----
# bad
describe MyClass, '.do_something' do
end
describe MyClass, '.do_something_else' do
end

# good
describe MyClass do
  describe '.do_something' do
  end
  describe '.do_something_else' do
  end
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleDescribes

== RSpec/MultipleExpectations

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.7
| 1.21
|===

Checks if examples contain too many `expect` calls.

This cop is configurable using the `Max` option
and works with `--auto-gen-config`.

=== Examples

[source,ruby]
----
# bad
describe UserCreator do
  it 'builds a user' do
    expect(user.name).to eq("John")
    expect(user.age).to eq(22)
  end
end

# good
describe UserCreator do
  it 'sets the users name' do
    expect(user.name).to eq("John")
  end

  it 'sets the users age' do
    expect(user.age).to eq(22)
  end
end
----

==== `aggregate_failures: true` (default)

[source,ruby]
----
# good - the cop ignores when RSpec aggregates failures
describe UserCreator do
  it 'builds a user', :aggregate_failures do
    expect(user.name).to eq("John")
    expect(user.age).to eq(22)
  end
end
----

==== `aggregate_failures: false`

[source,ruby]
----
# Detected as an offense
describe UserCreator do
  it 'builds a user', aggregate_failures: false do
    expect(user.name).to eq("John")
    expect(user.age).to eq(22)
  end
end
----

==== `Max: 1` (default)

[source,ruby]
----
# bad
describe UserCreator do
  it 'builds a user' do
    expect(user.name).to eq("John")
    expect(user.age).to eq(22)
  end
end
----

==== `Max: 2`

[source,ruby]
----
# good
describe UserCreator do
  it 'builds a user' do
    expect(user.name).to eq("John")
    expect(user.age).to eq(22)
  end
end
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| Max
| `1`
| Integer
|===

=== References

* https://rspec.rubystyle.guide/#expectation-per-example
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleExpectations
* http://betterspecs.org/#single

== RSpec/MultipleMemoizedHelpers

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.43
| -
|===

Checks if example groups contain too many `let` and `subject` calls.

This cop is configurable using the `Max` option and the `AllowSubject`
which will configure the cop to only register offenses on calls to
`let` and not calls to `subject`.

=== Examples

[source,ruby]
----
# bad
describe MyClass do
  let(:foo) { [] }
  let(:bar) { [] }
  let!(:baz) { [] }
  let(:qux) { [] }
  let(:quux) { [] }
  let(:quuz) { {} }
end

describe MyClass do
  let(:foo) { [] }
  let(:bar) { [] }
  let!(:baz) { [] }

  context 'when stuff' do
    let(:qux) { [] }
    let(:quux) { [] }
    let(:quuz) { {} }
  end
end

# good
describe MyClass do
  let(:bar) { [] }
  let!(:baz) { [] }
  let(:qux) { [] }
  let(:quux) { [] }
  let(:quuz) { {} }
end

describe MyClass do
  context 'when stuff' do
    let(:foo) { [] }
    let(:bar) { [] }
    let!(:booger) { [] }
  end

  context 'when other stuff' do
    let(:qux) { [] }
    let(:quux) { [] }
    let(:quuz) { {} }
  end
end
----

==== when disabling AllowSubject configuration

[source,ruby]
----
# rubocop.yml
# RSpec/MultipleMemoizedHelpers:
#   AllowSubject: false

# bad - `subject` counts towards memoized helpers
describe MyClass do
  subject { {} }
  let(:foo) { [] }
  let(:bar) { [] }
  let!(:baz) { [] }
  let(:qux) { [] }
  let(:quux) { [] }
end
----

==== with Max configuration

[source,ruby]
----
# rubocop.yml
# RSpec/MultipleMemoizedHelpers:
#   Max: 1

# bad
describe MyClass do
  let(:foo) { [] }
  let(:bar) { [] }
end
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowSubject
| `true`
| Boolean

| Max
| `5`
| Integer
|===

=== References

* https://rspec.rubystyle.guide/#let-blocks
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleMemoizedHelpers

== RSpec/MultipleSubjects

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 1.16
| -
|===

Checks if an example group defines `subject` multiple times.

This cop does not support autocorrection in some cases.
The autocorrect behavior for this cop depends on the type of
duplication:

  - If multiple named subjects are defined then this probably indicates
    that the overwritten subjects (all subjects except the last
    definition) are effectively being used to define helpers. In this
    case they are replaced with `let`.

  - If multiple unnamed subjects are defined though then this can *only*
    be dead code and we remove the overwritten subject definitions.

  - If subjects are defined with `subject!` then we don't autocorrect.
    This is enough of an edge case that people can just move this to
    a `before` hook on their own

=== Examples

[source,ruby]
----
# bad
describe Foo do
  subject(:user) { User.new }
  subject(:post) { Post.new }
end

# good
describe Foo do
  let(:user) { User.new }
  subject(:post) { Post.new }
end

# bad (does not support autocorrection)
describe Foo do
  subject!(:user) { User.new }
  subject!(:post) { Post.new }
end

# good
describe Foo do
  before do
    User.new
    Post.new
  end
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleSubjects

== RSpec/NamedSubject

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.5.3
| 2.15
|===

Checks for explicitly referenced test subjects.

RSpec lets you declare an "implicit subject" using `subject { ... }`
which allows for tests like `it { is_expected.to be_valid }`.
If you need to reference your test subject you should explicitly
name it using `subject(:your_subject_name) { ... }`. Your test subjects
should be the most important object in your tests so they deserve
a descriptive name.

This cop can be configured in your configuration using `EnforcedStyle`,
and `IgnoreSharedExamples` which will not report offenses for implicit
subjects in shared example groups.

=== Examples

==== `EnforcedStyle: always` (default)

[source,ruby]
----
# bad
RSpec.describe User do
  subject { described_class.new }

  it 'is valid' do
    expect(subject.valid?).to be(true)
  end
end

# good
RSpec.describe User do
  subject(:user) { described_class.new }

  it 'is valid' do
    expect(user.valid?).to be(true)
  end
end

# also good
RSpec.describe User do
  subject(:user) { described_class.new }

  it { is_expected.to be_valid }
end
----

==== `EnforcedStyle: named_only`

[source,ruby]
----
# bad
RSpec.describe User do
  subject(:user) { described_class.new }

  it 'is valid' do
    expect(subject.valid?).to be(true)
  end
end

# good
RSpec.describe User do
  subject(:user) { described_class.new }

  it 'is valid' do
    expect(user.valid?).to be(true)
  end
end

# also good
RSpec.describe User do
  subject { described_class.new }

  it { is_expected.to be_valid }
end

# acceptable
RSpec.describe User do
  subject { described_class.new }

  it 'is valid' do
    expect(subject.valid?).to be(true)
  end
end
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| EnforcedStyle
| `always`
| `always`, `named_only`

| IgnoreSharedExamples
| `true`
| Boolean
|===

=== References

* https://rspec.rubystyle.guide/#use-subject
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NamedSubject

== RSpec/NestedGroups

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.7
| 2.13
|===

Checks for nested example groups.

This cop is configurable using the `Max` option
and supports `--auto-gen-config`.

=== Examples

[source,ruby]
----
# bad
context 'when using some feature' do
  let(:some)    { :various }
  let(:feature) { :setup   }

  context 'when user is signed in' do  # flagged by rubocop
    let(:user) do
      UserCreate.call(user_attributes)
    end

    let(:user_attributes) do
      {
        name: 'John',
        age:  22,
        role: role
      }
    end

    context 'when user is an admin' do # flagged by rubocop
      let(:role) { 'admin' }

      it 'blah blah'
      it 'yada yada'
    end
  end
end

# good
context 'using some feature as an admin' do
  let(:some)    { :various }
  let(:feature) { :setup   }

  let(:user) do
    UserCreate.call(
      name: 'John',
      age:  22,
      role: 'admin'
    )
  end

  it 'blah blah'
  it 'yada yada'
end
----

==== `Max: 3` (default)

[source,ruby]
----
# bad
describe Foo do
  context 'foo' do
    context 'bar' do
      context 'baz' do # flagged by rubocop
      end
    end
  end
end
----

==== `Max: 2`

[source,ruby]
----
# bad
describe Foo do
  context 'foo' do
    context 'bar' do # flagged by rubocop
      context 'baz' do # flagged by rubocop
      end
    end
  end
end
----

==== `AllowedGroups: [] (default)`

[source,ruby]
----
describe Foo do # <-- nested groups 1
  context 'foo' do # <-- nested groups 2
    context 'bar' do # <-- nested groups 3
    end
  end
end
----

==== `AllowedGroups: [path]`

[source,ruby]
----
describe Foo do # <-- nested groups 1
  path '/foo' do # <-- nested groups 1 (not counted)
    context 'bar' do # <-- nested groups 2
    end
  end
end
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| Max
| `3`
| Integer

| AllowedGroups
| `[]`
| Array
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NestedGroups

== RSpec/NoExpectationExample

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| No
| No
| 2.13
| 2.14
|===

Checks if an example contains any expectation.

All RSpec's example and expectation methods are covered by default.
If you are using your own custom methods,
add the following configuration:

  RSpec:
    Language:
      Examples:
        Regular:
          - custom_it
      Expectations:
        - custom_expect

This cop can be customized with an allowed expectation methods pattern
with an `AllowedPatterns` option. ^expect_ and ^assert_ are allowed
by default.

=== Examples

[source,ruby]
----
# bad
it do
  a?
end

# good
it do
  expect(a?).to be(true)
end
----

==== `AllowedPatterns` configuration

[source,ruby]
----
# .rubocop.yml
# RSpec/NoExpectationExample:
#   AllowedPatterns:
#     - ^expect_
#     - ^assert_
----

[source,ruby]
----
# bad
it do
  not_expect_something
end

# good
it do
  expect_something
end

it do
  assert_something
end
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowedPatterns
| `^expect_`, `^assert_`
| Array
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NoExpectationExample

== RSpec/NotToNot

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 1.4
| -
|===

Checks for consistent method usage for negating expectations.

=== Examples

==== `EnforcedStyle: not_to` (default)

[source,ruby]
----
# bad
it '...' do
  expect(false).to_not be_true
end

# good
it '...' do
  expect(false).not_to be_true
end
----

==== `EnforcedStyle: to_not`

[source,ruby]
----
# bad
it '...' do
  expect(false).not_to be_true
end

# good
it '...' do
  expect(false).to_not be_true
end
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| EnforcedStyle
| `not_to`
| `not_to`, `to_not`
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NotToNot

== RSpec/OverwritingSetup

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.14
| -
|===

Checks if there is a let/subject that overwrites an existing one.

=== Examples

[source,ruby]
----
# bad
let(:foo) { bar }
let(:foo) { baz }

subject(:foo) { bar }
let(:foo) { baz }

let(:foo) { bar }
let!(:foo) { baz }

# good
subject(:test) { something }
let(:foo) { bar }
let(:baz) { baz }
let!(:other) { other }
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/OverwritingSetup

== RSpec/Pending

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Disabled
| Yes
| No
| 1.25
| -
|===

Checks for any pending or skipped examples.

=== Examples

[source,ruby]
----
# bad
describe MyClass do
  it "should be true"
end

describe MyClass do
  it "should be true", skip: true do
    expect(1).to eq(2)
  end
end

describe MyClass do
  it "should be true" do
    pending
  end
end

describe MyClass do
  xit "should be true" do
  end
end

# good
describe MyClass do
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Pending

== RSpec/PendingWithoutReason

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 2.16
| -
|===

Checks for pending or skipped examples without reason.

=== Examples

[source,ruby]
----
# bad
pending 'does something' do
end

# bad
it 'does something', :pending do
end

# bad
it 'does something' do
  pending
end

# bad
xdescribe 'something' do
end

# bad
skip 'does something' do
end

# bad
it 'does something', :skip do
end

# bad
it 'does something' do
  skip
end

# bad
it 'does something'

# good
it 'does something' do
  pending 'reason'
end

# good
it 'does something' do
  skip 'reason'
end

# good
it 'does something', pending: 'reason' do
end

# good
it 'does something', skip: 'reason' do
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/PendingWithoutReason

== RSpec/PredicateMatcher

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always (Unsafe)
| 1.16
| -
|===

Prefer using predicate matcher over using predicate method directly.

RSpec defines magic matchers for predicate methods.
This cop recommends to use the predicate matcher instead of using
predicate method directly.

=== Examples

==== Strict: true, EnforcedStyle: inflected (default)

[source,ruby]
----
# bad
expect(foo.something?).to be_truthy

# good
expect(foo).to be_something

# also good - It checks "true" strictly.
expect(foo.something?).to be(true)
----

==== Strict: false, EnforcedStyle: inflected

[source,ruby]
----
# bad
expect(foo.something?).to be_truthy
expect(foo.something?).to be(true)

# good
expect(foo).to be_something
----

==== Strict: true, EnforcedStyle: explicit

[source,ruby]
----
# bad
expect(foo).to be_something

# good - the above code is rewritten to it by this cop
expect(foo.something?).to be(true)

# bad - no autocorrect
expect(foo)
  .to be_something(<<~TEXT)
    bar
  TEXT

# good
expect(foo.something?(<<~TEXT)).to be(true)
  bar
TEXT
----

==== Strict: false, EnforcedStyle: explicit

[source,ruby]
----
# bad
expect(foo).to be_something

# good - the above code is rewritten to it by this cop
expect(foo.something?).to be_truthy
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| Strict
| `true`
| Boolean

| EnforcedStyle
| `inflected`
| `inflected`, `explicit`

| AllowedExplicitMatchers
| `[]`
| Array
|===

=== References

* https://rspec.rubystyle.guide/#predicate-matchers
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/PredicateMatcher

== RSpec/ReceiveCounts

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 1.26
| -
|===

Check for `once` and `twice` receive counts matchers usage.

=== Examples

[source,ruby]
----
# bad
expect(foo).to receive(:bar).exactly(1).times
expect(foo).to receive(:bar).exactly(2).times
expect(foo).to receive(:bar).at_least(1).times
expect(foo).to receive(:bar).at_least(2).times
expect(foo).to receive(:bar).at_most(1).times
expect(foo).to receive(:bar).at_most(2).times

# good
expect(foo).to receive(:bar).once
expect(foo).to receive(:bar).twice
expect(foo).to receive(:bar).at_least(:once)
expect(foo).to receive(:bar).at_least(:twice)
expect(foo).to receive(:bar).at_most(:once)
expect(foo).to receive(:bar).at_most(:twice).times
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReceiveCounts

== RSpec/ReceiveMessages

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always (Unsafe)
| 2.23
| -
|===

Checks for multiple messages stubbed on the same object.

=== Safety

The autocorrection is marked as unsafe, because it may change the
order of stubs. This in turn may cause e.g. variables to be called
before they are defined.

=== Examples

[source,ruby]
----
# bad
before do
  allow(Service).to receive(:foo).and_return(bar)
  allow(Service).to receive(:baz).and_return(qux)
end

# good
before do
  allow(Service).to receive_messages(foo: bar, baz: qux)
end

# good - ignore same message
before do
  allow(Service).to receive(:foo).and_return(bar)
  allow(Service).to receive(:foo).and_return(qux)
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReceiveMessages

== RSpec/ReceiveNever

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 1.28
| -
|===

Prefer `not_to receive(...)` over `receive(...).never`.

=== Examples

[source,ruby]
----
# bad
expect(foo).to receive(:bar).never

# good
expect(foo).not_to receive(:bar)
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReceiveNever

== RSpec/RedundantAround

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 2.19
| -
|===

Remove redundant `around` hook.

=== Examples

[source,ruby]
----
# bad
around do |example|
  example.run
end

# good
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RedundantAround

== RSpec/RedundantPredicateMatcher

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 2.26
| -
|===

Checks for redundant predicate matcher.

=== Examples

[source,ruby]
----
# bad
expect(foo).to be_exist(bar)
expect(foo).not_to be_include(bar)
expect(foo).to be_all(bar)

# good
expect(foo).to exist(bar)
expect(foo).not_to include(bar)
expect(foo).to all be(bar)
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RedundantPredicateMatcher

== RSpec/RemoveConst

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 2.26
| -
|===

Checks that `remove_const` is not used in specs.

=== Examples

[source,ruby]
----
# bad
it 'does something' do
  Object.send(:remove_const, :SomeConstant)
end

before do
  SomeClass.send(:remove_const, :SomeConstant)
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RemoveConst

== RSpec/RepeatedDescription

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.9
| -
|===

Check for repeated description strings in example groups.

=== Examples

[source,ruby]
----
# bad
RSpec.describe User do
  it 'is valid' do
    # ...
  end

  it 'is valid' do
    # ...
  end
end

# good
RSpec.describe User do
  it 'is valid when first and last name are present' do
    # ...
  end

  it 'is valid when last name only is present' do
    # ...
  end
end

# good
RSpec.describe User do
  it 'is valid' do
    # ...
  end

  it 'is valid', :flag do
    # ...
  end
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedDescription

== RSpec/RepeatedExample

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.10
| -
|===

Check for repeated examples within example groups.

=== Examples

[source,ruby]
----
it 'is valid' do
  expect(user).to be_valid
end

it 'validates the user' do
  expect(user).to be_valid
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedExample

== RSpec/RepeatedExampleGroupBody

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.38
| -
|===

Check for repeated describe and context block body.

=== Examples

[source,ruby]
----
# bad
describe 'cool feature x' do
  it { cool_predicate }
end

describe 'cool feature y' do
  it { cool_predicate }
end

# good
describe 'cool feature' do
  it { cool_predicate }
end

describe 'another cool feature' do
  it { another_predicate }
end

# good
context 'when case x', :tag do
  it { cool_predicate }
end

context 'when case y' do
  it { cool_predicate }
end

# good
context Array do
  it { is_expected.to respond_to :each }
end

context Hash do
  it { is_expected.to respond_to :each }
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedExampleGroupBody

== RSpec/RepeatedExampleGroupDescription

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.38
| -
|===

Check for repeated example group descriptions.

=== Examples

[source,ruby]
----
# bad
describe 'cool feature' do
  # example group
end

describe 'cool feature' do
  # example group
end

# bad
context 'when case x' do
  # example group
end

describe 'when case x' do
  # example group
end

# good
describe 'cool feature' do
  # example group
end

describe 'another cool feature' do
  # example group
end

# good
context 'when case x' do
  # example group
end

context 'when another case' do
  # example group
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedExampleGroupDescription

== RSpec/RepeatedIncludeExample

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.44
| -
|===

Check for repeated include of shared examples.

=== Examples

[source,ruby]
----
# bad
describe 'foo' do
  include_examples 'cool stuff'
  include_examples 'cool stuff'
end

# bad
describe 'foo' do
  it_behaves_like 'a cool', 'thing'
  it_behaves_like 'a cool', 'thing'
end

# bad
context 'foo' do
  it_should_behave_like 'a duck'
  it_should_behave_like 'a duck'
end

# good
describe 'foo' do
  include_examples 'cool stuff'
end

describe 'bar' do
  include_examples 'cool stuff'
end

# good
describe 'foo' do
  it_behaves_like 'a cool', 'thing'
  it_behaves_like 'a cool', 'person'
end

# good
context 'foo' do
  it_should_behave_like 'a duck'
  it_should_behave_like 'a goose'
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedIncludeExample

== RSpec/RepeatedSubjectCall

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 2.27
| -
|===

Checks for repeated calls to subject missing that it is memoized.

=== Examples

[source,ruby]
----
# bad
it do
  subject
  expect { subject }.to not_change { A.count }
end

it do
  expect { subject }.to change { A.count }
  expect { subject }.to not_change { A.count }
end

# good
it do
  expect { my_method }.to change { A.count }
  expect { my_method }.to not_change { A.count }
end

# also good
it do
  expect { subject.a }.to change { A.count }
  expect { subject.b }.to not_change { A.count }
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedSubjectCall

== RSpec/ReturnFromStub

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 1.16
| 1.22
|===

Checks for consistent style of stub's return setting.

Enforces either `and_return` or block-style return in the cases
where the returned value is constant. Ignores dynamic returned values
are the result would be different

This cop can be configured using the `EnforcedStyle` option

=== Examples

==== `EnforcedStyle: and_return` (default)

[source,ruby]
----
# bad
allow(Foo).to receive(:bar) { "baz" }
expect(Foo).to receive(:bar) { "baz" }

# good
allow(Foo).to receive(:bar).and_return("baz")
expect(Foo).to receive(:bar).and_return("baz")
# also good as the returned value is dynamic
allow(Foo).to receive(:bar) { bar.baz }
----

==== `EnforcedStyle: block`

[source,ruby]
----
# bad
allow(Foo).to receive(:bar).and_return("baz")
expect(Foo).to receive(:bar).and_return("baz")

# good
allow(Foo).to receive(:bar) { "baz" }
expect(Foo).to receive(:bar) { "baz" }
# also good as the returned value is dynamic
allow(Foo).to receive(:bar).and_return(bar.baz)
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| EnforcedStyle
| `and_return`
| `and_return`, `block`
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReturnFromStub

== RSpec/ScatteredLet

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Command-line only
| 1.14
| <<next>>
|===

Checks for let scattered across the example group.

Group lets together

=== Examples

[source,ruby]
----
# bad
describe Foo do
  let(:foo) { 1 }
  subject { Foo }
  let(:bar) { 2 }
  before { prepare }
  let!(:baz) { 3 }
end

# good
describe Foo do
  subject { Foo }
  before { prepare }
  let(:foo) { 1 }
  let(:bar) { 2 }
  let!(:baz) { 3 }
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ScatteredLet

== RSpec/ScatteredSetup

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Command-line only
| 1.10
| <<next>>
|===

Checks for setup scattered across multiple hooks in an example group.

Unify `before`, `after`, and `around` hooks when possible.

=== Examples

[source,ruby]
----
# bad
describe Foo do
  before { setup1 }
  before { setup2 }
end

# good
describe Foo do
  before do
    setup1
    setup2
  end
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ScatteredSetup

== RSpec/SharedContext

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 1.13
| -
|===

Checks for proper shared_context and shared_examples usage.

If there are no examples defined, use shared_context.
If there is no setup defined, use shared_examples.

=== Examples

[source,ruby]
----
# bad
RSpec.shared_context 'only examples here' do
  it 'does x' do
  end

  it 'does y' do
  end
end

# good
RSpec.shared_examples 'only examples here' do
  it 'does x' do
  end

  it 'does y' do
  end
end
----

[source,ruby]
----
# bad
RSpec.shared_examples 'only setup here' do
  subject(:foo) { :bar }

  let(:baz) { :bazz }

  before do
    something
  end
end

# good
RSpec.shared_context 'only setup here' do
  subject(:foo) { :bar }

  let(:baz) { :bazz }

  before do
    something
  end
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SharedContext

== RSpec/SharedExamples

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 1.25
| 2.26
|===

Checks for consistent style for shared example names.

Enforces either `string` or `symbol` for shared example names.

This cop can be configured using the `EnforcedStyle` option

=== Examples

==== `EnforcedStyle: string` (default)

[source,ruby]
----
# bad
it_behaves_like :foo_bar_baz
it_should_behave_like :foo_bar_baz
shared_examples :foo_bar_baz
shared_examples_for :foo_bar_baz
include_examples :foo_bar_baz

# good
it_behaves_like 'foo bar baz'
it_should_behave_like 'foo bar baz'
shared_examples 'foo bar baz'
shared_examples_for 'foo bar baz'
include_examples 'foo bar baz'
----

==== `EnforcedStyle: symbol`

[source,ruby]
----
# bad
it_behaves_like 'foo bar baz'
it_should_behave_like 'foo bar baz'
shared_examples 'foo bar baz'
shared_examples_for 'foo bar baz'
include_examples 'foo bar baz'

# good
it_behaves_like :foo_bar_baz
it_should_behave_like :foo_bar_baz
shared_examples :foo_bar_baz
shared_examples_for :foo_bar_baz
include_examples :foo_bar_baz
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| EnforcedStyle
| `string`
| `string`, `symbol`
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SharedExamples

== RSpec/SingleArgumentMessageChain

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 1.9
| 1.10
|===

Checks that chains of messages contain more than one element.

=== Examples

[source,ruby]
----
# bad
allow(foo).to receive_message_chain(:bar).and_return(42)

# good
allow(foo).to receive(:bar).and_return(42)

# also good
allow(foo).to receive(:bar, :baz)
allow(foo).to receive("bar.baz")
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SingleArgumentMessageChain

== RSpec/SkipBlockInsideExample

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 2.19
| -
|===

Checks for passing a block to `skip` within examples.

=== Examples

[source,ruby]
----
# bad
it 'does something' do
  skip 'not yet implemented' do
    do_something
  end
end

# good
it 'does something' do
  skip 'not yet implemented'
  do_something
end

# good - when outside example
skip 'not yet implemented' do
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SkipBlockInsideExample

== RSpec/SortMetadata

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 2.14
| -
|===

Sort RSpec metadata alphabetically.

=== Examples

[source,ruby]
----
# bad
describe 'Something', :b, :a
context 'Something', foo: 'bar', baz: true
it 'works', :b, :a, foo: 'bar', baz: true

# good
describe 'Something', :a, :b
context 'Something', baz: true, foo: 'bar'
it 'works', :a, :b, baz: true, foo: 'bar'
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SortMetadata

== RSpec/SpecFilePathFormat

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 2.24
| -
|===

Checks that spec file paths are consistent and well-formed.

=== Examples

[source,ruby]
----
# bad
whatever_spec.rb         # describe MyClass
my_class_spec.rb         # describe MyClass, '#method'

# good
my_class_spec.rb         # describe MyClass
my_class_method_spec.rb  # describe MyClass, '#method'
my_class/method_spec.rb  # describe MyClass, '#method'
----

==== `CustomTransform: {RuboCop=>rubocop, RSpec=>rspec}` (default)

[source,ruby]
----
# good
rubocop_spec.rb          # describe RuboCop
rspec_spec.rb            # describe RSpec
----

==== `IgnoreMethods: false` (default)

[source,ruby]
----
# bad
my_class_spec.rb         # describe MyClass, '#method'
----

==== `IgnoreMethods: true`

[source,ruby]
----
# good
my_class_spec.rb         # describe MyClass, '#method'
----

==== `IgnoreMetadata: {type=>routing}` (default)

[source,ruby]
----
# good
whatever_spec.rb         # describe MyClass, type: :routing do; end
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| Include
| `+**/*_spec.rb+`
| Array

| Exclude
| `+**/spec/routing/**/*+`
| Array

| CustomTransform
| `{"RuboCop"=>"rubocop", "RSpec"=>"rspec"}`
| 

| IgnoreMethods
| `false`
| Boolean

| IgnoreMetadata
| `{"type"=>"routing"}`
| 
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SpecFilePathFormat

== RSpec/SpecFilePathSuffix

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 2.24
| -
|===

Checks that spec file paths suffix are consistent and well-formed.

=== Examples

[source,ruby]
----
# bad
my_class/foo_specorb.rb   # describe MyClass
spec/models/user.rb       # describe User
spec/models/user_specxrb  # describe User

# good
my_class_spec.rb          # describe MyClass

# good - shared examples are allowed
spec/models/user.rb       # shared_examples_for 'foo'
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| Include
| `+**/*_spec*rb*+`, `+**/spec/**/*+`
| Array
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SpecFilePathSuffix

== RSpec/StubbedMock

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.44
| -
|===

Checks that message expectations do not have a configured response.

=== Examples

[source,ruby]
----
# bad
expect(foo).to receive(:bar).with(42).and_return("hello world")

# good (without spies)
allow(foo).to receive(:bar).with(42).and_return("hello world")
expect(foo).to receive(:bar).with(42)
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/StubbedMock

== RSpec/SubjectDeclaration

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 2.5
| -
|===

Ensure that subject is defined using subject helper.

=== Examples

[source,ruby]
----
# bad
let(:subject) { foo }
let!(:subject) { foo }
subject(:subject) { foo }
subject!(:subject) { foo }

# bad
block = -> {}
let(:subject, &block)

# good
subject(:test_subject) { foo }
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SubjectDeclaration

== RSpec/SubjectStub

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.7
| 2.8
|===

Checks for stubbed test subjects.

Checks nested subject stubs for innermost subject definition
when subject is also defined in parent example groups.

=== Examples

[source,ruby]
----
# bad
describe Article do
  subject(:article) { Article.new }

  it 'indicates that the author is unknown' do
    allow(article).to receive(:author).and_return(nil)
    expect(article.description).to include('by an unknown author')
  end
end

# bad
describe Article do
  subject(:foo) { Article.new }

  context 'nested subject' do
    subject(:article) { Article.new }

    it 'indicates that the author is unknown' do
      allow(article).to receive(:author).and_return(nil)
      expect(article.description).to include('by an unknown author')
    end
  end
end

# good
describe Article do
  subject(:article) { Article.new(author: nil) }

  it 'indicates that the author is unknown' do
    expect(article.description).to include('by an unknown author')
  end
end
----

=== References

* https://rspec.rubystyle.guide/#dont-stub-subject
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SubjectStub
* https://robots.thoughtbot.com/don-t-stub-the-system-under-test
* https://penelope.zone/2015/12/27/introducing-rspec-smells-and-where-to-find-them.html#smell-1-stubjec

== RSpec/UndescriptiveLiteralsDescription

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 2.29
| -
|===

Description should be descriptive.

If example group or example contains only `execute string`, numbers
and regular expressions, the description is not clear.

=== Examples

[source,ruby]
----
# bad
describe `time` do
 # ...
end

# bad
context /when foo/ do
  # ...
end

# bad
it 10000 do
  # ...
end

# good
describe Foo do
  # ...
end

# good
describe '#foo' do
  # ...
end

# good
context "when #{foo} is bar" do
  # ...
end

# good
it 'does something' do
  # ...
end
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/UndescriptiveLiteralsDescription

== RSpec/UnspecifiedException

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.30
| -
|===

Checks for a specified error in checking raised errors.

Enforces one of an Exception type, a string, or a regular
expression to match against the exception message as a parameter
to `raise_error`

=== Examples

[source,ruby]
----
# bad
expect {
  raise StandardError.new('error')
}.to raise_error

# good
expect {
  raise StandardError.new('error')
}.to raise_error(StandardError)

expect {
  raise StandardError.new('error')
}.to raise_error('error')

expect {
  raise StandardError.new('error')
}.to raise_error(/err/)

expect { do_something }.not_to raise_error
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/UnspecifiedException

== RSpec/VariableDefinition

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 1.40
| -
|===

Checks that memoized helpers names are symbols or strings.

=== Examples

==== EnforcedStyle: symbols (default)

[source,ruby]
----
# bad
subject('user') { create_user }
let('user_name') { 'Adam' }

# good
subject(:user) { create_user }
let(:user_name) { 'Adam' }
----

==== EnforcedStyle: strings

[source,ruby]
----
# bad
subject(:user) { create_user }
let(:user_name) { 'Adam' }

# good
subject('user') { create_user }
let('user_name') { 'Adam' }
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| EnforcedStyle
| `symbols`
| `symbols`, `strings`
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VariableDefinition

== RSpec/VariableName

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.40
| 2.13
|===

Checks that memoized helper names use the configured style.

Variables can be excluded from checking using the `AllowedPatterns`
option.

=== Examples

==== EnforcedStyle: snake_case (default)

[source,ruby]
----
# bad
subject(:userName1) { 'Adam' }
let(:userName2) { 'Adam' }

# good
subject(:user_name_1) { 'Adam' }
let(:user_name_2) { 'Adam' }
----

==== EnforcedStyle: camelCase

[source,ruby]
----
# bad
subject(:user_name_1) { 'Adam' }
let(:user_name_2) { 'Adam' }

# good
subject(:userName1) { 'Adam' }
let(:userName2) { 'Adam' }
----

==== AllowedPatterns configuration

[source,ruby]
----
# rubocop.yml
# RSpec/VariableName:
#   EnforcedStyle: snake_case
#   AllowedPatterns:
#     - ^userFood
----

[source,ruby]
----
# okay because it matches the `^userFood` regex in `AllowedPatterns`
subject(:userFood_1) { 'spaghetti' }
let(:userFood_2) { 'fettuccine' }
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| EnforcedStyle
| `snake_case`
| `snake_case`, `camelCase`

| AllowedPatterns
| `[]`
| Array
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VariableName

== RSpec/VerifiedDoubleReference

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always (Unsafe)
| 2.10.0
| 2.12
|===

Checks for consistent verified double reference style.

Only investigates references that are one of the supported styles.

This cop can be configured in your configuration using the
`EnforcedStyle` option and supports `--auto-gen-config`.

=== Examples

==== `EnforcedStyle: constant` (default)

[source,ruby]
----
# bad
let(:foo) do
  instance_double('ClassName', method_name: 'returned_value')
end

# good
let(:foo) do
  instance_double(ClassName, method_name: 'returned_value')
end
----

==== `EnforcedStyle: string`

[source,ruby]
----
# bad
let(:foo) do
  instance_double(ClassName, method_name: 'returned_value')
end

# good
let(:foo) do
  instance_double('ClassName', method_name: 'returned_value')
end
----

==== Reference is not in the supported style list. No enforcement

[source,ruby]
----
# good
let(:foo) do
  instance_double(@klass, method_name: 'returned_value')
end
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| EnforcedStyle
| `constant`
| `constant`, `string`
|===

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VerifiedDoubleReference
* https://rspec.info/features/3-12/rspec-mocks/verifying-doubles

== RSpec/VerifiedDoubles

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.2.1
| 1.5
|===

Prefer using verifying doubles over normal doubles.

=== Examples

[source,ruby]
----
# bad
let(:foo) do
  double(method_name: 'returned value')
end

# bad
let(:foo) do
  double("ClassName", method_name: 'returned value')
end

# good
let(:foo) do
  instance_double("ClassName", method_name: 'returned value')
end
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| IgnoreNameless
| `true`
| Boolean

| IgnoreSymbolicNames
| `false`
| Boolean
|===

=== References

* https://rspec.rubystyle.guide/#doubles
* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VerifiedDoubles
* https://rspec.info/features/3-12/rspec-mocks/verifying-doubles

== RSpec/VoidExpect

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 1.16
| -
|===

Checks void `expect()`.

=== Examples

[source,ruby]
----
# bad
expect(something)

# good
expect(something).to be(1)
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VoidExpect

== RSpec/Yield

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always
| 1.32
| -
|===

Checks for calling a block within a stub.

=== Examples

[source,ruby]
----
# bad
allow(foo).to receive(:bar) { |&block| block.call(1) }

# good
expect(foo).to receive(:bar).and_yield(1)
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Yield