Class: SplitTestRb::JsonParser

Inherits:
Object
  • Object
show all
Defined in:
lib/split_test_rb.rb

Overview

Parses RSpec JSON result files and extracts test timing data

Class Method Summary collapse

Class Method Details

.extract_file_path(example) ⇒ Object

Extracts file path from example, preferring id field over file_path This is important for shared examples where file_path points to the shared example file but id contains the actual spec file path (e.g., “./spec/features/entry_spec.rb”)



35
36
37
38
39
40
41
42
# File 'lib/split_test_rb.rb', line 35

def self.extract_file_path(example)
  if example['id']
    # Extract file path from id (format: "./path/to/spec.rb[1:2:3]")
    example['id'].split('[').first
  else
    example['file_path']
  end
end

.normalize_path(path) ⇒ Object

Normalizes file path by removing leading ./



114
115
116
# File 'lib/split_test_rb.rb', line 114

def self.normalize_path(path)
  path.sub(%r{^\./}, '')
end

.parse(json_path) ⇒ Object

Parses RSpec JSON file and returns hash of => execution_time



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/split_test_rb.rb', line 9

def self.parse(json_path)
  content = File.read(json_path)
  data = JSON.parse(content)
  timings = {}

  examples = data['examples'] || []
  examples.each do |example|
    file_path = extract_file_path(example)
    run_time = example['run_time'].to_f

    next unless file_path

    # Normalize path to ensure consistent format (remove leading ./)
    file_path = normalize_path(file_path)

    # Aggregate timing for files (sum if multiple test cases from same file)
    timings[file_path] ||= 0
    timings[file_path] += run_time
  end

  timings
end

.parse_directory(dir_path) ⇒ Object

Parses all JSON files in a directory and merges results



86
87
88
89
# File 'lib/split_test_rb.rb', line 86

def self.parse_directory(dir_path)
  json_files = Dir.glob(File.join(dir_path, '**', '*.json'))
  parse_files(json_files)
end

.parse_files(json_paths) ⇒ Object

Parses multiple JSON files and merges results



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/split_test_rb.rb', line 92

def self.parse_files(json_paths)
  timings = {}

  json_paths.each do |json_path|
    next unless File.exist?(json_path)
    next if File.empty?(json_path)

    begin
      file_timings = parse(json_path)
      file_timings.each do |file, time|
        timings[file] ||= 0
        timings[file] += time
      end
    rescue JSON::ParserError => e
      warn "Warning: Failed to parse #{json_path}: #{e.message}"
    end
  end

  timings
end

.parse_files_with_examples(json_paths) ⇒ Object

Parses multiple JSON files and returns hash of => execution_time



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/split_test_rb.rb', line 65

def self.parse_files_with_examples(json_paths)
  timings = {}

  json_paths.each do |json_path|
    next unless File.exist?(json_path)
    next if File.empty?(json_path)

    begin
      example_timings = parse_with_examples(json_path)
      example_timings.each do |example_id, time|
        timings[example_id] = time
      end
    rescue JSON::ParserError => e
      warn "Warning: Failed to parse #{json_path}: #{e.message}"
    end
  end

  timings
end

.parse_with_examples(json_path) ⇒ Object

Parses RSpec JSON file and returns hash of => execution_time Example ID format: “spec/file.rb



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/split_test_rb.rb', line 46

def self.parse_with_examples(json_path)
  content = File.read(json_path)
  data = JSON.parse(content)
  timings = {}

  examples = data['examples'] || []
  examples.each do |example|
    next unless example['id']

    example_id = normalize_path(example['id'])
    run_time = example['run_time'].to_f

    timings[example_id] = run_time
  end

  timings
end