forked from rubocop/rubocop-minitest
-
Notifications
You must be signed in to change notification settings - Fork 0
/
assert_output.rb
48 lines (40 loc) · 1.31 KB
/
assert_output.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# frozen_string_literal: true
module RuboCop
module Cop
module Minitest
# Checks for opportunities to use `assert_output`.
#
# @example
# # bad
# $stdout = StringIO.new
# puts object.method
# $stdout.rewind
# assert_match expected, $stdout.read
#
# # good
# assert_output(expected) { puts object.method }
#
class AssertOutput < Base
include MinitestExplorationHelpers
MSG = 'Use `assert_output` instead of mutating %<name>s.'
OUTPUT_GLOBAL_VARIABLES = %i[$stdout $stderr].freeze
def on_gvasgn(node)
test_case_node = find_test_case(node)
return unless test_case_node
gvar_name = node.children.first
return unless OUTPUT_GLOBAL_VARIABLES.include?(gvar_name)
assertions(test_case_node).each do |assertion|
add_offense(assertion, message: format(MSG, name: gvar_name)) if references_gvar?(assertion, gvar_name)
end
end
private
def find_test_case(node)
node.each_ancestor.find { |ancestor| test_case?(ancestor) }
end
def references_gvar?(assertion, gvar_name)
assertion.each_descendant(:gvar).any? { |d| d.children.first == gvar_name }
end
end
end
end
end