Skip to content

Commit

Permalink
Merge pull request #27 from duduribeiro/add_cop_to_enforce_assert_res…
Browse files Browse the repository at this point in the history
…pond_to

Include a cop to enforce assert_respond_to
  • Loading branch information
koic authored Oct 13, 2019
2 parents f9f4c1a + 6bd6377 commit b054f33
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* [#18](https://github.com/rubocop-hq/rubocop-minitest/pull/18): Add new `Minitest/RefuteFalse` cop. ([@duduribeiro][])
* [#20](https://github.com/rubocop-hq/rubocop-minitest/pull/20): Add new `Minitest/RefuteEmpty` cop. ([@abhaynikam][])
* [#21](https://github.com/rubocop-hq/rubocop-minitest/pull/21): Add new `Minitest/RefuteEqual` cop. ([@duduribeiro][])
* [#27](https://github.com/rubocop-hq/rubocop-minitest/pull/27): Add new `Minitest/AssertRespondTo` cop. ([@duduribeiro][])

### 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 @@ -20,6 +20,12 @@ Minitest/AssertIncludes:
Enabled: true
VersionAdded: '0.2'

Minitest/AssertRespondTo:
Description: 'This cop enforces the test to use `assert_respond_to(object, :some_method)` over `assert(object.respond_to?(:some_method))`.'
StyleGuide: 'https://github.com/rubocop-hq/minitest-style-guide#assert-responds-to-method'
Enabled: true
VersionAdded: '0.3'

Minitest/AssertTruthy:
Description: 'This cop enforces the test to use `assert(actual)` instead of using `assert_equal(true, actual)`.'
StyleGuide: 'https://github.com/rubocop-hq/minitest-style-guide#assert-truthy'
Expand Down
51 changes: 51 additions & 0 deletions lib/rubocop/cop/minitest/assert_respond_to.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# frozen_string_literal: true

module RuboCop
module Cop
module Minitest
# This cop enforces the use of `assert_respond_to(object, :some_method)`
# over `assert(object.respond_to?(:some_method))`.
#
# @example
# # bad
# assert(object.respond_to?(:some_method))
# assert(object.respond_to?(:some_method), 'the message')
#
# # good
# assert_respond_to(object, :some_method)
# assert_respond_to(object, :some_method, 'the message')
#
class AssertRespondTo < Cop
MSG = 'Prefer using `assert_respond_to(%<preferred>s)` over ' \
'`assert(%<over>s)`.'

def_node_matcher :assert_with_respond_to, <<~PATTERN
(send nil? :assert $(send $_ :respond_to? $_) $...)
PATTERN

def on_send(node)
assert_with_respond_to(node) do |over, object, method, rest_args|
custom_message = rest_args.first
preferred = [object, method, custom_message]
.compact.map(&:source).join(', ')
over = [over, custom_message].compact.map(&:source).join(', ')
message = format(MSG, preferred: preferred, over: over)
add_offense(node, message: message)
end
end

def autocorrect(node)
lambda do |corrector|
assert_with_respond_to(node) do |_, object, method, rest_args|
custom_message = rest_args.first
preferred = [object, method, custom_message]
.compact.map(&:source).join(', ')
replacement = "assert_respond_to(#{preferred})"
corrector.replace(node.loc.expression, replacement)
end
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 @@ -3,6 +3,7 @@
require_relative 'minitest/assert_empty'
require_relative 'minitest/assert_nil'
require_relative 'minitest/assert_includes'
require_relative 'minitest/assert_respond_to'
require_relative 'minitest/assert_truthy'
require_relative 'minitest/refute_empty'
require_relative 'minitest/refute_false'
Expand Down
1 change: 1 addition & 0 deletions manual/cops.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* [Minitest/AssertEmpty](cops_minitest.md#minitestassertempty)
* [Minitest/AssertIncludes](cops_minitest.md#minitestassertincludes)
* [Minitest/AssertNil](cops_minitest.md#minitestassertnil)
* [Minitest/AssertRespondTo](cops_minitest.md#minitestassertrespondto)
* [Minitest/AssertTruthy](cops_minitest.md#minitestasserttruthy)
* [Minitest/RefuteEmpty](cops_minitest.md#minitestrefuteempty)
* [Minitest/RefuteEqual](cops_minitest.md#minitestrefuteequal)
Expand Down
25 changes: 25 additions & 0 deletions manual/cops_minitest.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,31 @@ assert_nil(actual, 'the message')

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

## Minitest/AssertRespondTo

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

This cop enforces the use of `assert_respond_to(object, :some_method)`
over `assert(object.respond_to?(:some_method))`.

### Examples

```ruby
# bad
assert(object.respond_to?(:some_method))
assert(object.respond_to?(:some_method), 'the message')

# good
assert_respond_to(object, :some_method)
assert_respond_to(object, :some_method, 'the message')
```

### References

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

## Minitest/AssertTruthy

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

require 'test_helper'

class AssertRespondToTest < Minitest::Test
def setup
@cop = RuboCop::Cop::Minitest::AssertRespondTo.new
end

def test_registers_offense_when_using_assert_calling_respond_to_method
assert_offense(<<~RUBY, @cop)
class FooTest < Minitest::Test
def test_do_something
assert(object.respond_to?(:some_method))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `assert_respond_to(object, :some_method)` over `assert(object.respond_to?(:some_method))`.
end
end
RUBY

assert_correction(<<~RUBY, @cop)
class FooTest < Minitest::Test
def test_do_something
assert_respond_to(object, :some_method)
end
end
RUBY
end

def test_registers_offense_when_using_assert_calling_respond_to_method_with_message
assert_offense(<<~RUBY, @cop)
class FooTest < Minitest::Test
def test_do_something
assert(object.respond_to?(:some_method), 'the message')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `assert_respond_to(object, :some_method, 'the message')` over `assert(object.respond_to?(:some_method), 'the message')`.
end
end
RUBY

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

def test_does_not_register_offense_when_using_assert_respond_to
assert_no_offenses(<<~RUBY, @cop)
class FooTest < Minitest::Test
def test_do_something
assert_respond_to('rubocop-minitest', :some_method)
end
end
RUBY
end
end

0 comments on commit b054f33

Please sign in to comment.