rubocop-minitest 0.10.1 → 0.12.0

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 +18 -3
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +5 -1
  4. data/.rubocop.yml +5 -1
  5. data/.rubocop_todo.yml +8 -7
  6. data/CHANGELOG.md +95 -50
  7. data/CONTRIBUTING.md +3 -3
  8. data/Gemfile +2 -2
  9. data/LICENSE.txt +1 -1
  10. data/README.md +18 -2
  11. data/Rakefile +1 -1
  12. data/bin/console +2 -0
  13. data/config/default.yml +15 -4
  14. data/docs/antora.yml +1 -1
  15. data/docs/modules/ROOT/pages/cops.adoc +14 -1
  16. data/docs/modules/ROOT/pages/cops_minitest.adoc +79 -8
  17. data/docs/modules/ROOT/pages/index.adoc +1 -1
  18. data/legacy-docs/cops_minitest.md +16 -16
  19. data/legacy-docs/index.md +1 -1
  20. data/lib/rubocop/cop/minitest/assert_empty.rb +1 -1
  21. data/lib/rubocop/cop/minitest/assert_empty_literal.rb +12 -16
  22. data/lib/rubocop/cop/minitest/assert_equal.rb +1 -1
  23. data/lib/rubocop/cop/minitest/assert_in_delta.rb +4 -1
  24. data/lib/rubocop/cop/minitest/assert_includes.rb +1 -1
  25. data/lib/rubocop/cop/minitest/assert_instance_of.rb +1 -1
  26. data/lib/rubocop/cop/minitest/assert_kind_of.rb +1 -1
  27. data/lib/rubocop/cop/minitest/assert_match.rb +1 -1
  28. data/lib/rubocop/cop/minitest/assert_nil.rb +5 -11
  29. data/lib/rubocop/cop/minitest/assert_output.rb +1 -1
  30. data/lib/rubocop/cop/minitest/assert_path_exists.rb +6 -12
  31. data/lib/rubocop/cop/minitest/assert_respond_to.rb +1 -1
  32. data/lib/rubocop/cop/minitest/assert_silent.rb +8 -6
  33. data/lib/rubocop/cop/minitest/assert_truthy.rb +5 -11
  34. data/lib/rubocop/cop/minitest/assert_with_expected_argument.rb +41 -0
  35. data/lib/rubocop/cop/minitest/assertion_in_lifecycle_hook.rb +1 -1
  36. data/lib/rubocop/cop/minitest/global_expectations.rb +6 -7
  37. data/lib/rubocop/cop/minitest/literal_as_actual_argument.rb +15 -14
  38. data/lib/rubocop/cop/minitest/multiple_assertions.rb +2 -2
  39. data/lib/rubocop/cop/minitest/no_assertions.rb +48 -0
  40. data/lib/rubocop/cop/minitest/refute_empty.rb +1 -1
  41. data/lib/rubocop/cop/minitest/refute_equal.rb +7 -8
  42. data/lib/rubocop/cop/minitest/refute_false.rb +15 -22
  43. data/lib/rubocop/cop/minitest/refute_in_delta.rb +4 -1
  44. data/lib/rubocop/cop/minitest/refute_includes.rb +1 -1
  45. data/lib/rubocop/cop/minitest/refute_instance_of.rb +1 -1
  46. data/lib/rubocop/cop/minitest/refute_kind_of.rb +1 -1
  47. data/lib/rubocop/cop/minitest/refute_match.rb +1 -1
  48. data/lib/rubocop/cop/minitest/refute_nil.rb +4 -8
  49. data/lib/rubocop/cop/minitest/refute_path_exists.rb +6 -12
  50. data/lib/rubocop/cop/minitest/refute_respond_to.rb +1 -1
  51. data/lib/rubocop/cop/minitest/test_method_name.rb +18 -8
  52. data/lib/rubocop/cop/minitest/unspecified_exception.rb +1 -1
  53. data/lib/rubocop/cop/minitest_cops.rb +2 -0
  54. data/lib/rubocop/cop/mixin/in_delta_mixin.rb +5 -15
  55. data/lib/rubocop/cop/mixin/minitest_cop_rule.rb +13 -13
  56. data/lib/rubocop/cop/mixin/minitest_exploration_helpers.rb +27 -3
  57. data/lib/rubocop/minitest/version.rb +8 -1
  58. data/mkdocs.yml +2 -2
  59. data/relnotes/v0.1.0.md +1 -1
  60. data/relnotes/v0.10.0.md +12 -12
  61. data/relnotes/v0.10.1.md +1 -1
  62. data/relnotes/v0.10.2.md +5 -0
  63. data/relnotes/v0.10.3.md +5 -0
  64. data/relnotes/v0.11.0.md +16 -0
  65. data/relnotes/v0.11.1.md +5 -0
  66. data/relnotes/v0.12.0.md +10 -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 +7 -7
  82. data/tasks/cops_documentation.rake +24 -304
  83. metadata +28 -15
