Skip to content

Commit 11a97e6

Browse files
committed
Parse tests using prism
1 parent bab4aa7 commit 11a97e6

File tree

2 files changed

+57
-2
lines changed

2 files changed

+57
-2
lines changed

railties/lib/rails/test_unit/test_parser.rb

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,59 @@
11
# frozen_string_literal: true
22

3+
begin
4+
require "prism"
5+
rescue LoadError
6+
# If Prism isn't available (because of using an older Ruby version) then we'll
7+
# define a fallback parser using ripper.
8+
end
9+
10+
if defined?(Prism)
11+
module Rails
12+
module TestUnit
13+
# Parse a test file to extract the line ranges of all tests in both
14+
# method-style (def test_foo) and declarative-style (test "foo" do)
15+
class TestParser < Prism::Visitor
16+
# Helper to translate a method object into the path and line range where
17+
# the method was defined.
18+
def self.definition_for(method)
19+
filepath, start_line = method.source_location
20+
Prism.parse_file(filepath).value.accept(new(ranges = {}))
21+
(end_line = ranges[start_line]) && [filepath, (start_line..end_line)]
22+
end
23+
24+
def self.definitions_for(source, filepath)
25+
Prism.parse(source, filepath: filepath).value.accept(new(ranges = {}))
26+
ranges
27+
end
28+
29+
attr_reader :ranges
30+
31+
def initialize(ranges)
32+
@ranges = ranges
33+
end
34+
35+
def visit_def_node(node)
36+
if node.name.start_with?("test")
37+
ranges[node.location.start_line] = node.location.end_line
38+
end
39+
super
40+
end
41+
42+
def visit_call_node(node)
43+
if node.name == :test
44+
ranges[node.location.start_line] = node.location.end_line
45+
end
46+
super
47+
end
48+
end
49+
end
50+
end
51+
52+
# If we have Prism, then we don't need to define the fallback parser using
53+
# ripper.
54+
return
55+
end
56+
357
require "ripper"
458

559
module Rails

railties/test/test_unit/test_parser_test.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# frozen_string_literal: true
22

3+
require "active_support/deprecator"
34
require "active_support/test_case"
45
require "active_support/testing/autorun"
56
require "rails/test_unit/test_parser"
@@ -42,7 +43,7 @@ def test_oneline; assert true; end
4243
end
4344
RUBY
4445

45-
parser = Rails::TestUnit::TestParser.new(example_test, "example_test.rb")
46+
actual_map = Rails::TestUnit::TestParser.definitions_for(example_test, "example_test.rb")
4647
expected_map = {
4748
4 => 8, # test_method
4849
10 => 10, # test_oneline
@@ -53,6 +54,6 @@ def test_oneline; assert true; end
5354
27 => 27, # declarative oneilne do
5455
29 => 32 # declarative multiline w/braces
5556
}
56-
assert_equal expected_map, parser.parse
57+
assert_equal expected_map, actual_map
5758
end
5859
end

0 commit comments

Comments
 (0)