Skip to content

Commit

Permalink
Merge pull request #1132 from tejasbubane/fix-1130
Browse files Browse the repository at this point in the history
Add new `RSpec/IdenticalEqualityAssertion` cop
  • Loading branch information
pirj authored May 25, 2021
2 parents cb5c0dc + cada3e0 commit e0e109c
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

* Add missing documentation for `single_statement_only` style of `RSpec/ImplicitSubject` cop. ([@tejasbubane][])
* Fix an exception in `DescribedClass` when accessing a constant on a variable in a spec that is nested in a namespace. ([@rrosenblum][])
* Add new `RSpec/IdenticalEqualityAssertion` cop. ([@tejasbubane][])

## 2.3.0 (2021-04-28)

Expand Down
6 changes: 6 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,12 @@ RSpec/HooksBeforeExamples:
VersionAdded: '1.29'
StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/HooksBeforeExamples

RSpec/IdenticalEqualityAssertion:
Description: Checks for equality assertions with identical expressions on both sides.
Enabled: pending
VersionAdded: '2.4'
StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IdenticalEqualityAssertion

RSpec/ImplicitBlockExpectation:
Description: Check that implicit block expectation syntax is not used.
Enabled: true
Expand Down
1 change: 1 addition & 0 deletions docs/modules/ROOT/pages/cops.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
* xref:cops_rspec.adoc#rspecfocus[RSpec/Focus]
* xref:cops_rspec.adoc#rspechookargument[RSpec/HookArgument]
* xref:cops_rspec.adoc#rspechooksbeforeexamples[RSpec/HooksBeforeExamples]
* xref:cops_rspec.adoc#rspecidenticalequalityassertion[RSpec/IdenticalEqualityAssertion]
* xref:cops_rspec.adoc#rspecimplicitblockexpectation[RSpec/ImplicitBlockExpectation]
* xref:cops_rspec.adoc#rspecimplicitexpect[RSpec/ImplicitExpect]
* xref:cops_rspec.adoc#rspecimplicitsubject[RSpec/ImplicitSubject]
Expand Down
31 changes: 31 additions & 0 deletions docs/modules/ROOT/pages/cops_rspec.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1720,6 +1720,37 @@ end

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

== RSpec/IdenticalEqualityAssertion

|===
| Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged

| Pending
| 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

|===
Expand Down
38 changes: 38 additions & 0 deletions lib/rubocop/cop/rspec/identical_equality_assertion.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# frozen_string_literal: true

module RuboCop
module Cop
module RSpec
# Checks for equality assertions with identical expressions on both sides.
#
# @example
#
# # 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)
#
class IdenticalEqualityAssertion < Base
MSG = 'Identical expressions on both sides of the equality ' \
'may indicate a flawed test.'
RESTRICT_ON_SEND = %i[to].freeze

# @!method equality_check?(node)
def_node_matcher :equality_check?, <<~PATTERN
(send (send nil? :expect $_) :to
{(send nil? {:eql :eq :be} $_)
(send (send nil? :be) :== $_)})
PATTERN

def on_send(node)
equality_check?(node) do |left, right|
add_offense(node) if left == right
end
end
end
end
end
end
1 change: 1 addition & 0 deletions lib/rubocop/cop/rspec_cops.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
require_relative 'rspec/focus'
require_relative 'rspec/hook_argument'
require_relative 'rspec/hooks_before_examples'
require_relative 'rspec/identical_equality_assertion'
require_relative 'rspec/implicit_block_expectation'
require_relative 'rspec/implicit_expect'
require_relative 'rspec/implicit_subject'
Expand Down
57 changes: 57 additions & 0 deletions spec/rubocop/cop/rspec/identical_equality_assertion_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::RSpec::IdenticalEqualityAssertion do
it 'registers an offense when using identical expressions with `eq`' do
expect_offense(<<~RUBY)
expect(foo.bar).to eq(foo.bar)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Identical expressions on both sides of the equality may indicate a flawed test.
RUBY
end

it 'registers an offense when using identical expressions with `eql`' do
expect_offense(<<~RUBY)
expect(foo.bar.baz).to eql(foo.bar.baz)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Identical expressions on both sides of the equality may indicate a flawed test.
RUBY
end

it 'registers an offense for trivial constants' do
expect_offense(<<~RUBY)
expect(42).to eq(42)
^^^^^^^^^^^^^^^^^^^^ Identical expressions on both sides of the equality may indicate a flawed test.
RUBY
end

it 'registers an offense for complex constants' do
expect_offense(<<~RUBY)
expect({a: 1, b: :b}).to eql({a: 1, b: :b})
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Identical expressions on both sides of the equality may indicate a flawed test.
RUBY
end

it 'registers an offense for identical expression with be' do
expect_offense(<<~RUBY)
expect(foo.bar).to be(foo.bar)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Identical expressions on both sides of the equality may indicate a flawed test.
RUBY
end

it 'registers an offense for identical expression with be ==' do
expect_offense(<<~RUBY)
expect(foo.bar).to be == foo.bar
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Identical expressions on both sides of the equality may indicate a flawed test.
RUBY
end

it 'does not register offense for different expressions' do
expect_no_offenses(<<~RUBY)
expect(foo.bar).to eq(bar.foo)
RUBY
end

it 'checks for whole expression' do
expect_no_offenses(<<~RUBY)
expect(Foo.new(1).foo).to eql(Foo.new(2).bar)
RUBY
end
end

0 comments on commit e0e109c

Please sign in to comment.