rubocop-minitest 0.9.0 → 0.11.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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +18 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +5 -1
- data/.rubocop.yml +5 -3
- data/.rubocop_todo.yml +8 -7
- data/CHANGELOG.md +94 -37
- data/CONTRIBUTING.md +3 -3
- data/Gemfile +2 -2
- data/LICENSE.txt +1 -1
- data/README.md +20 -4
- data/Rakefile +29 -0
- data/bin/console +2 -0
- data/config/default.yml +100 -16
- data/docs/antora.yml +7 -0
- data/docs/modules/ROOT/nav.adoc +6 -0
- data/docs/modules/ROOT/pages/cops.adoc +49 -0
- data/docs/modules/ROOT/pages/cops_minitest.adoc +1050 -0
- data/docs/modules/ROOT/pages/index.adoc +5 -0
- data/docs/modules/ROOT/pages/installation.adoc +15 -0
- data/docs/modules/ROOT/pages/usage.adoc +32 -0
- data/{manual → legacy-docs}/cops.md +0 -0
- data/{manual → legacy-docs}/cops_minitest.md +16 -16
- data/legacy-docs/index.md +1 -0
- data/{manual → legacy-docs}/installation.md +0 -0
- data/{manual → legacy-docs}/usage.md +0 -0
- data/lib/rubocop/cop/generator.rb +56 -0
- data/lib/rubocop/cop/minitest/assert_empty_literal.rb +23 -7
- data/lib/rubocop/cop/minitest/assert_in_delta.rb +29 -0
- data/lib/rubocop/cop/minitest/assert_kind_of.rb +25 -0
- data/lib/rubocop/cop/minitest/assert_nil.rb +1 -0
- data/lib/rubocop/cop/minitest/assert_output.rb +49 -0
- data/lib/rubocop/cop/minitest/assert_path_exists.rb +59 -0
- data/lib/rubocop/cop/minitest/assert_silent.rb +45 -0
- data/lib/rubocop/cop/minitest/assert_truthy.rb +1 -0
- data/lib/rubocop/cop/minitest/assert_with_expected_argument.rb +38 -0
- data/lib/rubocop/cop/minitest/assertion_in_lifecycle_hook.rb +43 -0
- data/lib/rubocop/cop/minitest/global_expectations.rb +4 -4
- data/lib/rubocop/cop/minitest/literal_as_actual_argument.rb +53 -0
- data/lib/rubocop/cop/minitest/multiple_assertions.rb +63 -0
- data/lib/rubocop/cop/minitest/refute_equal.rb +2 -1
- data/lib/rubocop/cop/minitest/refute_false.rb +1 -0
- data/lib/rubocop/cop/minitest/refute_in_delta.rb +29 -0
- data/lib/rubocop/cop/minitest/refute_kind_of.rb +25 -0
- data/lib/rubocop/cop/minitest/refute_nil.rb +1 -0
- data/lib/rubocop/cop/minitest/refute_path_exists.rb +59 -0
- data/lib/rubocop/cop/minitest/test_method_name.rb +79 -0
- data/lib/rubocop/cop/minitest/unspecified_exception.rb +36 -0
- data/lib/rubocop/cop/minitest_cops.rb +16 -0
- data/lib/rubocop/cop/mixin/argument_range_helper.rb +10 -0
- data/lib/rubocop/cop/mixin/in_delta_mixin.rb +50 -0
- data/lib/rubocop/cop/mixin/minitest_cop_rule.rb +2 -1
- data/lib/rubocop/cop/mixin/minitest_exploration_helpers.rb +97 -0
- data/lib/rubocop/minitest/version.rb +8 -1
- data/mkdocs.yml +4 -4
- data/relnotes/v0.1.0.md +1 -1
- data/relnotes/v0.10.0.md +21 -0
- data/relnotes/v0.10.1.md +5 -0
- data/relnotes/v0.10.2.md +5 -0
- data/relnotes/v0.10.3.md +5 -0
- data/relnotes/v0.11.0.md +16 -0
- data/relnotes/v0.2.0.md +4 -4
- data/relnotes/v0.2.1.md +1 -1
- data/relnotes/v0.3.0.md +6 -6
- data/relnotes/v0.4.0.md +5 -5
- data/relnotes/v0.4.1.md +1 -1
- data/relnotes/v0.5.0.md +1 -1
- data/relnotes/v0.5.1.md +1 -1
- data/relnotes/v0.6.0.md +1 -1
- data/relnotes/v0.6.1.md +2 -2
- data/relnotes/v0.6.2.md +1 -1
- data/relnotes/v0.7.0.md +5 -5
- data/relnotes/v0.8.0.md +4 -4
- data/relnotes/v0.8.1.md +1 -1
- data/relnotes/v0.9.0.md +3 -3
- data/rubocop-minitest.gemspec +7 -7
- data/tasks/cops_documentation.rake +15 -264
- data/tasks/cut_release.rake +16 -0
- metadata +55 -20
- data/manual/index.md +0 -1
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Minitest
|
6
|
+
# This cop enforces the test to use `assert_silent { ... }`
|
7
|
+
# instead of using `assert_output('', '') { ... }`.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# assert_output('', '') { puts object.do_something }
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# assert_silent { puts object.do_something }
|
15
|
+
#
|
16
|
+
class AssertSilent < Cop
|
17
|
+
MSG = 'Prefer using `assert_silent` over `assert_output("", "")`.'
|
18
|
+
|
19
|
+
def_node_matcher :assert_silent_candidate?, <<~PATTERN
|
20
|
+
(block
|
21
|
+
(send nil? :assert_output
|
22
|
+
#empty_string?
|
23
|
+
#empty_string?)
|
24
|
+
...)
|
25
|
+
PATTERN
|
26
|
+
|
27
|
+
def on_block(node)
|
28
|
+
add_offense(node.send_node) if assert_silent_candidate?(node)
|
29
|
+
end
|
30
|
+
|
31
|
+
def autocorrect(node)
|
32
|
+
lambda do |corrector|
|
33
|
+
corrector.replace(node, 'assert_silent')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def empty_string?(node)
|
40
|
+
node.str_type? && node.value.empty?
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -20,6 +20,7 @@ module RuboCop
|
|
20
20
|
|
21
21
|
MSG = 'Prefer using `assert(%<arguments>s)` over ' \
|
22
22
|
'`assert_equal(true, %<arguments>s)`.'
|
23
|
+
RESTRICT_ON_SEND = %i[assert_equal].freeze
|
23
24
|
|
24
25
|
def_node_matcher :assert_equal_with_truthy, <<~PATTERN
|
25
26
|
(send nil? :assert_equal true $_ $...)
|
@@ -0,0 +1,38 @@
|
|
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
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# assert(3, my_list.length)
|
12
|
+
# assert(expected, actual)
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# assert_equal(3, my_list.length)
|
16
|
+
# assert_equal(expected, actual)
|
17
|
+
# assert(foo, 'message')
|
18
|
+
#
|
19
|
+
class AssertWithExpectedArgument < Cop
|
20
|
+
MSG = 'Did you mean to use `assert_equal(%<arguments>s)`?'
|
21
|
+
RESTRICT_ON_SEND = %i[assert].freeze
|
22
|
+
|
23
|
+
def_node_matcher :assert_with_two_arguments?, <<~PATTERN
|
24
|
+
(send nil? :assert $_ $_)
|
25
|
+
PATTERN
|
26
|
+
|
27
|
+
def on_send(node)
|
28
|
+
assert_with_two_arguments?(node) do |_expected, message|
|
29
|
+
return if message.str_type? || message.dstr_type?
|
30
|
+
|
31
|
+
arguments = node.arguments.map(&:source).join(', ')
|
32
|
+
add_offense(node, message: format(MSG, arguments: arguments))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Minitest
|
6
|
+
# This cop checks for usage of assertions in lifecycle hooks.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# class FooTest < Minitest::Test
|
11
|
+
# def setup
|
12
|
+
# assert_equal(foo, bar)
|
13
|
+
# end
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# class FooTest < Minitest::Test
|
18
|
+
# def test_something
|
19
|
+
# assert_equal(foo, bar)
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
class AssertionInLifecycleHook < Cop
|
24
|
+
include MinitestExplorationHelpers
|
25
|
+
|
26
|
+
MSG = 'Do not use `%<assertion>s` in `%<hook>s` hook.'
|
27
|
+
|
28
|
+
def on_class(class_node)
|
29
|
+
return unless test_class?(class_node)
|
30
|
+
|
31
|
+
lifecycle_hooks(class_node).each do |hook_node|
|
32
|
+
hook_node.each_descendant(:send) do |node|
|
33
|
+
if assertion?(node)
|
34
|
+
message = format(MSG, assertion: node.method_name, hook: hook_node.method_name)
|
35
|
+
add_offense(node, message: message)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -30,6 +30,8 @@ module RuboCop
|
|
30
30
|
|
31
31
|
BLOCK_MATCHERS = %i[must_output must_raise must_be_silent must_throw].freeze
|
32
32
|
|
33
|
+
RESTRICT_ON_SEND = VALUE_MATCHERS + BLOCK_MATCHERS
|
34
|
+
|
33
35
|
VALUE_MATCHERS_STR = VALUE_MATCHERS.map do |m|
|
34
36
|
":#{m}"
|
35
37
|
end.join(' ').freeze
|
@@ -72,11 +74,9 @@ module RuboCop
|
|
72
74
|
receiver = node.receiver.source_range
|
73
75
|
|
74
76
|
if BLOCK_MATCHERS.include?(node.method_name)
|
75
|
-
corrector.
|
76
|
-
corrector.insert_after(receiver, ' }')
|
77
|
+
corrector.wrap(receiver, '_ { ', ' }')
|
77
78
|
else
|
78
|
-
corrector.
|
79
|
-
corrector.insert_after(receiver, ')')
|
79
|
+
corrector.wrap(receiver, '_(', ')')
|
80
80
|
end
|
81
81
|
end
|
82
82
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Minitest
|
6
|
+
# This cop enforces correct order of expected and
|
7
|
+
# actual arguments for `assert_equal`.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# assert_equal foo, 2
|
12
|
+
# assert_equal foo, [1, 2]
|
13
|
+
# assert_equal foo, [1, 2], 'message'
|
14
|
+
#
|
15
|
+
# # good
|
16
|
+
# assert_equal 2, foo
|
17
|
+
# assert_equal [1, 2], foo
|
18
|
+
# assert_equal [1, 2], foo, 'message'
|
19
|
+
#
|
20
|
+
class LiteralAsActualArgument < Cop
|
21
|
+
include ArgumentRangeHelper
|
22
|
+
|
23
|
+
MSG = 'Replace the literal with the first argument.'
|
24
|
+
RESTRICT_ON_SEND = %i[assert_equal].freeze
|
25
|
+
|
26
|
+
def on_send(node)
|
27
|
+
return unless node.method?(:assert_equal)
|
28
|
+
|
29
|
+
actual = node.arguments[1]
|
30
|
+
return unless actual
|
31
|
+
|
32
|
+
add_offense(node, location: all_arguments_range(node)) if actual.recursive_basic_literal?
|
33
|
+
end
|
34
|
+
|
35
|
+
def autocorrect(node)
|
36
|
+
expected, actual, message = *node.arguments
|
37
|
+
|
38
|
+
lambda do |corrector|
|
39
|
+
new_actual_source =
|
40
|
+
if actual.hash_type? && !actual.braces?
|
41
|
+
"{#{actual.source}}"
|
42
|
+
else
|
43
|
+
actual.source
|
44
|
+
end
|
45
|
+
arguments = [new_actual_source, expected.source, message&.source].compact.join(', ')
|
46
|
+
|
47
|
+
corrector.replace(node, "assert_equal(#{arguments})")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Minitest
|
6
|
+
# This cop checks if test cases contain too many assertion calls.
|
7
|
+
# The maximum allowed assertion calls is configurable.
|
8
|
+
#
|
9
|
+
# @example Max: 1
|
10
|
+
# # bad
|
11
|
+
# class FooTest < Minitest::Test
|
12
|
+
# def test_asserts_twice
|
13
|
+
# assert_equal(42, do_something)
|
14
|
+
# assert_empty(array)
|
15
|
+
# end
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# # good
|
19
|
+
# class FooTest < Minitest::Test
|
20
|
+
# def test_asserts_once
|
21
|
+
# assert_equal(42, do_something)
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# def test_another_asserts_once
|
25
|
+
# assert_empty(array)
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
class MultipleAssertions < Cop
|
30
|
+
include ConfigurableMax
|
31
|
+
include MinitestExplorationHelpers
|
32
|
+
|
33
|
+
MSG = 'Test case has too many assertions [%<total>d/%<max>d].'
|
34
|
+
|
35
|
+
def on_class(class_node)
|
36
|
+
return unless test_class?(class_node)
|
37
|
+
|
38
|
+
test_cases(class_node).each do |node|
|
39
|
+
assertions_count = assertions_count(node)
|
40
|
+
|
41
|
+
next unless assertions_count > max_assertions
|
42
|
+
|
43
|
+
self.max = assertions_count
|
44
|
+
|
45
|
+
message = format(MSG, total: assertions_count, max: max_assertions)
|
46
|
+
add_offense(node, location: :name, message: message)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def assertions_count(node)
|
53
|
+
base = assertion?(node) ? 1 : 0
|
54
|
+
base + node.each_child_node.sum { |c| assertions_count(c) }
|
55
|
+
end
|
56
|
+
|
57
|
+
def max_assertions
|
58
|
+
Integer(cop_config.fetch('Max', 3))
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -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 `
|
7
|
+
# over `assert(expected != actual)` or `assert(! expected == actual)`.
|
8
8
|
#
|
9
9
|
# @example
|
10
10
|
# # bad
|
@@ -19,6 +19,7 @@ module RuboCop
|
|
19
19
|
|
20
20
|
MSG = 'Prefer using `refute_equal(%<preferred>s)` over ' \
|
21
21
|
'`assert(%<over>s)`.'
|
22
|
+
RESTRICT_ON_SEND = %i[assert].freeze
|
22
23
|
|
23
24
|
def_node_matcher :assert_not_equal, <<~PATTERN
|
24
25
|
(send nil? :assert ${(send $_ :!= $_) (send (send $_ :! ) :== $_) } $... )
|
@@ -25,6 +25,7 @@ module RuboCop
|
|
25
25
|
'`assert_equal(false, %<arguments>s)`.'
|
26
26
|
MSG_FOR_ASSERT = 'Prefer using `refute(%<arguments>s)` over ' \
|
27
27
|
'`assert(!%<arguments>s)`.'
|
28
|
+
RESTRICT_ON_SEND = %i[assert_equal assert].freeze
|
28
29
|
|
29
30
|
def_node_matcher :assert_equal_with_false, <<~PATTERN
|
30
31
|
(send nil? :assert_equal false $_ $...)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Minitest
|
6
|
+
# This cop enforces the test to use `refute_in_delta`
|
7
|
+
# instead of using `refute_equal` to compare floats.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# refute_equal(0.2, actual)
|
12
|
+
# refute_equal(0.2, actual, 'message')
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# refute_in_delta(0.2, actual)
|
16
|
+
# refute_in_delta(0.2, actual, 0.001, 'message')
|
17
|
+
#
|
18
|
+
class RefuteInDelta < Cop
|
19
|
+
include InDeltaMixin
|
20
|
+
|
21
|
+
RESTRICT_ON_SEND = %i[refute_equal].freeze
|
22
|
+
|
23
|
+
def_node_matcher :equal_floats_call, <<~PATTERN
|
24
|
+
(send nil? :refute_equal $_ $_ $...)
|
25
|
+
PATTERN
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Minitest
|
6
|
+
# This cop enforces the use of `refute_kind_of(Class, object)`
|
7
|
+
# over `refute(object.kind_of?(Class))`.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# refute(object.kind_of?(Class))
|
12
|
+
# refute(object.kind_of?(Class), 'message')
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# refute_kind_of(Class, object)
|
16
|
+
# refute_kind_of(Class, object, 'message')
|
17
|
+
#
|
18
|
+
class RefuteKindOf < Cop
|
19
|
+
extend MinitestCopRule
|
20
|
+
|
21
|
+
define_rule :refute, target_method: :kind_of?, inverse: true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -20,6 +20,7 @@ module RuboCop
|
|
20
20
|
|
21
21
|
MSG = 'Prefer using `refute_nil(%<arguments>s)` over ' \
|
22
22
|
'`refute_equal(nil, %<arguments>s)`.'
|
23
|
+
RESTRICT_ON_SEND = %i[refute_equal].freeze
|
23
24
|
|
24
25
|
def_node_matcher :refute_equal_with_nil, <<~PATTERN
|
25
26
|
(send nil? :refute_equal nil $_ $...)
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Minitest
|
6
|
+
# This cop enforces the test to use `refute_path_exists`
|
7
|
+
# instead of using `refute(File.exist?(path))`.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# refute(File.exist?(path))
|
12
|
+
# refute(File.exist?(path), 'message')
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# refute_path_exists(path)
|
16
|
+
# refute_path_exists(path, 'message')
|
17
|
+
#
|
18
|
+
class RefutePathExists < Cop
|
19
|
+
MSG = 'Prefer using `%<good_method>s` over `%<bad_method>s`.'
|
20
|
+
RESTRICT_ON_SEND = %i[refute].freeze
|
21
|
+
|
22
|
+
def_node_matcher :refute_file_exists, <<~PATTERN
|
23
|
+
(send nil? :refute
|
24
|
+
(send
|
25
|
+
(const _ :File) {:exist? :exists?} $_)
|
26
|
+
$...)
|
27
|
+
PATTERN
|
28
|
+
|
29
|
+
def on_send(node)
|
30
|
+
refute_file_exists(node) do |path, failure_message|
|
31
|
+
failure_message = failure_message.first
|
32
|
+
good_method = build_good_method(path, failure_message)
|
33
|
+
message = format(MSG, good_method: good_method, bad_method: node.source)
|
34
|
+
|
35
|
+
add_offense(node, message: message)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def autocorrect(node)
|
40
|
+
refute_file_exists(node) do |path, failure_message|
|
41
|
+
failure_message = failure_message.first
|
42
|
+
|
43
|
+
lambda do |corrector|
|
44
|
+
replacement = build_good_method(path, failure_message)
|
45
|
+
corrector.replace(node, replacement)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def build_good_method(path, message)
|
53
|
+
args = [path.source, message&.source].compact.join(', ')
|
54
|
+
"refute_path_exists(#{args})"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Minitest
|
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_`.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# class FooTest < Minitest::Test
|
12
|
+
# def does_something
|
13
|
+
# assert_equal 42, do_something
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# # good
|
18
|
+
# class FooTest < Minitest::Test
|
19
|
+
# def test_does_something
|
20
|
+
# assert_equal 42, do_something
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# # good
|
25
|
+
# class FooTest < Minitest::Test
|
26
|
+
# def helper_method(argument)
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
class TestMethodName < Cop
|
31
|
+
include MinitestExplorationHelpers
|
32
|
+
include DefNode
|
33
|
+
|
34
|
+
MSG = 'Test method name should start with `test_` prefix.'
|
35
|
+
|
36
|
+
def on_class(class_node)
|
37
|
+
return unless test_class?(class_node)
|
38
|
+
|
39
|
+
class_elements(class_node).each do |node|
|
40
|
+
add_offense(node, location: :name) if offense?(node)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def autocorrect(node)
|
45
|
+
lambda do |corrector|
|
46
|
+
corrector.replace(node.loc.name, "test_#{node.method_name}")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def class_elements(class_node)
|
53
|
+
class_def = class_node.body
|
54
|
+
return [] unless class_def
|
55
|
+
|
56
|
+
if class_def.def_type?
|
57
|
+
[class_def]
|
58
|
+
else
|
59
|
+
class_def.each_child_node(:def).to_a
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def offense?(node)
|
64
|
+
return false if assertions(node).none?
|
65
|
+
|
66
|
+
public?(node) && node.arguments.empty? && !test_method_name?(node) && !lifecycle_hook_method?(node)
|
67
|
+
end
|
68
|
+
|
69
|
+
def public?(node)
|
70
|
+
!non_public?(node)
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_method_name?(node)
|
74
|
+
node.method_name.to_s.start_with?('test_')
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|