Skip to content

Instantly share code, notes, and snippets.

@noahd1
Last active September 25, 2025 22:04
Show Gist options
  • Select an option

  • Save noahd1/808eda3ae1406903e1b6c362a43c08ae to your computer and use it in GitHub Desktop.

Select an option

Save noahd1/808eda3ae1406903e1b6c362a43c08ae to your computer and use it in GitHub Desktop.
Report coverage for a single file and a single line given a directory of SimpleCov files which contain results for parallelized builds
require 'json'
require 'json'
require 'pathname'
# Support optional verbose flag as third argument
if ARGV.length < 2 || ARGV.length > 3
puts "Usage: ruby script.rb <folder_path> <target_file_subpath:line_number> [--verbose]"
exit 1
end
folder_path = ARGV[0]
target_arg = ARGV[1]
verbose = ARGV.length == 3 && ARGV[2] == '--verbose'
if target_arg =~ /^(.*):(\d+)$/
target_file_subpath = $1
target_line_number = $2.to_i
target_line_index = target_line_number - 1
else
puts "Error: Second argument must be in the format PATH:LINE_NUMBER"
exit 1
end
# Counters for summary
found_count = 0
covered_count = 0
uncovered_count = 0
omitted_count = 0
unexpected_line_count = 0
begin
json_files = Dir.glob(File.join(folder_path, '*.json')) + Dir.glob(File.join(folder_path, '.*.json'))
if json_files.empty?
puts "No .json files found in #{folder_path}"
exit 1
end
json_files.each do |file_path|
begin
file_content = File.read(file_path)
json_data = JSON.parse(file_content)
json_data.each do |top_key, top_value|
coverage = top_value["coverage"] if top_value.is_a?(Hash)
next unless coverage.is_a?(Hash)
matched_key = coverage.keys.find { |k| k.include?(target_file_subpath) }
unless matched_key
puts "No file matching '#{target_file_subpath}' under #{top_key}."
next
end
found_count += 1
file_info = coverage[matched_key]
next unless file_info.is_a?(Hash)
if file_info.key?("lines")
lines = file_info["lines"]
unless lines.is_a?(Array)
raise "Error: 'lines' is not an array in #{file_path} for #{top_key}"
end
if lines.length <= target_line_index
unexpected_line_count += 1
next
end
value = lines[target_line_index]
if value.nil?
omitted_count += 1
elsif value == 0
uncovered_count += 1
elsif value > 0
if verbose
puts "Covered: #{matched_key} (#{top_key}) in #{file_path}:#{target_line_number}"
end
covered_count += 1
end
else
puts "No 'lines' key for #{matched_key} under #{top_key}."
end
end
rescue Errno::ENOENT
puts "File not found: #{file_path}"
rescue JSON::ParserError => e
puts "Invalid JSON in #{file_path}: #{e.message}"
end
end
rescue => e
puts "Error: #{e.message}"
end
# Print summary
puts "\nSummary:"
puts "Total times path found: #{found_count}"
puts "Total times line considered covered: #{covered_count}"
puts "Total times line considered uncovered: #{uncovered_count}"
puts "Total times line considered omitted: #{omitted_count}"
puts "Total times with unexpected line count: #{unexpected_line_count}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment