rubocop-minitest 0.10.3 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +0 -3
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +5 -1
  4. data/.rubocop.yml +4 -1
  5. data/CHANGELOG.md +97 -52
  6. data/CONTRIBUTING.md +3 -3
  7. data/Gemfile +2 -2
  8. data/README.md +4 -4
  9. data/Rakefile +1 -1
  10. data/bin/console +2 -0
  11. data/config/default.yml +15 -4
  12. data/docs/antora.yml +1 -1
  13. data/docs/modules/ROOT/pages/cops.adoc +2 -0
  14. data/docs/modules/ROOT/pages/cops_minitest.adoc +71 -7
  15. data/docs/modules/ROOT/pages/index.adoc +1 -1
  16. data/legacy-docs/cops_minitest.md +16 -16
  17. data/legacy-docs/index.md +1 -1
  18. data/lib/rubocop/cop/minitest/assert_empty.rb +1 -1
  19. data/lib/rubocop/cop/minitest/assert_empty_literal.rb +12 -16
  20. data/lib/rubocop/cop/minitest/assert_equal.rb +1 -1
  21. data/lib/rubocop/cop/minitest/assert_in_delta.rb +4 -1
  22. data/lib/rubocop/cop/minitest/assert_includes.rb +1 -1
  23. data/lib/rubocop/cop/minitest/assert_instance_of.rb +1 -1
  24. data/lib/rubocop/cop/minitest/assert_kind_of.rb +1 -1
  25. data/lib/rubocop/cop/minitest/assert_match.rb +1 -1
  26. data/lib/rubocop/cop/minitest/assert_nil.rb +5 -11
  27. data/lib/rubocop/cop/minitest/assert_output.rb +1 -1
  28. data/lib/rubocop/cop/minitest/assert_path_exists.rb +6 -12
  29. data/lib/rubocop/cop/minitest/assert_respond_to.rb +1 -1
  30. data/lib/rubocop/cop/minitest/assert_silent.rb +8 -6
  31. data/lib/rubocop/cop/minitest/assert_truthy.rb +5 -11
  32. data/lib/rubocop/cop/minitest/assert_with_expected_argument.rb +41 -0
  33. data/lib/rubocop/cop/minitest/assertion_in_lifecycle_hook.rb +1 -1
  34. data/lib/rubocop/cop/minitest/global_expectations.rb +6 -7
  35. data/lib/rubocop/cop/minitest/literal_as_actual_argument.rb +15 -14
  36. data/lib/rubocop/cop/minitest/multiple_assertions.rb +2 -2
  37. data/lib/rubocop/cop/minitest/no_assertions.rb +48 -0
  38. data/lib/rubocop/cop/minitest/refute_empty.rb +1 -1
  39. data/lib/rubocop/cop/minitest/refute_equal.rb +6 -7
  40. data/lib/rubocop/cop/minitest/refute_false.rb +15 -22
  41. data/lib/rubocop/cop/minitest/refute_in_delta.rb +4 -1
  42. data/lib/rubocop/cop/minitest/refute_includes.rb +1 -1
  43. data/lib/rubocop/cop/minitest/refute_instance_of.rb +1 -1
  44. data/lib/rubocop/cop/minitest/refute_kind_of.rb +1 -1
  45. data/lib/rubocop/cop/minitest/refute_match.rb +1 -1
  46. data/lib/rubocop/cop/minitest/refute_nil.rb +4 -8
  47. data/lib/rubocop/cop/minitest/refute_path_exists.rb +6 -12
  48. data/lib/rubocop/cop/minitest/refute_respond_to.rb +1 -1
  49. data/lib/rubocop/cop/minitest/test_method_name.rb +9 -8
  50. data/lib/rubocop/cop/minitest/unspecified_exception.rb +1 -1
  51. data/lib/rubocop/cop/minitest_cops.rb +2 -0
  52. data/lib/rubocop/cop/mixin/in_delta_mixin.rb +5 -15
  53. data/lib/rubocop/cop/mixin/minitest_cop_rule.rb +12 -12
  54. data/lib/rubocop/cop/mixin/minitest_exploration_helpers.rb +14 -4
  55. data/lib/rubocop/minitest/version.rb +1 -1
  56. data/mkdocs.yml +1 -1
  57. data/relnotes/v0.1.0.md +1 -1
  58. data/relnotes/v0.10.0.md +12 -12
  59. data/relnotes/v0.10.1.md +1 -1
  60. data/relnotes/v0.10.2.md +1 -1
  61. data/relnotes/v0.10.3.md +1 -1
  62. data/relnotes/v0.11.0.md +16 -0
  63. data/relnotes/v0.11.1.md +5 -0
  64. data/relnotes/v0.12.0.md +10 -0
  65. data/relnotes/v0.12.1.md +5 -0
  66. data/relnotes/v0.13.0.md +5 -0
  67. data/relnotes/v0.2.0.md +4 -4
  68. data/relnotes/v0.2.1.md +1 -1
  69. data/relnotes/v0.3.0.md +6 -6
  70. data/relnotes/v0.4.0.md +5 -5
  71. data/relnotes/v0.4.1.md +1 -1
  72. data/relnotes/v0.5.0.md +1 -1
  73. data/relnotes/v0.5.1.md +1 -1
  74. data/relnotes/v0.6.0.md +1 -1
  75. data/relnotes/v0.6.1.md +2 -2
  76. data/relnotes/v0.6.2.md +1 -1
  77. data/relnotes/v0.7.0.md +5 -5
  78. data/relnotes/v0.8.0.md +4 -4
  79. data/relnotes/v0.8.1.md +1 -1
  80. data/relnotes/v0.9.0.md +3 -3
  81. data/rubocop-minitest.gemspec +5 -5
  82. data/tasks/cops_documentation.rake +10 -12
  83. metadata +17 -10
