rubocop-minitest 0.32.2 → 0.34.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ce290f7a13faed25c00a17d9daf8bcaf17e187599a075323fc99f8494c29c2bb
4
- data.tar.gz: 9def860d52f65aed4e8923bcf2fd851a5188485986c7ad5bce44a9dc0d79b2d3
3
+ metadata.gz: 571b1db9fefc76fa80002c19d3717b845d1db2233f4e42334be77c000e6e4c97
4
+ data.tar.gz: 9e415cf5f10bd9fe304cf4e7e06ddc8e429fd44f8f81736db6399ff49e159014
5
5
  SHA512:
6
- metadata.gz: 8db20fcf7d8e58b564da63b85f6692c4a2be189ffeacdc654f4b18ea689416688442df945606c84f55e63b9007c8df51b4f173004a7ae145603733f6bac62c61
7
- data.tar.gz: 41232dfbabd012e4edbe1e78b49f1846004246950773a6f06c50fff358cb71a79fbdcd95ed0657690387801331093606c2dabb376788368cf51438ff84846be4
6
+ metadata.gz: c4e0adcffeec5f46c694480f7a4d99c04f76545694318c1b660f5dcde4eb6e0626f07bd2d25a9d1042019223cc393fae17555a98fe9d6fbcc567c790cc3aee4d
7
+ data.tar.gz: 4ba96bd280bec762d6256e40f16e40c2831cddb78c7df75ef172c0ca50d6d55ab8ec61499f05cc613cdc9925ab3f370c21bf8bb6f047591b3aae9db45f8117cd
data/README.md CHANGED
@@ -53,6 +53,8 @@ $ rubocop --require rubocop-minitest
53
53
  ### Rake task
54
54
 
