rubocop-minitest 0.10.2 → 0.12.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +3 -3
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +5 -1
  4. data/.rubocop.yml +4 -1
  5. data/CHANGELOG.md +96 -51
  6. data/CONTRIBUTING.md +3 -3
  7. data/Gemfile +2 -2
  8. data/LICENSE.txt +1 -1
  9. data/README.md +4 -4
  10. data/Rakefile +1 -1
  11. data/bin/console +2 -0
  12. data/config/default.yml +15 -4
  13. data/docs/antora.yml +1 -1
  14. data/docs/modules/ROOT/pages/cops.adoc +2 -0
  15. data/docs/modules/ROOT/pages/cops_minitest.adoc +78 -7
  16. data/docs/modules/ROOT/pages/index.adoc +1 -1
  17. data/legacy-docs/cops_minitest.md +16 -16
  18. data/legacy-docs/index.md +1 -1
  19. data/lib/rubocop/cop/minitest/assert_empty.rb +1 -1
  20. data/lib/rubocop/cop/minitest/assert_empty_literal.rb +12 -16
  21. data/lib/rubocop/cop/minitest/assert_equal.rb +1 -1
  22. data/lib/rubocop/cop/minitest/assert_in_delta.rb +4 -1
  23. data/lib/rubocop/cop/minitest/assert_includes.rb +1 -1
  24. data/lib/rubocop/cop/minitest/assert_instance_of.rb +1 -1
  25. data/lib/rubocop/cop/minitest/assert_kind_of.rb +1 -1
  26. data/lib/rubocop/cop/minitest/assert_match.rb +1 -1
  27. data/lib/rubocop/cop/minitest/assert_nil.rb +5 -11
  28. data/lib/rubocop/cop/minitest/assert_output.rb +1 -1
  29. data/lib/rubocop/cop/minitest/assert_path_exists.rb +6 -12
  30. data/lib/rubocop/cop/minitest/assert_respond_to.rb +1 -1
  31. data/lib/rubocop/cop/minitest/assert_silent.rb +8 -6
  32. data/lib/rubocop/cop/minitest/assert_truthy.rb +5 -11
  33. data/lib/rubocop/cop/minitest/assert_with_expected_argument.rb +41 -0
  34. data/lib/rubocop/cop/minitest/assertion_in_lifecycle_hook.rb +1 -1
  35. data/lib/rubocop/cop/minitest/global_expectations.rb +6 -7
  36. data/lib/rubocop/cop/minitest/literal_as_actual_argument.rb +15 -14
  37. data/lib/rubocop/cop/minitest/multiple_assertions.rb +2 -2
  38. data/lib/rubocop/cop/minitest/no_assertions.rb +48 -0
  39. data/lib/rubocop/cop/minitest/refute_empty.rb +1 -1
  40. data/lib/rubocop/cop/minitest/refute_equal.rb +6 -7
  41. data/lib/rubocop/cop/minitest/refute_false.rb +15 -22
  42. data/lib/rubocop/cop/minitest/refute_in_delta.rb +4 -1
  43. data/lib/rubocop/cop/minitest/refute_includes.rb +1 -1
  44. data/lib/rubocop/cop/minitest/refute_instance_of.rb +1 -1
  45. data/lib/rubocop/cop/minitest/refute_kind_of.rb +1 -1
  46. data/lib/rubocop/cop/minitest/refute_match.rb +1 -1
  47. data/lib/rubocop/cop/minitest/refute_nil.rb +4 -8
  48. data/lib/rubocop/cop/minitest/refute_path_exists.rb +6 -12
  49. data/lib/rubocop/cop/minitest/refute_respond_to.rb +1 -1
  50. data/lib/rubocop/cop/minitest/test_method_name.rb +18 -8
  51. data/lib/rubocop/cop/minitest/unspecified_exception.rb +1 -1
  52. data/lib/rubocop/cop/minitest_cops.rb +2 -0
  53. data/lib/rubocop/cop/mixin/in_delta_mixin.rb +5 -15
  54. data/lib/rubocop/cop/mixin/minitest_cop_rule.rb +12 -12
  55. data/lib/rubocop/cop/mixin/minitest_exploration_helpers.rb +20 -3
  56. data/lib/rubocop/minitest/version.rb +1 -1
  57. data/mkdocs.yml +2 -2
  58. data/relnotes/v0.1.0.md +1 -1
  59. data/relnotes/v0.10.0.md +12 -12
  60. data/relnotes/v0.10.1.md +1 -1
  61. data/relnotes/v0.10.2.md +1 -1
  62. data/relnotes/v0.10.3.md +5 -0
  63. data/relnotes/v0.11.0.md +16 -0
  64. data/relnotes/v0.11.1.md +5 -0
  65. data/relnotes/v0.12.0.md +10 -0
  66. data/relnotes/v0.12.1.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 +9 -11
  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.loc.name, 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 $_ $_ $...)