Skip to content

Commit

Permalink
Include a Cop to enforce refute(actual) over assert_equal(false)
Browse files Browse the repository at this point in the history
This commit adds a Cop that checks some usage of
`assert_equal(false, something)` and enforces the usage of
`refute(something)` instead.
  • Loading branch information
duduribeiro committed Sep 27, 2019
1 parent 7a42f9f commit 24ac75e
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## master (unreleased)

* [#18](https://github.com/rubocop-hq/rubocop-minitest/pull/18): Add new `Minitest/RefuteFalse` cop. ([@duduribeiro][])

## 0.2.1 (2019-09-24)

### Bug fixes
Expand Down
6 changes: 6 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,9 @@ Minitest/RefuteNil:
StyleGuide: 'https://github.com/rubocop-hq/minitest-style-guide#refute-nil'
Enabled: true
VersionAdded: '0.2'

Minitest/RefuteFalse:
Description: 'Check if your test uses `refute(actual)` instead of `assert_equal(false, actual)`.'
StyleGuide: 'https://github.com/rubocop-hq/minitest-style-guide#refute-false'
Enabled: true
VersionAdded: '0.3'
46 changes: 46 additions & 0 deletions lib/rubocop/cop/minitest/refute_false.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# frozen_string_literal: true

module RuboCop
module Cop
module Minitest
# Check if your test uses `refute(actual)`
# instead of `assert_equal(false, actual)`.
#
# @example
# # bad
# assert_equal(false, actual)
# assert_equal(false, actual, 'the message')
#
# # good
# refute(actual)
# refute(actual, 'the message')
#
class RefuteFalse < Cop
MSG = 'Prefer using `refute(%<arguments>s)` over ' \
'`assert_equal(false, %<arguments>s)`.'

def_node_matcher :assert_equal_with_false, <<~PATTERN
(send nil? :assert_equal false $_ $...)
PATTERN

def on_send(node)
assert_equal_with_false(node) do |actual, rest_receiver_arg|
message = rest_receiver_arg.first

arguments = [actual.source, message&.source].compact.join(', ')

add_offense(node, message: format(MSG, arguments: arguments))
end
end

def autocorrect(node)
lambda do |corrector|
arguments = node.arguments.reject(&:false_type?)
replacement = arguments.map(&:source).join(', ')
corrector.replace(node.loc.expression, "refute(#{replacement})")
end
end
end
end
end
end
1 change: 1 addition & 0 deletions lib/rubocop/cop/minitest_cops.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
require_relative 'minitest/assert_nil'
require_relative 'minitest/assert_includes'
require_relative 'minitest/assert_truthy'
require_relative 'minitest/refute_false'
require_relative 'minitest/refute_nil'
1 change: 1 addition & 0 deletions manual/cops.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* [Minitest/AssertIncludes](cops_minitest.md#minitestassertincludes)
* [Minitest/AssertNil](cops_minitest.md#minitestassertnil)
* [Minitest/AssertTruthy](cops_minitest.md#minitestasserttruthy)
* [Minitest/RefuteFalse](cops_minitest.md#minitestrefutefalse)
* [Minitest/RefuteNil](cops_minitest.md#minitestrefutenil)

<!-- END_COP_LIST -->
25 changes: 25 additions & 0 deletions manual/cops_minitest.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,31 @@ assert(actual, 'the message')

* [https://github.com/rubocop-hq/minitest-style-guide#assert-truthy](https://github.com/rubocop-hq/minitest-style-guide#assert-truthy)

## Minitest/RefuteFalse

Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
--- | --- | --- | --- | ---
Enabled | Yes | Yes | 0.3 | -

Check if your test uses `refute(actual)`
instead of `assert_equal(false, actual)`.

### Examples

```ruby
# bad
assert_equal(false, actual)
assert_equal(false, actual, 'the message')

# good
refute(actual)
refute(actual, 'the message')
```

### References

* [https://github.com/rubocop-hq/minitest-style-guide#refute-false](https://github.com/rubocop-hq/minitest-style-guide#refute-false)

## Minitest/RefuteNil

Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
Expand Down
120 changes: 120 additions & 0 deletions test/rubocop/cop/minitest/refute_false_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# frozen_string_literal: true

require 'test_helper'

class RefuteFalseTest < Minitest::Test
def setup
@cop = RuboCop::Cop::Minitest::RefuteFalse.new
end

def test_registers_offense_when_using_assert_equal_with_false
assert_offense(<<~RUBY, @cop)
class FooTest < Minitest::Test
def test_do_something
assert_equal(false, somestuff)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `refute(somestuff)` over `assert_equal(false, somestuff)`.
end
end
RUBY

assert_correction(<<~RUBY, @cop)
class FooTest < Minitest::Test
def test_do_something
refute(somestuff)
end
end
RUBY
end

def test_registers_offense_when_using_assert_equal_with_false_and_message
assert_offense(<<~RUBY, @cop)
class FooTest < Minitest::Test
def test_do_something
assert_equal(false, somestuff, 'the message')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `refute(somestuff, 'the message')` over `assert_equal(false, somestuff, 'the message')`.
end
end
RUBY

assert_correction(<<~RUBY, @cop)
class FooTest < Minitest::Test
def test_do_something
refute(somestuff, 'the message')
end
end
RUBY
end

def test_registers_offense_when_using_assert_equal_with_method_call
assert_offense(<<~RUBY, @cop)
class FooTest < Minitest::Test
def test_do_something
assert_equal(false, obj.do_something, 'the message')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `refute(obj.do_something, 'the message')` over `assert_equal(false, obj.do_something, 'the message')`.
end
end
RUBY

assert_correction(<<~RUBY, @cop)
class FooTest < Minitest::Test
def test_do_something
refute(obj.do_something, 'the message')
end
end
RUBY
end

def test_registers_offense_when_using_assert_equal_with_variable_message
assert_offense(<<~RUBY, @cop)
class FooTest < Minitest::Test
def test_do_something
message = 'the message'
assert_equal(false, somestuff, message)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `refute(somestuff, message)` over `assert_equal(false, somestuff, message)`.
end
end
RUBY

assert_correction(<<~RUBY, @cop)
class FooTest < Minitest::Test
def test_do_something
message = 'the message'
refute(somestuff, message)
end
end
RUBY
end

def test_registers_offense_when_using_assert_equal_with_constant_message
assert_offense(<<~RUBY, @cop)
class FooTest < Minitest::Test
MESSAGE = 'the message'
def test_do_something
assert_equal(false, somestuff, MESSAGE)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `refute(somestuff, MESSAGE)` over `assert_equal(false, somestuff, MESSAGE)`.
end
end
RUBY

assert_correction(<<~RUBY, @cop)
class FooTest < Minitest::Test
MESSAGE = 'the message'
def test_do_something
refute(somestuff, MESSAGE)
end
end
RUBY
end

def test_does_not_register_offense_when_using_refute_method
assert_no_offenses(<<~RUBY, @cop)
class FooTest < Minitest::Test
def test_do_something
refute(somestuff)
end
end
RUBY
end
end

0 comments on commit 24ac75e

Please sign in to comment.