Skip to content

Commit e6c38ca

Browse files
authored
Merge pull request #333 from koic/fix_false_positives_for_minitest_no_assertion_test
[Fix #332] Fix false positives for `Minitest/NoAssertions`
2 parents 936c5aa + dbefbf0 commit e6c38ca

File tree

5 files changed

+69
-19
lines changed

5 files changed

+69
-19
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* [#332](https://github.com/rubocop/rubocop-minitest/issues/332): Fix false positives for `Minitest/NoAssertions` when using matcher methods. ([@koic][])

lib/rubocop/cop/minitest/global_expectations.rb

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -87,20 +87,10 @@ class GlobalExpectations < Base
8787

8888
MSG = 'Use `%<preferred>s` instead.'
8989

90-
VALUE_MATCHERS = %i[
91-
must_be_empty must_equal must_be_close_to must_be_within_delta
92-
must_be_within_epsilon must_include must_be_instance_of must_be_kind_of
93-
must_match must_be_nil must_be must_respond_to must_be_same_as
94-
path_must_exist path_wont_exist wont_be_empty wont_equal wont_be_close_to
95-
wont_be_within_delta wont_be_within_epsilon wont_include wont_be_instance_of
96-
wont_be_kind_of wont_match wont_be_nil wont_be wont_respond_to wont_be_same_as
97-
].freeze
98-
99-
BLOCK_MATCHERS = %i[
100-
must_output must_pattern_match must_raise must_be_silent must_throw wont_pattern_match
101-
].freeze
102-
103-
RESTRICT_ON_SEND = VALUE_MATCHERS + BLOCK_MATCHERS
90+
VALUE_MATCHERS = MinitestExplorationHelpers::VALUE_MATCHERS
91+
BLOCK_MATCHERS = MinitestExplorationHelpers::BLOCK_MATCHERS
92+
93+
RESTRICT_ON_SEND = MinitestExplorationHelpers::MATCHER_METHODS
10494

10595
# There are aliases for the `_` method - `expect` and `value`
10696
DSL_METHODS = %i[_ expect value].freeze

lib/rubocop/cop/minitest/no_assertions.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ module Cop
55
module Minitest
66
# Checks if test cases contain any assertion calls.
77
#
8+
# Matchers such as `must_equal` and `wont_match` are also treated as assertion methods.
9+
#
810
# @example
911
# # bad
1012
# class FooTest < Minitest::Test
@@ -19,6 +21,23 @@ module Minitest
1921
# end
2022
# end
2123
#
24+
# # bad
25+
# class FooTest < ActiveSupport::TestCase
26+
# describe 'foo' do
27+
# it 'test equal' do
28+
# end
29+
# end
30+
# end
31+
#
32+
# # good
33+
# class FooTest < ActiveSupport::TestCase
34+
# describe 'foo' do
35+
# it 'test equal' do
36+
# musts.must_equal expected_musts
37+
# end
38+
# end
39+
# end
40+
#
2241
class NoAssertions < Base
2342
include MinitestExplorationHelpers
2443

lib/rubocop/cop/mixin/minitest_exploration_helpers.rb

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,22 @@ module MinitestExplorationHelpers
1010
include DefNode
1111
extend NodePattern::Macros
1212

13-
ASSERTION_PREFIXES = %w[assert refute].freeze
13+
VALUE_MATCHERS = %i[
14+
must_be_empty must_equal must_be_close_to must_be_within_delta
15+
must_be_within_epsilon must_include must_be_instance_of must_be_kind_of
16+
must_match must_be_nil must_be must_respond_to must_be_same_as
17+
path_must_exist path_wont_exist wont_be_empty wont_equal wont_be_close_to
18+
wont_be_within_delta wont_be_within_epsilon wont_include wont_be_instance_of
19+
wont_be_kind_of wont_match wont_be_nil wont_be wont_respond_to wont_be_same_as
20+
].freeze
21+
22+
BLOCK_MATCHERS = %i[
23+
must_output must_pattern_match must_raise must_be_silent must_throw wont_pattern_match
24+
].freeze
25+
26+
MATCHER_METHODS = VALUE_MATCHERS + BLOCK_MATCHERS
27+
28+
ASSERTION_PREFIXES = %i[assert refute].freeze
1429

1530
LIFECYCLE_HOOK_METHODS_IN_ORDER = %i[
1631
before_setup
@@ -99,17 +114,18 @@ def assertions_count(node)
99114
end
100115
end
101116

117+
# rubocop:disable Metrics/CyclomaticComplexity
102118
def assertion_method?(node)
103119
return false unless node
104120
return assertion_method?(node.expression) if node.assignment? && node.respond_to?(:expression)
105121
return false unless node.type?(:send, :any_block)
106122

107-
ASSERTION_PREFIXES.any? do |prefix|
108-
method_name = node.method_name
123+
method_name = node.method_name
124+
assertion_method = ASSERTION_PREFIXES.any? { |prefix| method_name.start_with?(prefix.to_s) }
109125

110-
method_name.start_with?(prefix) || node.method?(:flunk)
111-
end
126+
assertion_method || node.method?(:flunk) || MATCHER_METHODS.include?(method_name)
112127
end
128+
# rubocop:enable Metrics/CyclomaticComplexity
113129

114130
def lifecycle_hook_method?(node)
115131
node.def_type? && LIFECYCLE_HOOK_METHODS.include?(node.method_name)

test/rubocop/cop/minitest/no_assertions_test.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,30 @@ def test_the_truth
7878
RUBY
7979
end
8080

81+
def test_register_no_offense_if_test_has_must_be_empty_assertion
82+
assert_no_offenses(<<~RUBY)
83+
class FooTest < Minitest::Test
84+
describe 'foo' do
85+
it 'must have good data' do
86+
_(invalid_recs).must_be_empty ->{ do_something }
87+
end
88+
end
89+
end
90+
RUBY
91+
end
92+
93+
def test_register_no_offense_if_test_has_must_include_assertion
94+
assert_no_offenses(<<~RUBY)
95+
class FooTest < Minitest::Test
96+
describe 'foo' do
97+
it 'must include [false, true]' do
98+
value([false, true]).must_include value
99+
end
100+
end
101+
end
102+
RUBY
103+
end
104+
81105
def test_register_no_offense_for_unrelated_methods
82106
assert_no_offenses(<<~RUBY)
83107
class FooTest < Minitest::Test

0 commit comments

Comments
 (0)