-
Notifications
You must be signed in to change notification settings - Fork 252
Expand file tree
/
Copy pathexpectations_test_runner.rb
More file actions
149 lines (126 loc) · 4.96 KB
/
expectations_test_runner.rb
File metadata and controls
149 lines (126 loc) · 4.96 KB
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# typed: true
# frozen_string_literal: true
class ExpectationsTestRunner < Minitest::Test
TEST_EXP_DIR = "test/expectations"
TEST_FIXTURES_DIR = "test/fixtures"
TEST_RUBY_LSP_FIXTURES = File.join(TEST_FIXTURES_DIR, "*.{rb,rake}")
TEST_PRISM_FIXTURES = File.join(TEST_FIXTURES_DIR, "prism/test/prism/fixtures/**", "*.txt")
def setup
@global_state = RubyLsp::GlobalState.new
end
class << self
def expectations_tests(handler_class, expectation_suffix)
class_eval(<<~RB, __FILE__, __LINE__ + 1)
module ExpectationsRunnerMethods
def run_expectations(source)
raise "This method should be implemented in the inherited class"
end
def assert_expectations(source, expected)
parsed_expected = JSON.parse(expected)
actual = run_expectations(source)
if ENV['WRITE_EXPECTATIONS'] && parsed_expected["result"] != JSON.parse(actual.to_json)
File.write(@_expectation_path, JSON.pretty_generate(result: actual, params: @__params) + "\\n")
else
if parsed_expected["result"].nil?
assert_nil(JSON.parse(actual.to_json))
else
assert_equal(parsed_expected["result"], JSON.parse(actual.to_json))
end
end
end
def default_args
[]
end
end
include ExpectationsRunnerMethods
RB
Dir.glob(TEST_RUBY_LSP_FIXTURES).each do |path|
test_name = File.basename(path, File.extname(path))
expectations_dir = File.join(TEST_EXP_DIR, expectation_suffix)
unless File.directory?(expectations_dir)
raise "Expectations directory #{expectations_dir} does not exist"
end
json_path = File.join(expectations_dir, "#{test_name}.exp.json")
rb_path = File.join(expectations_dir, "#{test_name}.exp.rb")
if File.file?(json_path) && File.file?(rb_path)
raise "multiple expectations for #{test_name}"
elsif File.file?(json_path)
expectation_path = json_path
elsif File.file?(rb_path)
expectation_path = rb_path
end
sanitized_name = test_name.gsub(/[^\w]/, "_")
if expectation_path && File.file?(expectation_path)
class_eval(<<~RB, __FILE__, __LINE__ + 1)
def test_#{expectation_suffix}__#{sanitized_name}
@_path = "#{path}"
@_expectation_path = "#{expectation_path}"
source = File.read(@_path)
expected = File.read(@_expectation_path)
initialize_params(expected)
assert_expectations(source, expected)
end
RB
else
class_eval(<<~RB, __FILE__, __LINE__ + 1)
def test_#{expectation_suffix}__#{sanitized_name}__does_not_raise
@_path = "#{path}"
source = File.read(@_path)
run_expectations(source)
end
RB
end
end
Dir.glob(TEST_PRISM_FIXTURES).each do |path|
class_eval(<<~RB, __FILE__, __LINE__ + 1)
def test_#{expectation_suffix}__#{uniq_name_from_path(path)}__does_not_raise
@_path = "#{path}"
source = File.read(@_path)
run_expectations(source)
rescue RubyLsp::Requests::Support::InternalRuboCopError, RubyLsp::Requests::Formatting::Error
skip "Fixture requires a fix from Rubocop"
end
RB
end
end
# Ensure that the test name include path context to avoid duplicate
# from test/fixtures/prism/test/prism/fixtures/unparser/corpus/semantic/and.txt
# to test_fixtures_prism_test_prism_fixtures_unparser_corpus_semantic_and
def uniq_name_from_path(path)
path.gsub(%r{(/|\.|-)}, "_").gsub(".txt", "")
end
end
private
def diff(expected, actual)
res = super
return unless res
begin
# If the values are JSON we want to pretty print them
expected_obj = { "result" => expected }
expected_obj["params"] = @__params if @__params
actual_obj = { "result" => actual }
actual_obj["params"] = @__params if @__params
$stderr.puts "########## Expected ##########"
$stderr.puts JSON.pretty_generate(expected_obj)
$stderr.puts "########## Actual ##########"
$stderr.puts JSON.pretty_generate(actual_obj)
$stderr.puts "##############################"
rescue
# Values are not JSON, just print the raw values
$stderr.puts "########## Expected ##########"
$stderr.puts expected
$stderr.puts "########## Actual ##########"
$stderr.puts actual
$stderr.puts "##############################"
end
res
end
def json_expectations(expected_json_string)
return {} if expected_json_string.empty?
JSON.parse(expected_json_string)["result"]
end
def initialize_params(expected)
parsed_expected = JSON.parse(expected, symbolize_names: true)
@__params = parsed_expected[:params] || []
end
end