Skip to content

Commit

Permalink
[Fix #189] Fix a false positive for `Minitest/EmptyLineBeforeAssertio…
Browse files Browse the repository at this point in the history
…nMethods`

Fixes #189 and #194.

This PR fixes a false negative for `Minitest/EmptyLineBeforeAssertionMethods`
when using assertion method used in block before assertion method.
  • Loading branch information
koic committed Nov 4, 2022
1 parent f4c6b6a commit ec4848c
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#189](https://github.com/rubocop/rubocop-minitest/issues/189): Fix a false negative for `Minitest/EmptyLineBeforeAssertionMethods` when using assertion method used in block before assertion method. ([@koic][])
22 changes: 17 additions & 5 deletions lib/rubocop/cop/minitest/empty_line_before_assertion_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,28 @@ class EmptyLineBeforeAssertionMethods < Base

MSG = 'Add empty line before assertion.'

# rubocop:disable Metrics/CyclomaticComplexity
def on_send(node)
return unless (assertion_method = assertion_method(node))
return unless (previous_line_node = assertion_method.left_sibling)
return if node.parent.resbody_type?
return if accept_previous_line?(previous_line_node, assertion_method)

previous_line_node = previous_line_node.arguments.last if use_heredoc_argument?(previous_line_node)
return if use_assertion_method_at_last_of_block?(previous_line_node)
return unless no_empty_line?(previous_line_node, assertion_method)

register_offense(assertion_method, previous_line_node)
end
# rubocop:enable Metrics/CyclomaticComplexity

private

def assertion_method(node)
if assertion_method?(node)
node
elsif node.parent&.block_type? && assertion_method?(node.parent.body)
node.parent
end
return node if assertion_method?(node)
return unless (parent = node.parent)

node.parent if parent.block_type? && parent.body && assertion_method?(parent.body)
end

def accept_previous_line?(previous_line_node, node)
Expand All @@ -56,6 +58,16 @@ def use_heredoc_argument?(node)
node.respond_to?(:arguments) && heredoc?(node.arguments.last)
end

def use_assertion_method_at_last_of_block?(node)
return false if !node.block_type? || !node.body

if node.body.begin_type?
assertion_method?(node.body.children.last)
else
assertion_method?(node.body)
end
end

def heredoc?(last_argument)
last_argument.respond_to?(:heredoc?) && last_argument.heredoc?
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,70 @@ def test_do_something
RUBY
end

def test_registers_offense_when_using_non_assertion_method_used_in_single_line_block_before_assertion_method
assert_offense(<<~RUBY)
def test_do_something
set.each { |thing| do_something(thing) }
assert_equal 'This is really bad', error.message
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Add empty line before assertion.
end
RUBY

assert_correction(<<~RUBY)
def test_do_something
set.each { |thing| do_something(thing) }
assert_equal 'This is really bad', error.message
end
RUBY
end

def test_registers_offense_when_using_non_assertion_method_used_in_multi_line_block_before_assertion_method
assert_offense(<<~RUBY)
def test_do_something
set.each do |thing|
refute_nil(thing)
do_something(thing)
end
assert_equal 'This is really bad', error.message
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Add empty line before assertion.
end
RUBY

assert_correction(<<~RUBY)
def test_do_something
set.each do |thing|
refute_nil(thing)
do_something(thing)
end
assert_equal 'This is really bad', error.message
end
RUBY
end

def test_registers_offense_when_using_empty_block_before_assertion_method
assert_offense(<<~RUBY)
def test_do_something
set.each do |thing|
end
assert_equal 'This is really bad', error.message
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Add empty line before assertion.
end
RUBY

assert_correction(<<~RUBY)
def test_do_something
set.each do |thing|
end
assert_equal 'This is really bad', error.message
end
RUBY
end

def test_registers_offense_when_using_statement_before_assertion_method_used_in_rescue
assert_offense(<<~'RUBY')
def test_do_something
Expand Down Expand Up @@ -258,7 +322,7 @@ def test_do_something
RUBY
end

def test_registers_offense_when_using_assertion_method_before_assertion_method_used_in_block
def test_does_not_register_offense_when_using_assertion_method_before_assertion_method_used_in_block
assert_no_offenses(<<~RUBY)
def test_do_something
set = Set.new([1,2,3])
Expand All @@ -282,6 +346,28 @@ def test_do_something
RUBY
end

def test_does_not_register_offense_when_using_assertion_method_used_in_single_line_block_before_assertion_method
assert_no_offenses(<<~RUBY)
def test_do_something
set.each { |thing| refute_nil(thing) }
assert_equal 'This is really bad', error.message
end
RUBY
end

def test_does_not_register_offense_when_using_assertion_method_used_in_multi_line_block_before_assertion_method
assert_no_offenses(<<~RUBY)
def test_do_something
set.each do |thing|
do_something
refute_nil(thing)
end
assert_equal 'This is really bad', error.message
end
RUBY
end

def test_does_not_register_offense_when_using_rescue_before_assertion_method
assert_no_offenses(<<~'RUBY')
def test_do_something
Expand Down

0 comments on commit ec4848c

Please sign in to comment.