rubocop-minitest 0.10.1 → 0.12.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 +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
@@ -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 $_ $_ $...)
@@ -15,7 +15,7 @@ module RuboCop
15
15
  # refute_includes(collection, object)
16
16
  # refute_includes(collection, object, 'message')
17
17
  #
18
- class RefuteIncludes < Cop
18
+ class RefuteIncludes < Base
19
19
  extend MinitestCopRule
20
20
 
21
21
  define_rule :refute, target_method: :include?, preferred_method: :refute_includes
@@ -15,7 +15,7 @@ module RuboCop
15
15
  # refute_instance_of(Class, object)
16
16
  # refute_instance_of(Class, object, 'message')
17
17
  #
18
- class RefuteInstanceOf < Cop
18
+ class RefuteInstanceOf < Base
19
19
  extend MinitestCopRule
20
20
 
21
21
  define_rule :refute, target_method: :instance_of?, inverse: true
@@ -15,7 +15,7 @@ module RuboCop
15
15
  # refute_kind_of(Class, object)
16
16
  # refute_kind_of(Class, object, 'message')
17
17
  #
18
- class RefuteKindOf < Cop
18
+ class RefuteKindOf < Base
19
19
  extend MinitestCopRule
20
20
 
21
21
  define_rule :refute, target_method: :kind_of?, inverse: true
@@ -15,7 +15,7 @@ module RuboCop
15
15
  # refute_match(matcher, string)
16
16
  # refute_match(matcher, string, 'message')
17
17
  #
18
- class RefuteMatch < Cop
18
+ class RefuteMatch < Base
19
19
  extend MinitestCopRule
20
20
 
21
21
  define_rule :refute, target_method: :match
@@ -15,11 +15,13 @@ module RuboCop
15
15
  # refute_nil(actual)
16
16
  # refute_nil(actual, 'message')
17
17
  #
18
- class RefuteNil < Cop
18
+ class RefuteNil < Base
19
19
  include ArgumentRangeHelper
20
+ extend AutoCorrector
20
21
 
21
22
  MSG = 'Prefer using `refute_nil(%<arguments>s)` over ' \
22
23
  '`refute_equal(nil, %<arguments>s)`.'
24
+ RESTRICT_ON_SEND = %i[refute_equal].freeze
23
25
 
24
26
  def_node_matcher :refute_equal_with_nil, <<~PATTERN
25
27
  (send nil? :refute_equal nil $_ $...)
@@ -31,13 +33,7 @@ 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
- refute_equal_with_nil(node) do |actual|
36
+ add_offense(node, message: format(MSG, arguments: arguments)) do |corrector|
41
37
  corrector.replace(node.loc.selector, 'refute_nil')