@@ -15,7 +15,7 @@ module RuboCop
15
15
  # # good
16
16
  # assert_output(expected) { puts object.method }
17
17
  #
18
- class AssertOutput < Cop
18
+ class AssertOutput < Base
19
19
  include MinitestExplorationHelpers
20
20
 
21
21
  MSG = 'Use `assert_output` instead of mutating %<name>s.'
@@ -15,8 +15,11 @@ module RuboCop
15
15
  # assert_path_exists(path)
16
16
  # assert_path_exists(path, 'message')
17
17
  #
18
- class AssertPathExists < Cop
18
+ class AssertPathExists < Base
19
+ extend AutoCorrector
20
+
19
21
  MSG = 'Prefer using `%<good_method>s` over `%<bad_method>s`.'
22
+ RESTRICT_ON_SEND = %i[assert].freeze
20
23
 
21
24
  def_node_matcher :assert_file_exists, <<~PATTERN
22
25
  (send nil? :assert
@@ -31,17 +34,8 @@ module RuboCop
31
34
  good_method = build_good_method(path, failure_message)
32
35
  message = format(MSG, good_method: good_method, bad_method: node.source)
33
36
 
34
- add_offense(node, message: message)
35
- end
36
- end
37
-
38
- def autocorrect(node)
39
- assert_file_exists(node) do |path, failure_message|
40
- failure_message = failure_message.first
41
-
42
- lambda do |corrector|
43
- replacement = build_good_method(path, failure_message)
44
- corrector.replace(node, replacement)
37
+ add_offense(node, message: message) do |corrector|
38
+ corrector.replace(node, good_method)
45
39
  end
46
40
  end
47
41
  end
@@ -17,7 +17,7 @@ module RuboCop
17
17
  # assert_respond_to(object, :do_something, 'message')
18
18
  # assert_respond_to(self, :do_something)
19
19
  #
20
- class AssertRespondTo < Cop
20
+ class AssertRespondTo < Base
21
21
  extend MinitestCopRule
22
22
 
23
23
  define_rule :assert, target_method: :respond_to?
@@ -13,7 +13,9 @@ module RuboCop
13
13
  # # good
14
14
  # assert_silent { puts object.do_something }
15
15
  #
16
- class AssertSilent < Cop
16
+ class AssertSilent < Base
17
+ extend AutoCorrector
18
+
17
19
  MSG = 'Prefer using `assert_silent` over `assert_output("", "")`.'
18
20
 
19
21
  def_node_matcher :assert_silent_candidate?, <<~PATTERN
@@ -25,12 +27,12 @@ module RuboCop
25
27
  PATTERN
26
28
 
27
29
  def on_block(node)
28
- add_offense(node.send_node) if assert_silent_candidate?(node)
29
- end
30
+ return unless assert_silent_candidate?(node)
31
+
32
+ send_node = node.send_node
30
33
 
31
- def autocorrect(node)
32
- lambda do |corrector|
33
- corrector.replace(node, 'assert_silent')
34
+ add_offense(send_node) do |corrector|
35
+ corrector.replace(send_node, 'assert_silent')
34
36
  end
35
37
  end
36
38
 
@@ -15,11 +15,13 @@ module RuboCop
15
15
  # assert(actual)
16
16
  # assert(actual, 'message')
17
17
  #
18
- class AssertTruthy < Cop
18
+ class AssertTruthy < Base
19
19
  include ArgumentRangeHelper
20
+ extend AutoCorrector
20
21
 
21
22
  MSG = 'Prefer using `assert(%<arguments>s)` over ' \
22
23
  '`assert_equal(true, %<arguments>s)`.'
24
+ RESTRICT_ON_SEND = %i[assert_equal].freeze
23
25
 
24
26
  def_node_matcher :assert_equal_with_truthy, <<~PATTERN
25
27
  (send nil? :assert_equal true $_ $...)
@@ -31,17 +33,9 @@ module RuboCop
31
33
 
32
34
  arguments = [actual.source, message&.source].compact.join(', ')
33
35
 
34
- add_offense(node, message: format(MSG, arguments: arguments))
35
- end
36
- end
37
-
38
- def autocorrect(node)
39
- lambda do |corrector|
40
- assert_equal_with_truthy(node) do |actual|
36
+ add_offense(node, message: format(MSG, arguments: arguments)) do |corrector|
41
37
  corrector.replace(node.loc.selector, 'assert')
42
- corrector.replace(
43
- first_and_second_arguments_range(node), actual.source
44
- )
38
+ corrector.replace(first_and_second_arguments_range(node), actual.source)
45
39
  end
46
40
  end
47
41
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Minitest
6
+ # This cop tries to detect when a user accidentally used
7
+ # `assert` when they meant to use `assert_equal`.
8
+ #
9
+ # It is marked as unsafe because it is not possible to determine
10
+ # whether the second argument of `assert` is a message or not.
11
+ #
12
+ # @example
13
+ # # bad
14
+ # assert(3, my_list.length)
15
+ # assert(expected, actual)
16
+ #
17
+ # # good
18
+ # assert_equal(3, my_list.length)
19
+ # assert_equal(expected, actual)
20
+ # assert(foo, 'message')
21
+ #
22
+ class AssertWithExpectedArgument < Base
23
+ MSG = 'Did you mean to use `assert_equal(%<arguments>s)`?'
24
+ RESTRICT_ON_SEND = %i[assert].freeze
25
+
26
+ def_node_matcher :assert_with_two_arguments?, <<~PATTERN
27
+ (send nil? :assert $_ $_)
28
+ PATTERN
29
+
30
+ def on_send(node)
31
+ assert_with_two_arguments?(node) do |_expected, message|
32
+ return if message.str_type? || message.dstr_type?
33
+
34
+ arguments = node.arguments.map(&:source).join(', ')
35
+ add_offense(node, message: format(MSG, arguments: arguments))
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -20,7 +20,7 @@ module RuboCop
20
20
  # end
21
21
  # end
22
22
  #
23
- class AssertionInLifecycleHook < Cop
23
+ class AssertionInLifecycleHook < Base
24
24
  include MinitestExplorationHelpers
25
25
 
26
26
  MSG = 'Do not use `%<assertion>s` in `%<hook>s` hook.'
@@ -16,7 +16,9 @@ module RuboCop
16
16
  # _(musts).must_equal expected_musts
17
17
  # _(wonts).wont_match expected_wonts
18
18
  # _ { musts }.must_raise TypeError
19
- class GlobalExpectations < Cop
19
+ class GlobalExpectations < Base
20
+ extend AutoCorrector
21
+
20
22
  MSG = 'Use `%<preferred>s` instead.'
21
23
 
22
24
  VALUE_MATCHERS = %i[
@@ -30,6 +32,8 @@ module RuboCop
30
32
 
31
33
  BLOCK_MATCHERS = %i[must_output must_raise must_be_silent must_throw].freeze
32
34
 
35
+ RESTRICT_ON_SEND = VALUE_MATCHERS + BLOCK_MATCHERS
36
+
33
37
  VALUE_MATCHERS_STR = VALUE_MATCHERS.map do |m|
34
38
  ":#{m}"
35
39
  end.join(' ').freeze
@@ -62,13 +66,8 @@ module RuboCop
62
66
  return unless value_global_expectation?(node) || block_global_expectation?(node)
63
67
 
64
68
  message = format(MSG, preferred: preferred_receiver(node))
65
- add_offense(node, location: node.receiver.source_range, message: message)
66
- end
67
-
68
- def autocorrect(node)
69
- return unless value_global_expectation?(node) || block_global_expectation?(node)
70
69
 
71
- lambda do |corrector|
70
+ add_offense(node.receiver.source_range, message: message) do |corrector|
72
71
  receiver = node.receiver.source_range
73
72
 
74
73
  if BLOCK_MATCHERS.include?(node.method_name)
@@ -17,34 +17,35 @@ module RuboCop
17
17
  # assert_equal [1, 2], foo
18
18
  # assert_equal [1, 2], foo, 'message'
19
19
  #
20
- class LiteralAsActualArgument < Cop
20
+ class LiteralAsActualArgument < Base
21
21
  include ArgumentRangeHelper
22
+ extend AutoCorrector
22
23
 
23
24
  MSG = 'Replace the literal with the first argument.'
25
+ RESTRICT_ON_SEND = %i[assert_equal].freeze
24
26
 
25
27
  def on_send(node)
26
28
  return unless node.method?(:assert_equal)
27
29
 
28
30
  actual = node.arguments[1]
29
- return unless actual
31
+ return unless actual&.recursive_basic_literal?
30
32
 
31
- add_offense(node, location: all_arguments_range(node)) if actual.recursive_basic_literal?
33
+ add_offense(all_arguments_range(node)) do |corrector|
34
+ autocorrect(corrector, node)
35
+ end
32
36
  end
33
37
 
34
- def autocorrect(node)
38
+ def autocorrect(corrector, node)
35
39
  expected, actual, message = *node.arguments
36
40
 
37
- lambda do |corrector|
38
- new_actual_source =
39
- if actual.hash_type? && !actual.braces?
40
- "{#{actual.source}}"
41
- else
42
- actual.source
43
- end
44
- arguments = [new_actual_source, expected.source, message&.source].compact.join(', ')
41
+ new_actual_source = if actual.hash_type? && !actual.braces?
42
+ "{#{actual.source}}"
43
+ else
44
+ actual.source
45
+ end
46
+ arguments = [new_actual_source, expected.source, message&.source].compact.join(', ')
45
47
 
46
- corrector.replace(node, "assert_equal(#{arguments})")
47
- end
48
+ corrector.replace(node, "assert_equal(#{arguments})")
48
49
  end
49
50
  end
50
51
  end
@@ -26,7 +26,7 @@ module RuboCop
26
26
  # end
27
27
  # end
28
28
  #
29
- class MultipleAssertions < Cop
29
+ class MultipleAssertions < Base
30
30
  include ConfigurableMax
31
31
  include MinitestExplorationHelpers
32
32
 
@@ -43,7 +43,7 @@ module RuboCop
43
43
  self.max = assertions_count
44
44
 
45
45
  message = format(MSG, total: assertions_count, max: max_assertions)
46
- add_offense(node, location: :name, message: message)
46
+ add_offense(node, message: message)
47
47
  end
48
48
  end
49
49
 
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Minitest
6
+ # This cop checks if test cases contain any assertion calls.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # class FooTest < Minitest::Test
11
+ # def test_the_truth
12
+ # end
13
+ # end
14
+ #
15
+ # # good
16
+ # class FooTest < Minitest::Test
17
+ # def test_the_truth
18
+ # assert true
19
+ # end
20
+ # end
21
+ #
22
+ class NoAssertions < Base
23
+ include MinitestExplorationHelpers
24
+
25
+ MSG = 'Test case has no assertions.'
26
+
27
+ def on_class(class_node)
28
+ return unless test_class?(class_node)
29
+
30
+ test_cases(class_node).each do |node|
31
+ assertions_count = assertions_count(node)
32
+
33
+ next if assertions_count.positive?
34
+
35
+ add_offense(node.block_type? ? node.loc.expression : node.loc.name)
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def assertions_count(node)
42
+ base = assertion?(node) ? 1 : 0
43
+ base + node.each_child_node.sum { |c| assertions_count(c) }
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -15,7 +15,7 @@ module RuboCop
15
15
  # refute_empty(object)
16
16
  # refute_empty(object, 'message')
17
17
  #
18
- class RefuteEmpty < Cop
18
+ class RefuteEmpty < Base
19
19
  extend MinitestCopRule
20
20
 
21
21
  define_rule :refute, target_method: :empty?
@@ -14,11 +14,13 @@ module RuboCop
14
14
  # # good
15
15
  # refute_equal("rubocop-minitest", actual)
16
16
  #
17
- class RefuteEqual < Cop
17
+ class RefuteEqual < Base
18
18
  include ArgumentRangeHelper
19
+ extend AutoCorrector
19
20
 
20
21
  MSG = 'Prefer using `refute_equal(%<preferred>s)` over ' \
21
22
  '`assert(%<over>s)`.'
23
+ RESTRICT_ON_SEND = %i[assert].freeze
22
24
 
23
25
  def_node_matcher :assert_not_equal, <<~PATTERN
24
26
  (send nil? :assert ${(send $_ :!= $_) (send (send $_ :! ) :== $_) } $... )
@@ -28,13 +30,10 @@ module RuboCop
28
30
  preferred, over = process_not_equal(node)
29
31
  return unless preferred && over
30
32
 
31
- message = format(MSG, preferred: preferred, over: over)
32
- add_offense(node, message: message)
33
- end
33
+ assert_not_equal(node) do |_, expected, actual|
34
+ message = format(MSG, preferred: preferred, over: over)
34
35
 
35
- def autocorrect(node)
36
- lambda do |corrector|
37
- assert_not_equal(node) do |_, expected, actual|
36
+ add_offense(node, message: message) do |corrector|
38
37
  corrector.replace(node.loc.selector, 'refute_equal')
39
38
 
40
39
  replacement = [expected, actual].map(&:source).join(', ')
@@ -18,13 +18,15 @@ module RuboCop
18
18
  # refute(actual)
19
19
  # refute(actual, 'message')
20
20
  #
21
- class RefuteFalse < Cop
21
+ class RefuteFalse < Base
22
22
  include ArgumentRangeHelper
23
+ extend AutoCorrector
23
24
 
24
25
  MSG_FOR_ASSERT_EQUAL = 'Prefer using `refute(%<arguments>s)` over ' \
25
26
  '`assert_equal(false, %<arguments>s)`.'
26
27
  MSG_FOR_ASSERT = 'Prefer using `refute(%<arguments>s)` over ' \
27
28
  '`assert(!%<arguments>s)`.'
29
+ RESTRICT_ON_SEND = %i[assert_equal assert].freeze
28
30
 
29
31
  def_node_matcher :assert_equal_with_false, <<~PATTERN
30
32
  (send nil? :assert_equal false $_ $...)
@@ -35,38 +37,29 @@ module RuboCop
35
37
  PATTERN
36
38
 
37
39
  def on_send(node)
38
- actual, rest_receiver_arg = assert_equal_with_false(node) ||
39
- assert_with_bang_argument(node)
40
+ actual, rest_receiver_arg = assert_equal_with_false(node) || assert_with_bang_argument(node)
40
41
  return unless actual
41
42
 
42
43
  message_argument = rest_receiver_arg.first
43
44
 
44
45
  arguments = [actual.source, message_argument&.source].compact.join(', ')
45
46
 
46
- message = if node.method?(:assert_equal)
47
- MSG_FOR_ASSERT_EQUAL
48
- else
49
- MSG_FOR_ASSERT
50
- end
47
+ message = node.method?(:assert_equal) ? MSG_FOR_ASSERT_EQUAL : MSG_FOR_ASSERT
51
48
 
52
- add_offense(node, message: format(message, arguments: arguments))
49
+ add_offense(node, message: format(message, arguments: arguments)) do |corrector|
50
+ autocorrect(corrector, node, actual)
51
+ end
53
52
  end
54
53
 
55
- def autocorrect(node)
56
- lambda do |corrector|
57
- corrector.replace(node.loc.selector, 'refute')
54
+ private
58
55
 
59
- assert_equal_with_false(node) do |actual|
60
- corrector.replace(
61
- first_and_second_arguments_range(node), actual.source
62
- )
63
- end
56
+ def autocorrect(corrector, node, actual)
57
+ corrector.replace(node.loc.selector, 'refute')
64
58
 
65
- assert_with_bang_argument(node) do |actual|
66
- corrector.replace(
67
- first_argument_range(node), actual.source
68
- )
69
- end
59
+ if node.method?(:assert_equal)
60
+ corrector.replace(first_and_second_arguments_range(node), actual.source)
61
+ else
62
+ corrector.replace(first_argument_range(node), actual.source)
70
63
  end
71
64
  end
72
65
  end
@@ -15,8 +15,11 @@ module RuboCop
15
15
  # refute_in_delta(0.2, actual)
16
16
  # refute_in_delta(0.2, actual, 0.001, 'message')
17
17
  #
18
- class RefuteInDelta < Cop
18
+ class RefuteInDelta < Base
19
19
  include InDeltaMixin
20
+ extend AutoCorrector
21
+
22
+ RESTRICT_ON_SEND = %i[refute_equal].freeze
20
23
 
21
24
  def_node_matcher :equal_floats_call, <<~PATTERN
22
25
  (send nil? :refute_equal $_ $_ $...)