55
55
  ```ruby
56
+ require 'rubocop/rake_task'
57
+
56
58
  RuboCop::RakeTask.new do |task|
57
59
  task.requires << 'rubocop-minitest'
58
60
  end
data/config/default.yml CHANGED
@@ -192,12 +192,23 @@ Minitest/NoTestCases:
192
192
  Enabled: false
193
193
  VersionAdded: '0.30'
194
194
 
195
+ Minitest/NonExecutableTestMethod:
196
+ Description: 'Checks uses of test methods outside test class.'
197
+ Enabled: pending
198
+ Severity: warning
199
+ VersionAdded: '0.34'
200
+
195
201
  Minitest/NonPublicTestMethod:
196
202
  Description: 'Detects non `public` (marked as `private` or `protected`) test methods.'
197
203
  Enabled: pending
198
204
  Severity: warning
199
205
  VersionAdded: '0.27'
200
206
 
207
+ Minitest/RedundantMessageArgument:
208
+ Description: 'Detects redundant message argument in assertion methods.'
209
+ Enabled: pending
210
+ VersionAdded: '0.34'
211
+
201
212
  Minitest/RefuteEmpty:
202
213
  Description: 'This cop enforces to use `refute_empty` instead of using `refute(object.empty?)`.'
203
214
  StyleGuide: 'https://minitest.rubystyle.guide#refute-empty'
@@ -22,12 +22,11 @@ module RuboCop
22
22
  remove_method :on_send
23
23
  def on_send(node)
24
24
  return unless node.method?(:assert)
25
- return unless (arguments = peel_redundant_parentheses_from(node.arguments))
26
- return unless arguments.first.respond_to?(:method?) && arguments.first.method?(:empty?)
27
- return unless arguments.first.arguments.empty?
25
+ return unless node.first_argument.respond_to?(:method?) && node.first_argument.method?(:empty?)
26
+ return unless node.first_argument.arguments.empty?
28
27
 
29
- add_offense(node, message: offense_message(arguments)) do |corrector|
30
- autocorrect(corrector, node, arguments)
28
+ add_offense(node, message: offense_message(node.arguments)) do |corrector|
29
+ autocorrect(corrector, node, node.arguments)
31
30
  end
32
31
  end
33
32
  end
@@ -9,14 +9,46 @@ module RuboCop
9
9
  # @example
10
10
  # # bad
11
11
  # assert("rubocop-minitest" == actual)
12
+ # assert_operator("rubocop-minitest", :==, actual)
12
13
  #
13
14
  # # good
14
15
  # assert_equal("rubocop-minitest", actual)
15
16
  #
16
17
  class AssertEqual < Base
17
- extend MinitestCopRule
18
+ include ArgumentRangeHelper
19
+ extend AutoCorrector
18
20
 
19
- define_rule :assert, target_method: :==, preferred_method: :assert_equal
21
+ MSG = 'Prefer using `assert_equal(%<preferred>s)`.'
22
+ RESTRICT_ON_SEND = %i[assert assert_operator].freeze
23
+
24
+ def_node_matcher :assert_equal, <<~PATTERN
25
+ {
26
+ (send nil? :assert (send $_ :== $_) $...)
27
+ (send nil? :assert_operator $_ (sym :==) $_ $...)
28
+ }
29
+ PATTERN
30
+
31
+ # rubocop:disable Metrics/AbcSize
32
+ def on_send(node)
33
+ assert_equal(node) do |expected, actual, rest_args|
34
+ basic_arguments = "#{expected.source}, #{actual.source}"
35
+ preferred = (message_arg = rest_args.first) ? "#{basic_arguments}, #{message_arg.source}" : basic_arguments
36
+ message = format(MSG, preferred: preferred)
37
+
38
+ add_offense(node, message: message) do |corrector|
39
+ corrector.replace(node.loc.selector, 'assert_equal')
40
+
41
+ range = if node.method?(:assert)
42
+ node.first_argument
43
+ else
44
+ node.first_argument.source_range.begin.join(node.arguments[2].source_range.end)
45
+ end
46
+
47
+ corrector.replace(range, basic_arguments)
48
+ end
49
+ end
50
+ end
51
+ # rubocop:enable Metrics/AbcSize
20
52
  end
21
53
  end
22
54
  end
@@ -11,6 +11,7 @@ module RuboCop
11
11
  # assert(matcher.match(string))
12
12
  # assert(matcher.match?(string))
13
13
  # assert(matcher =~ string)
14
+ # assert_operator(matcher, :=~, string)
14
15
  # assert(matcher.match(string), 'message')
15
16
  #
16
17
  # # good
@@ -18,10 +19,50 @@ module RuboCop
18
19
  # assert_match(matcher, string, 'message')
19
20
  #
20
21
  class AssertMatch < Base
21
- extend MinitestCopRule
22
+ include ArgumentRangeHelper
23
+ extend AutoCorrector
22
24
 
23
- define_rule :assert, target_method: %i[match match? =~],
24
- preferred_method: :assert_match, inverse: 'regexp_type?'
25
+ MSG = 'Prefer using `assert_match(%<preferred>s)`.'
26
+ RESTRICT_ON_SEND = %i[assert assert_operator].freeze
27
+
28
+ def_node_matcher :assert_match, <<~PATTERN
29
+ {
30
+ (send nil? :assert (send $_ {:match :match? :=~} $_) $...)
31
+ (send nil? :assert_operator $_ (sym :=~) $_ $...)
32
+ }
33
+ PATTERN
34
+
35
+ # rubocop:disable Metrics/AbcSize
36
+ def on_send(node)
37
+ assert_match(node) do |expected, actual, rest_args|
38
+ basic_arguments = order_expected_and_actual(expected, actual)
39
+ preferred = (message_arg = rest_args.first) ? "#{basic_arguments}, #{message_arg.source}" : basic_arguments
40
+ message = format(MSG, preferred: preferred)
41
+
42
+ add_offense(node, message: message) do |corrector|
43
+ corrector.replace(node.loc.selector, 'assert_match')
44
+
45
+ range = if node.method?(:assert)
46
+ node.first_argument
47
+ else
48
+ node.first_argument.source_range.begin.join(node.arguments[2].source_range.end)
49
+ end
50
+
51
+ corrector.replace(range, basic_arguments)
52
+ end
53
+ end
54
+ end
55
+ # rubocop:enable Metrics/AbcSize
56
+
57
+ private
58
+
59
+ def order_expected_and_actual(expected, actual)
60
+ if actual.regexp_type?
61
+ [actual, expected]
62
+ else
63
+ [expected, actual]
64
+ end.map(&:source).join(', ')
65
+ end
25
66
  end
26
67
  end
27
68
  end
@@ -40,7 +40,7 @@ module RuboCop
40
40
 
41
41
  def build_new_arguments(node)
42
42
  lhs, op, rhs = *node.first_argument
43
- new_arguments = "#{lhs.source}, :#{op}, #{rhs.source}"
43
+ new_arguments = +"#{lhs.source}, :#{op}, #{rhs.source}"
44
44
 
45
45
  if node.arguments.count == 2
46
46
  new_arguments << ", #{node.last_argument.source}"
@@ -12,14 +12,58 @@ module RuboCop
12
12
  # @example
13
13
  # # bad
14
14
  # assert(expected.equal?(actual))
15
+ # assert_equal(expected.object_id, actual.object_id)
15
16
  #
16
17
  # # good
17
18
  # assert_same(expected, actual)
18
19
  #
19
20
  class AssertSame < Base
20
- extend MinitestCopRule
21
+ extend AutoCorrector
21
22
 
22
- define_rule :assert, target_method: :equal?, preferred_method: :assert_same
23
+ MSG = 'Prefer using `assert_same(%<new_arguments>s)`.'
24
+ RESTRICT_ON_SEND = %i[assert assert_equal].freeze
25
+
26
+ def_node_matcher :assert_with_equal?, <<~PATTERN
27
+ (send nil? :assert
28
+ $(send $_ :equal? $_)
29
+ $_?)
30
+ PATTERN
31
+
32
+ def_node_matcher :assert_equal_with_object_id?, <<~PATTERN
33
+ (send nil? :assert_equal
34
+ (send $_ :object_id)
35
+ (send $_ :object_id)
36
+ $_?)
37
+ PATTERN
38
+
39
+ # rubocop:disable Metrics/AbcSize
40
+ def on_send(node)
41
+ if (equal_node, expected_node, actual_node, message_node = assert_with_equal?(node))
42
+ add_offense(node, message: message(expected_node, actual_node, message_node.first)) do |corrector|
43
+ corrector.replace(node.loc.selector, 'assert_same')
44
+ corrector.replace(equal_node, "#{expected_node.source}, #{actual_node.source}")
45
+ end
46
+ elsif (expected_node, actual_node, message_node = assert_equal_with_object_id?(node))
47
+ add_offense(node, message: message(expected_node, actual_node, message_node.first)) do |corrector|
48
+ corrector.replace(node.loc.selector, 'assert_same')
49
+ remove_method_call(expected_node.parent, corrector)
50
+ remove_method_call(actual_node.parent, corrector)
51
+ end
52
+ end
53
+ end
54
+ # rubocop:enable Metrics/AbcSize
55
+
56
+ private
57
+
58
+ def message(expected_node, actual_node, message_node)
59
+ arguments = [expected_node, actual_node, message_node].compact.map(&:source).join(', ')
60
+ format(MSG, new_arguments: arguments)
61
+ end
62
+
63
+ def remove_method_call(send_node, corrector)
64
+ range = send_node.loc.dot.join(send_node.loc.selector)
65
+ corrector.remove(range)
66
+ end
23
67
  end
24
68
  end
25
69
  end
@@ -30,7 +30,7 @@ module RuboCop
30
30
  return if node.parent.resbody_type?
31
31
  return if accept_previous_line?(previous_line_node, assertion_method)
32
32
 
33
- previous_line_node = previous_line_node.arguments.last if use_heredoc_argument?(previous_line_node)
33
+ previous_line_node = previous_line_node.last_argument if use_heredoc_argument?(previous_line_node)
34
34
  return if use_assertion_method_at_last_of_block?(previous_line_node)
35
35
  return unless no_empty_line?(previous_line_node, assertion_method)
36
36
 
@@ -57,7 +57,7 @@ module RuboCop
57
57
  end
58
58
 
59
59
  def use_heredoc_argument?(node)
60
- node.respond_to?(:arguments) && heredoc?(node.arguments.last)
60
+ node.respond_to?(:arguments) && heredoc?(node.last_argument)
61
61
  end
62
62
 
63
63
  def use_assertion_method_at_last_of_block?(node)
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Minitest
6
+ # Checks for the use of test methods outside of a test class.
7
+ #
8
+ # Test methods should be defined within a test class to ensure their execution.
9
+ #
10
+ # NOTE: This cop assumes that classes whose superclass name includes the word
11
+ # "`Test`" are test classes, in order to prevent false positives.
12
+ #
13
+ # @example
14
+ #
15
+ # # bad
16
+ # class FooTest < Minitest::Test
17
+ # end
18
+ # def test_method_should_be_inside_test_class
19
+ # end
20
+ #
21
+ # # good
22
+ # class FooTest < Minitest::Test
23
+ # def test_method_should_be_inside_test_class
24
+ # end
25
+ # end
26
+ #
27
+ class NonExecutableTestMethod < Base
28
+ include MinitestExplorationHelpers
29
+
30
+ MSG = 'Test method should be defined inside a test class to ensure execution.'
31
+
32
+ def on_def(node)
33
+ return if !test_method?(node) || !use_test_class?
34
+ return if node.left_siblings.none? { |sibling| possible_test_class?(sibling) }
35
+
36
+ add_offense(node)
37
+ end
38
+
39
+ def use_test_class?
40
+ root_node = processed_source.ast
41
+
42
+ root_node.each_descendant(:class).any? { |class_node| test_class?(class_node) }
43
+ end
44
+
45
+ def possible_test_class?(node)
46
+ node.is_a?(AST::ClassNode) && test_class?(node) && node.parent_class.source.include?('Test')
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Minitest
6
+ # Detects redundant message argument in assertion methods.
7
+ # The message argument `nil` is redundant because it is the default value.
8
+ #
9
+ # @example
10
+ #
11
+ # # bad
12
+ # assert_equal(expected, actual, nil)
13
+ #
14
+ # # good
15
+ # assert_equal(expected, actual)
16
+ # assert_equal(expected, actual, 'message')
17
+ #
18
+ class RedundantMessageArgument < Base
19
+ extend AutoCorrector
20
+
21
+ MSG = 'Remove the redundant message argument.'
22
+
23
+ RESTRICT_ON_SEND = %i[
24
+ assert assert_empty assert_equal assert_same assert_in_delta assert_in_epsilon assert_includes
25
+ assert_instance_of assert_kind_of assert_match assert_nil assert_operator assert_path_exists
26
+ assert_predicate assert_respond_to assert_same assert_throws
27
+ flunk
28
+ refute refute_empty refute_equal refute_in_delta refute_in_epsilon refute_includes
29
+ refute_instance_of refute_kind_of refute_match refute_nil refute_operator refute_path_exists
30
+ refute_predicate refute_respond_to refute_same
31
+ ].freeze
32
+
33
+ # @!method bad_method?(node)
34
+ def_node_matcher :redundant_message_argument, <<~PATTERN
35
+ {
36
+ (send nil? :assert _ $nil)
37
+ (send nil? :assert_empty _ $nil)
38
+ (send nil? :assert_equal _ _ $nil)
39
+ (send nil? :assert_in_delta _ _ _ $nil)
40
+ (send nil? :assert_in_epsilon _ _ _ $nil)
41
+ (send nil? :assert_includes _ _ $nil)
42
+ (send nil? :assert_instance_of _ _ $nil)
43
+ (send nil? :assert_kind_of _ _ $nil)
44
+ (send nil? :assert_match _ _ $nil)
45
+ (send nil? :assert_nil _ $nil)
46
+ (send nil? :assert_operator _ _ _ $nil)
47
+ (send nil? :assert_path_exists _ $nil)
48
+ (send nil? :assert_predicate _ _ $nil)
49
+ (send nil? :assert_respond_to _ _ $nil)
50
+ (send nil? :assert_same _ _ $nil)
51
+ (send nil? :assert_throws _ $nil)
52
+ (send nil? :flunk $nil)
53
+ (send nil? :refute _ $nil)
54
+ (send nil? :refute_empty _ $nil)
55
+ (send nil? :refute_equal _ _ $nil)
56
+ (send nil? :refute_in_delta _ _ _ $nil)
57
+ (send nil? :refute_in_epsilon _ _ _ $nil)
58
+ (send nil? :refute_includes _ _ $nil)
59
+ (send nil? :refute_instance_of _ _ $nil)
60
+ (send nil? :refute_kind_of _ _ $nil)
61
+ (send nil? :refute_match _ _ $nil)
62
+ (send nil? :refute_nil _ $nil)
63
+ (send nil? :refute_operator _ _ _ $nil)
64
+ (send nil? :refute_path_exists _ $nil)
65
+ (send nil? :refute_predicate _ _ $nil)
66
+ (send nil? :refute_respond_to _ _ $nil)
67
+ (send nil? :refute_same _ _ $nil)
68
+ }
69
+ PATTERN
70
+
71
+ def on_send(node)
72
+ return unless (redundant_message_argument = redundant_message_argument(node))
73
+
74
+ add_offense(redundant_message_argument) do |corrector|
75
+ if node.arguments.one?
76
+ range = redundant_message_argument
77
+ else
78
+ index = node.arguments.index(redundant_message_argument)
79
+ range = node.arguments[index - 1].source_range.end.join(redundant_message_argument.source_range.end)
80
+ end
81
+
82
+ corrector.remove(range)
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -22,12 +22,11 @@ module RuboCop
22
22
  remove_method :on_send
23
23
  def on_send(node)
24
24
  return unless node.method?(:refute)
25
- return unless (arguments = peel_redundant_parentheses_from(node.arguments))
26
- return unless arguments.first.respond_to?(:method?) && arguments.first.method?(:empty?)
27
- return unless arguments.first.arguments.empty?
25
+ return unless node.first_argument.respond_to?(:method?) && node.first_argument.method?(:empty?)
26
+ return unless node.first_argument.arguments.empty?
28
27
 
29
- add_offense(node, message: offense_message(arguments)) do |corrector|
30
- autocorrect(corrector, node, arguments)
28
+ add_offense(node, message: offense_message(node.arguments)) do |corrector|
29
+ autocorrect(corrector, node, node.arguments)
31
30
  end
32
31
  end
33
32
  end
@@ -9,6 +9,9 @@ module RuboCop
9
9
  # @example
10
10
  # # bad
11
11
  # assert("rubocop-minitest" != actual)
12
+ # refute("rubocop-minitest" == actual)
13
+ # assert_operator("rubocop-minitest", :!=, actual)
14
+ # refute_operator("rubocop-minitest", :==, actual)
12
15
  #
13
16
  # # good
14
17
  # refute_equal("rubocop-minitest", actual)
@@ -18,45 +21,38 @@ module RuboCop
18
21
  extend AutoCorrector
19
22
 
20
23
  MSG = 'Prefer using `refute_equal(%<preferred>s)`.'
21
- RESTRICT_ON_SEND = %i[assert].freeze
22
-
23
- def_node_matcher :assert_not_equal, <<~PATTERN
24
- (send nil? :assert (send $_ :!= $_) $... )
24
+ RESTRICT_ON_SEND = %i[assert refute assert_operator refute_operator].freeze
25
+
26
+ def_node_matcher :refute_equal, <<~PATTERN
27
+ {
28
+ (send nil? :assert (send $_ :!= $_) $...)
29
+ (send nil? :refute (send $_ :== $_) $...)
30
+ (send nil? :assert_operator $_ (sym :!=) $_ $...)
31
+ (send nil? :refute_operator $_ (sym :==) $_ $...)
32
+ }
25
33
  PATTERN
26
34
 
35
+ # rubocop:disable Metrics/AbcSize
27
36
  def on_send(node)
28
- preferred = process_not_equal(node)
29
- return unless preferred
30
-
31
- assert_not_equal(node) do |expected, actual|
37
+ refute_equal(node) do |expected, actual, rest_args|
38
+ basic_arguments = "#{expected.source}, #{actual.source}"
39
+ preferred = (message_arg = rest_args.first) ? "#{basic_arguments}, #{message_arg.source}" : basic_arguments
32
40
  message = format(MSG, preferred: preferred)
33
41
 
34
42
  add_offense(node, message: message) do |corrector|
35
43
  corrector.replace(node.loc.selector, 'refute_equal')
36
44
 
37
- replacement = [expected, actual].map(&:source).join(', ')
38
- corrector.replace(node.first_argument, replacement)
39
- end
40
- end
41
- end
42
-
43
- private
45
+ range = if node.method?(:assert) || node.method?(:refute)
46
+ node.first_argument
47
+ else
48
+ node.first_argument.source_range.begin.join(node.arguments[2].source_range.end)
49
+ end
44
50
 
45
- def preferred_usage(first_arg, second_arg, custom_message = nil)
46
- [first_arg, second_arg, custom_message].compact.map(&:source).join(', ')
47
- end
48
-
49
- def original_usage(first_part, custom_message)
50
- [first_part, custom_message].compact.join(', ')
51
- end
52
-
53
- def process_not_equal(node)
54
- assert_not_equal(node) do |first_arg, second_arg, rest_args|
55
- custom_message = rest_args.first
56
-
57
- preferred_usage(first_arg, second_arg, custom_message)
51
+ corrector.replace(range, basic_arguments)
52
+ end
58
53
  end
59
54
  end
55
+ # rubocop:enable Metrics/AbcSize
60
56
  end
61
57
  end
62
58
  end
@@ -11,6 +11,8 @@ module RuboCop
11
11
  # refute(matcher.match(string))
12
12
  # refute(matcher.match?(string))
13
13
  # refute(matcher =~ string)
14
+ # refute_operator(matcher, :=~, string)
15
+ # assert_operator(matcher, :!~, string)
14
16
  # refute(matcher.match(string), 'message')
15
17
  #
16
18
  # # good
@@ -18,10 +20,51 @@ module RuboCop
18
20
  # refute_match(matcher, string, 'message')
19
21
  #
20
22
  class RefuteMatch < Base
21
- extend MinitestCopRule
23
+ include ArgumentRangeHelper
24
+ extend AutoCorrector
22
25
 
23
- define_rule :refute, target_method: %i[match match? =~],
24
- preferred_method: :refute_match, inverse: 'regexp_type?'
26
+ MSG = 'Prefer using `refute_match(%<preferred>s)`.'
27
+ RESTRICT_ON_SEND = %i[refute refute_operator assert_operator].freeze
28
+
29
+ def_node_matcher :refute_match, <<~PATTERN
30
+ {
31
+ (send nil? :refute (send $_ {:match :match? :=~} $_) $...)
32
+ (send nil? :refute_operator $_ (sym :=~) $_ $...)
33
+ (send nil? :assert_operator $_ (sym :!~) $_ $...)
34
+ }
35
+ PATTERN
36
+
37
+ # rubocop:disable Metrics/AbcSize
38
+ def on_send(node)
39
+ refute_match(node) do |expected, actual, rest_args|
40
+ basic_arguments = order_expected_and_actual(expected, actual)
41
+ preferred = (message_arg = rest_args.first) ? "#{basic_arguments}, #{message_arg.source}" : basic_arguments
42
+ message = format(MSG, preferred: preferred)
43
+
44
+ add_offense(node, message: message) do |corrector|
45
+ corrector.replace(node.loc.selector, 'refute_match')
46
+
47
+ range = if node.method?(:refute)
48
+ node.first_argument
49
+ else
50
+ node.first_argument.source_range.begin.join(node.arguments[2].source_range.end)
51
+ end
52
+
53
+ corrector.replace(range, basic_arguments)
54
+ end
55
+ end
56
+ end
57
+ # rubocop:enable Metrics/AbcSize
58
+
59
+ private
60
+
61
+ def order_expected_and_actual(expected, actual)
62
+ if actual.regexp_type?
63
+ [actual, expected]
64
+ else
65
+ [expected, actual]
66
+ end.map(&:source).join(', ')
67
+ end
25
68
  end
26
69
  end
27
70
  end
@@ -40,7 +40,7 @@ module RuboCop
40
40
 
41
41
  def build_new_arguments(node)
42
42
  lhs, op, rhs = *node.first_argument
43
- new_arguments = "#{lhs.source}, :#{op}, #{rhs.source}"
43
+ new_arguments = +"#{lhs.source}, :#{op}, #{rhs.source}"
44
44
 
45
45
  if node.arguments.count == 2
46
46
  new_arguments << ", #{node.last_argument.source}"
@@ -12,14 +12,58 @@ module RuboCop
12
12
  # @example
13
13
  # # bad
14
14
  # refute(expected.equal?(actual))
15
+ # refute_equal(expected.object_id, actual.object_id)
15
16
  #
16
17
  # # good
17
18
  # refute_same(expected, actual)
18
19
  #
19
20
  class RefuteSame < Base
20
- extend MinitestCopRule
21
+ extend AutoCorrector
21
22
 
22
- define_rule :refute, target_method: :equal?, preferred_method: :refute_same
23
+ MSG = 'Prefer using `refute_same(%<new_arguments>s)`.'
24
+ RESTRICT_ON_SEND = %i[refute refute_equal].freeze
25
+
26
+ def_node_matcher :refute_with_equal?, <<~PATTERN
27
+ (send nil? :refute
28
+ $(send $_ :equal? $_)
29
+ $_?)
30
+ PATTERN
31
+
32
+ def_node_matcher :refute_equal_with_object_id?, <<~PATTERN
33
+ (send nil? :refute_equal
34
+ (send $_ :object_id)
35
+ (send $_ :object_id)
36
+ $_?)
37
+ PATTERN
38
+
39
+ # rubocop:disable Metrics/AbcSize
40
+ def on_send(node)
41
+ if (equal_node, expected_node, actual_node, message_node = refute_with_equal?(node))
42
+ add_offense(node, message: message(expected_node, actual_node, message_node.first)) do |corrector|
43
+ corrector.replace(node.loc.selector, 'refute_same')
44
+ corrector.replace(equal_node, "#{expected_node.source}, #{actual_node.source}")
45
+ end
46
+ elsif (expected_node, actual_node, message_node = refute_equal_with_object_id?(node))
47
+ add_offense(node, message: message(expected_node, actual_node, message_node.first)) do |corrector|
48
+ corrector.replace(node.loc.selector, 'refute_same')
49
+ remove_method_call(expected_node.parent, corrector)
50
+ remove_method_call(actual_node.parent, corrector)
51
+ end
52
+ end
53
+ end
54
+ # rubocop:enable Metrics/AbcSize
55
+
56
+ private
57
+
58
+ def message(expected_node, actual_node, message_node)
59
+ arguments = [expected_node, actual_node, message_node].compact.map(&:source).join(', ')
60
+ format(MSG, new_arguments: arguments)
61
+ end
62
+
63
+ def remove_method_call(send_node, corrector)
64
+ range = send_node.loc.dot.join(send_node.loc.selector)
65
+ corrector.remove(range)
66
+ end
23
67
  end
24
68
  end
25
69
  end
@@ -30,6 +30,8 @@ require_relative 'minitest/assert_silent'
30
30
  require_relative 'minitest/assert_truthy'
31
31
  require_relative 'minitest/duplicate_test_run'
32
32
  require_relative 'minitest/empty_line_before_assertion_methods'
33
+ require_relative 'minitest/non_executable_test_method'
34
+ require_relative 'minitest/redundant_message_argument'
33
35
  require_relative 'minitest/return_in_test_method'
34
36
  require_relative 'minitest/test_file_name'
35
37
  require_relative 'minitest/global_expectations'
@@ -18,7 +18,7 @@ module RuboCop
18
18
 
19
19
  def all_arguments_range(node)
20
20
  first_argument = node.first_argument
21
- last_argument = node.arguments.last
21
+ last_argument = node.last_argument
22
22
 
23
23
  range_between(first_argument.source_range.begin_pos, last_argument.source_range.end_pos)
24
24
  end
@@ -45,13 +45,12 @@ module RuboCop
45
45
 
46
46
  def on_send(node)
47
47
  return unless node.method?(:#{assertion_method})
48
- return unless (arguments = peel_redundant_parentheses_from(node.arguments))
49
- return unless arguments.first&.call_type?
50
- return if arguments.first.arguments.empty? ||
51
- #{target_methods}.none? { |target_method| arguments.first.method?(target_method) }
48
+ return unless node.arguments.first&.call_type?
49
+ return if node.arguments.first.arguments.empty? ||
50
+ #{target_methods}.none? { |target_method| node.arguments.first.method?(target_method) }
52
51
 
53
- add_offense(node, message: offense_message(arguments)) do |corrector|
54
- autocorrect(corrector, node, arguments)
52
+ add_offense(node, message: offense_message(node.arguments)) do |corrector|
53
+ autocorrect(corrector, node, node.arguments)
55
54
  end
56
55
  end
57
56
 
@@ -60,21 +59,11 @@ module RuboCop
60
59
 
61
60
  new_arguments = new_arguments(arguments).join(', ')
62
61
 
63
- if enclosed_in_redundant_parentheses?(node)
64
- new_arguments = '(' + new_arguments + ')'
65
- end
66
-
67
62
  corrector.replace(node.first_argument, new_arguments)
68
63
  end
69
64
 
70
65
  private
71
66
 
72
- def peel_redundant_parentheses_from(arguments)
73
- return arguments unless arguments.first&.begin_type?
74
-
75
- peel_redundant_parentheses_from(arguments.first.children)
76
- end
77
-
78
67
  def offense_message(arguments)
79
68
  message_argument = arguments.last if arguments.first != arguments.last
80
69
 
@@ -103,10 +92,6 @@ module RuboCop
103
92
  new_arguments
104
93
  end
105
94
 
106
- def enclosed_in_redundant_parentheses?(node)
107
- node.arguments.first.begin_type?
108
- end
109
-
110
95
  def correct_receiver(receiver)
111
96
  receiver ? receiver.source : 'self'
112
97
  end
@@ -100,6 +100,7 @@ module RuboCop
100
100
  end
101
101
 
102
102
  def assertion_method?(node)
103
+ return assertion_method?(node.expression) if node.assignment?
103
104
  return false if !node.send_type? && !node.block_type? && !node.numblock_type?
104
105
 
105
106
  ASSERTION_PREFIXES.any? do |prefix|
@@ -9,17 +9,13 @@ module RuboCop
9
9
  MSG = 'Prefer using `%<assertion_type>s_predicate(%<new_arguments>s)`.'
10
10
 
11
11
  def on_send(node)
12
- return unless (arguments = peel_redundant_parentheses_from(node.arguments))
12
+ return unless node.first_argument
13
+ return if node.first_argument.block_type? || node.first_argument.numblock_type?
14
+ return unless predicate_method?(node.first_argument)
15
+ return unless node.first_argument.arguments.count.zero?
13
16
 
14
- first_argument = arguments.first
15
-
16
- return unless first_argument
17
- return if first_argument.block_type? || first_argument.numblock_type?
18
- return unless predicate_method?(first_argument)
19
- return unless first_argument.arguments.count.zero?
20
-
21
- add_offense(node, message: offense_message(arguments)) do |corrector|
22
- autocorrect(corrector, node, arguments)
17
+ add_offense(node, message: offense_message(node.arguments)) do |corrector|
18
+ autocorrect(corrector, node, node.arguments)
23
19
  end
24
20
  end
25
21
 
@@ -33,12 +29,6 @@ module RuboCop
33
29
 
34
30
  private
35
31
 
36
- def peel_redundant_parentheses_from(arguments)
37
- return arguments unless arguments.first&.begin_type?
38
-
39
- peel_redundant_parentheses_from(arguments.first.children)
40
- end
41
-
42
32
  def predicate_method?(first_argument)
43
33
  first_argument.respond_to?(:predicate_method?) && first_argument.predicate_method?
44
34
  end
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module Minitest
5
5
  # This module holds the RuboCop Minitest version information.
6
6
  module Version
7
- STRING = '0.32.2'
7
+ STRING = '0.34.0'
8
8
 
9
9
  def self.document_version
10
10
  STRING.match('\d+\.\d+').to_s
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-minitest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.32.2
4
+ version: 0.34.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2023-09-27 00:00:00.000000000 Z
13
+ date: 2023-12-16 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rubocop
@@ -32,6 +32,26 @@ dependencies:
32
32
  - - "<"
33
33
  - !ruby/object:Gem::Version
34
34
  version: '2.0'
35
+ - !ruby/object:Gem::Dependency
36
+ name: rubocop-ast
37
+ requirement: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: 1.30.0
42
+ - - "<"
43
+ - !ruby/object:Gem::Version
44
+ version: '2.0'
45
+ type: :runtime
46
+ prerelease: false
47
+ version_requirements: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: 1.30.0
52
+ - - "<"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
35
55
  description: |
36
56
  Automatic Minitest code style checking tool.
37
57
  A RuboCop extension focused on enforcing Minitest best practices and coding conventions.
@@ -74,7 +94,9 @@ files:
74
94
  - lib/rubocop/cop/minitest/multiple_assertions.rb
75
95
  - lib/rubocop/cop/minitest/no_assertions.rb
76
96
  - lib/rubocop/cop/minitest/no_test_cases.rb
97
+ - lib/rubocop/cop/minitest/non_executable_test_method.rb
77
98
  - lib/rubocop/cop/minitest/non_public_test_method.rb
99
+ - lib/rubocop/cop/minitest/redundant_message_argument.rb
78
100
  - lib/rubocop/cop/minitest/refute_empty.rb
79
101
  - lib/rubocop/cop/minitest/refute_equal.rb
80
102
  - lib/rubocop/cop/minitest/refute_false.rb
@@ -117,7 +139,7 @@ metadata:
117
139
  homepage_uri: https://docs.rubocop.org/rubocop-minitest/
118
140
  changelog_uri: https://github.com/rubocop/rubocop-minitest/blob/master/CHANGELOG.md
119
141
  source_code_uri: https://github.com/rubocop/rubocop-minitest
120
- documentation_uri: https://docs.rubocop.org/rubocop-minitest/0.32
142
+ documentation_uri: https://docs.rubocop.org/rubocop-minitest/0.34
121
143
  bug_tracker_uri: https://github.com/rubocop/rubocop-minitest/issues
122
144
  rubygems_mfa_required: 'true'
123
145
  post_install_message:
@@ -135,7 +157,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
157
  - !ruby/object:Gem::Version
136
158
  version: '0'
137
159
  requirements: []
138
- rubygems_version: 3.4.19
160
+ rubygems_version: 3.1.6
139
161
  signing_key:
140
162
  specification_version: 4
141
163
  summary: Automatic Minitest code style checking tool.