@@ -13,7 +13,7 @@ module RuboCop
13
13
  # # good
14
14
  # assert_equal("rubocop-minitest", actual)
15
15
  #
16
- class AssertEqual < Cop
16
+ class AssertEqual < Base
17
17
  extend MinitestCopRule
18
18
 
19
19
  define_rule :assert, target_method: :==, preferred_method: :assert_equal
@@ -15,8 +15,11 @@ module RuboCop
15
15
  # assert_in_delta(0.2, actual)
16
16
  # assert_in_delta(0.2, actual, 0.001, 'message')
17
17
  #
18
- class AssertInDelta < Cop
18
+ class AssertInDelta < Base
19
19
  include InDeltaMixin
20
+ extend AutoCorrector
21
+
22
+ RESTRICT_ON_SEND = %i[assert_equal].freeze
20
23
 
21
24
  def_node_matcher :equal_floats_call, <<~PATTERN
22
25
  (send nil? :assert_equal $_ $_ $...)
@@ -15,7 +15,7 @@ module RuboCop
15
15
  # assert_includes(collection, object)
16
16
  # assert_includes(collection, object, 'message')
17
17
  #
18
- class AssertIncludes < Cop
18
+ class AssertIncludes < Base
19
19
  extend MinitestCopRule
20
20
 
21
21
  define_rule :assert, target_method: :include?, preferred_method: :assert_includes
@@ -15,7 +15,7 @@ module RuboCop
15
15
  # assert_instance_of(Class, object)
16
16
  # assert_instance_of(Class, object, 'message')
17
17
  #
18
- class AssertInstanceOf < Cop
18
+ class AssertInstanceOf < Base
19
19
  extend MinitestCopRule
20
20
 
21
21
  define_rule :assert, target_method: :instance_of?, inverse: true
@@ -15,7 +15,7 @@ module RuboCop
15
15
  # assert_kind_of(Class, object)
16
16
  # assert_kind_of(Class, object, 'message')
17
17
  #
18
- class AssertKindOf < Cop
18
+ class AssertKindOf < Base
19
19
  extend MinitestCopRule
20
20
 
21
21
  define_rule :assert, target_method: :kind_of?, inverse: true
@@ -15,7 +15,7 @@ module RuboCop
15
15
  # assert_match(regex, string)
16
16
  # assert_match(matcher, string, 'message')
17
17
  #
18
- class AssertMatch < Cop
18
+ class AssertMatch < Base
19
19
  extend MinitestCopRule
20
20
 
21
21
  define_rule :assert, target_method: :match
@@ -15,11 +15,13 @@ module RuboCop
15
15
  # assert_nil(actual)
16
16
  # assert_nil(actual, 'message')
17
17
  #
18
- class AssertNil < Cop
18
+ class AssertNil < Base
19
19
  include ArgumentRangeHelper
20
+ extend AutoCorrector
20
21
 
21
22
  MSG = 'Prefer using `assert_nil(%<arguments>s)` over ' \
22
23
  '`assert_equal(nil, %<arguments>s)`.'
24
+ RESTRICT_ON_SEND = %i[assert_equal].freeze
23
25
 
24
26
  def_node_matcher :assert_equal_with_nil, <<~PATTERN
25
27
  (send nil? :assert_equal nil $_ $...)
@@ -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_nil(node) do |actual|
36
+ add_offense(node, message: format(MSG, arguments: arguments)) do |corrector|
41
37
  corrector.replace(node.loc.selector, 'assert_nil')
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
@@ -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?
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module Cop
5
5
  module Minitest
6
6
  # This cop enforces the use of `refute_equal(expected, object)`
7
- # over `assert_equal(expected != actual)` or `assert(! expected == actual)`.
7
+ # over `assert(expected != actual)` or `assert(! expected == actual)`.
8
8
  #
9
9
  # @example
10
10
  # # bad
@@ -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(', ')