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
@@ -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