42
38
  corrector.replace(
43
39
  first_and_second_arguments_range(node), actual.source
@@ -15,8 +15,11 @@ module RuboCop
15
15
  # refute_path_exists(path)
16
16
  # refute_path_exists(path, 'message')
17
17
  #
18
- class RefutePathExists < Cop
18
+ class RefutePathExists < Base
19
+ extend AutoCorrector
20
+
19
21
  MSG = 'Prefer using `%<good_method>s` over `%<bad_method>s`.'
22
+ RESTRICT_ON_SEND = %i[refute].freeze
20
23
 
21
24
  def_node_matcher :refute_file_exists, <<~PATTERN
22
25
  (send nil? :refute
@@ -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
- refute_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
  # refute_respond_to(object, :do_something, 'message')
18
18
  # refute_respond_to(self, :do_something)
19
19
  #
20
- class RefuteRespondTo < Cop
20
+ class RefuteRespondTo < Base
21
21
  extend MinitestCopRule
22
22
 
23
23
  define_rule :refute, target_method: :respond_to?
@@ -4,6 +4,7 @@ module RuboCop
4
4
  module Cop
5
5
  module Minitest
6
6
  # This cop enforces that test method names start with `test_` prefix.
7
+ # It aims to prevent tests that aren't executed by forgetting to start test method name with `test_`.
7
8
  #
8
9
  # @example
9
10
  # # bad
@@ -20,9 +21,16 @@ module RuboCop
20
21
  # end
21
22
  # end
22
23
  #
23
- class TestMethodName < Cop
24
+ # # good
25
+ # class FooTest < Minitest::Test
26
+ # def helper_method(argument)
27
+ # end
28
+ # end
29
+ #
30
+ class TestMethodName < Base
24
31
  include MinitestExplorationHelpers
25
32
  include DefNode
33
+ extend AutoCorrector
26
34
 
27
35
  MSG = 'Test method name should start with `test_` prefix.'
28
36
 
@@ -30,13 +38,13 @@ module RuboCop
30
38
  return unless test_class?(class_node)
31
39
 
32
40
  class_elements(class_node).each do |node|
33
- add_offense(node, location: :name) if offense?(node)
34
- end
35
- end
41
+ next unless offense?(node)
36
42
 
37
- def autocorrect(node)
38
- lambda do |corrector|
39
- corrector.replace(node.loc.name, "test_#{node.method_name}")
43
+ test_method_name = node.loc.name
44
+
45
+ add_offense(test_method_name) do |corrector|
46
+ corrector.replace(test_method_name, "test_#{node.method_name}")
47
+ end
40
48
  end
41
49
  end
42
50
 
@@ -54,7 +62,9 @@ module RuboCop
54
62
  end
55
63
 
56
64
  def offense?(node)
57
- public?(node) && !test_method_name?(node) && !lifecycle_hook_method?(node)
65
+ return false if assertions(node).none?
66
+
67
+ public?(node) && node.arguments.empty? && !test_method_name?(node) && !lifecycle_hook_method?(node)
58
68
  end
59
69
 
60
70
  def public?(node)
@@ -14,7 +14,7 @@ module RuboCop
14
14
  # assert_raises(FooException) { raise FooException }
15
15
  # assert_raises(FooException, 'This should have raised') { raise FooException }
16
16
  #
17
- class UnspecifiedException < Cop
17
+ class UnspecifiedException < Base
18
18
  MSG = 'Specify the exception being captured.'
19
19
 
20
20
  def on_block(block_node)
@@ -8,6 +8,7 @@ require_relative 'minitest/assert_empty'
8
8
  require_relative 'minitest/assert_empty_literal'
9
9
  require_relative 'minitest/assert_equal'
10
10
  require_relative 'minitest/assert_in_delta'
11
+ require_relative 'minitest/assert_with_expected_argument'
11
12
  require_relative 'minitest/assertion_in_lifecycle_hook'
12
13
  require_relative 'minitest/assert_kind_of'
13
14
  require_relative 'minitest/assert_nil'
@@ -22,6 +23,7 @@ require_relative 'minitest/assert_truthy'
22
23
  require_relative 'minitest/global_expectations'
23
24
  require_relative 'minitest/literal_as_actual_argument'
24
25
  require_relative 'minitest/multiple_assertions'
26
+ require_relative 'minitest/no_assertions'
25
27
  require_relative 'minitest/refute_empty'
26
28
  require_relative 'minitest/refute_false'
27
29
  require_relative 'minitest/refute_equal'
@@ -9,24 +9,14 @@ module RuboCop
9
9
  def on_send(node)
10
10
  equal_floats_call(node) do |expected, actual, message|
11
11
  message = message.first
12
+ good_method = build_good_method(expected, actual, message)
12
13
 
13
14
  if expected.float_type? || actual.float_type?
14
- message = format(MSG,
15
- good_method: build_good_method(expected, actual, message),
16
- bad_method: node.source)
15
+ message = format(MSG, good_method: good_method, bad_method: node.source)
17
16
 
18
- add_offense(node, message: message)
19
- end
20
- end
21
- end
22
-
23
- def autocorrect(node)
24
- equal_floats_call(node) do |expected, actual, message|
25
- message = message.first
26
- replacement = build_good_method(expected, actual, message)
27
-
28
- lambda do |corrector|
29
- corrector.replace(node, replacement)
17
+ add_offense(node, message: message) do |corrector|
18
+ corrector.replace(node, good_method)
19
+ end
30
20
  end
31
21
  end
32
22
  end
@@ -26,38 +26,38 @@ module RuboCop
26
26
 
27
27
  class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
28
28
  include ArgumentRangeHelper
29
+ extend AutoCorrector
29
30
 
30
31
  MSG = 'Prefer using `#{preferred_method}(%<new_arguments>s)` over ' \
31
32
  '`#{assertion_method}(%<original_arguments>s)`.'
33
+ RESTRICT_ON_SEND = %i[#{assertion_method}].freeze
32
34
 
33
35
  def on_send(node)
34
36
  return unless node.method?(:#{assertion_method})
35
37
  return unless (arguments = peel_redundant_parentheses_from(node.arguments))
36
38
  return unless arguments.first.respond_to?(:method?) && arguments.first.method?(:#{target_method})
37
39
 
38
- add_offense(node, message: offense_message(arguments))
40
+ add_offense(node, message: offense_message(arguments)) do |corrector|
41
+ autocorrect(corrector, node, arguments)
42
+ end
39
43
  end
40
44
 
41
- def autocorrect(node)
42
- lambda do |corrector|
43
- corrector.replace(node.loc.selector, '#{preferred_method}')
44
-
45
- arguments = peel_redundant_parentheses_from(node.arguments)
45
+ def autocorrect(corrector, node, arguments)
46
+ corrector.replace(node.loc.selector, '#{preferred_method}')
46
47
 
47
- new_arguments = new_arguments(arguments).join(', ')
48
+ new_arguments = new_arguments(arguments).join(', ')
48
49
 
49
- if enclosed_in_redundant_parentheses?(node)
50
- new_arguments = '(' + new_arguments + ')'
51
- end
52
-
53
- corrector.replace(first_argument_range(node), new_arguments)
50
+ if enclosed_in_redundant_parentheses?(node)
51
+ new_arguments = '(' + new_arguments + ')'
54
52
  end
53
+
54
+ corrector.replace(first_argument_range(node), new_arguments)
55
55
  end
56
56
 
57
57
  private
58
58
 
59
59
  def peel_redundant_parentheses_from(arguments)
60
- return arguments unless arguments.first.begin_type?
60
+ return arguments unless arguments.first&.begin_type?
61
61
 
62
62
  peel_redundant_parentheses_from(arguments.first.children)
63
63
  end
@@ -10,6 +10,17 @@ module RuboCop
10
10
 
11
11
  ASSERTION_PREFIXES = %w[assert refute].freeze
12
12
 
13
+ ASSERTION_METHODS = %i[
14
+ assert assert_empty assert_equal assert_in_delta assert_in_epsilon assert_includes assert_instance_of
15
+ assert_kind_of assert_match assert_nil assert_operator assert_output assert_path_exists assert_predicate
16
+ assert_raises assert_respond_to assert_same assert_send assert_silent assert_throws
17
+ refute refute_empty refute_equal refute_in_delta refute_in_epsilon refute_includes refute_instance_of
18
+ refute_kind_of refute_match refute_nil refute_operator refute_path_exists refute_predicate
19
+ refute_respond_to refute_same
20
+ ].freeze
21
+
22
+ FLUNK = 'flunk'
23
+
13
24
  LIFECYCLE_HOOK_METHODS = %i[
14
25
  before_setup
15
26
  setup
@@ -33,8 +44,8 @@ module RuboCop
33
44
  end
34
45
 
35
46
  def test_cases(class_node)
36
- class_def_nodes(class_node)
37
- .select { |def_node| test_case_name?(def_node.method_name) }
47
+ (class_def_nodes(class_node).select { |def_node| test_case_name?(def_node.method_name) }) +
48
+ test_method_calls(class_node)
38
49
  end
39
50
 
40
51
  def lifecycle_hooks(class_node)
@@ -53,6 +64,12 @@ module RuboCop
53
64
  end
54
65
  end
55
66
 
67
+ # support https://api.rubyonrails.org/classes/ActiveSupport/Testing/Declarative.html
68
+ def test_method_calls(class_node)
69
+ block_nodes = class_node.each_descendant(:block)
70
+ block_nodes.select { |block_node| block_node.method?(:test) }
71
+ end
72
+
56
73
  def test_case_name?(name)
57
74
  name.to_s.start_with?('test_')
58
75
  end
@@ -73,7 +90,14 @@ module RuboCop
73
90
 
74
91
  def assertion?(node)
75
92
  node.send_type? &&
76
- ASSERTION_PREFIXES.any? { |prefix| node.method_name.to_s.start_with?(prefix) }
93
+ ASSERTION_PREFIXES.any? do |prefix|
94
+ method_name = node.method_name.to_s
95
+ method_name == FLUNK || method_name.start_with?(prefix)
96
+ end
97
+ end
98
+
99
+ def assertion_method?(method_name)
100
+ method_name == FLUNK || ASSERTION_METHODS.include?(method_name)
77
101
  end
78
102
 
79
103
  def lifecycle_hook_method?(node)
@@ -2,6 +2,13 @@
2
2
 
3
3
  module RuboCop
4
4
  module Minitest
5
- VERSION = '0.10.1'
5
+ # This module holds the RuboCop Minitest version information.
6
+ module Version
7
+ STRING = '0.12.0'
8
+
9
+ def self.document_version
10
+ STRING.match('\d+\.\d+').to_s
11
+ end
12
+ end
6
13
  end
7
14
  end
data/mkdocs.yml CHANGED
@@ -1,7 +1,7 @@
1
1
  site_name: "A RuboCop extension focused on enforcing Minitest best practices and coding conventions."
2
- repo_url: https://github.com/rubocop-hq/rubocop-minitest
2
+ repo_url: https://github.com/rubocop/rubocop-minitest
3
3
  edit_uri: edit/master/legacy-docs/
4
- copyright: "Copyright &copy; 2019 Bozhidar Batsov, Jonas Arvidsson, Koichi ITO, and RuboCop contributors"
4
+ copyright: "Copyright &copy; 2021 Bozhidar Batsov, Jonas Arvidsson, Koichi ITO, and RuboCop contributors"
5
5
  docs_dir: legacy-docs
6
6
  pages:
7
7
  - Home: index.md