Skip to content

Instantly share code, notes, and snippets.

@tahirmt
Last active April 22, 2025 04:55
Show Gist options
  • Save tahirmt/bd5132923073374fc02c417b393a2a72 to your computer and use it in GitHub Desktop.
Save tahirmt/bd5132923073374fc02c417b393a2a72 to your computer and use it in GitHub Desktop.
Extract attachments from xcresult files
require 'json'
require 'ostruct'
file = ARGV[0]
output = ARGV[1]
if file.nil? || output.nil?
puts "Usage: ruby extractAttachments.rb [xcresult path] [output path]"
return
end
unless File.exist?(file)
puts "file does not exist at #{file}"
return
end
tests_summary_json = `xcrun xcresulttool get test-results summary --path "#{file}"`
tests_summary = JSON.parse(tests_summary_json, object_class: OpenStruct)
failed_tests = tests_summary.testFailures
failed_tests.each { |failed_test|
details_json = `xcrun xcresulttool get test-results test-details --test-id "#{failed_test.testIdentifierURL}" --path "#{file}"`
details = JSON.parse(details_json, object_class: OpenStruct)
if details.hasMediaAttachments
test_suite = details.testIdentifier.split("/").first || "unknown"
output_path = "#{output}/#{test_suite}/#{details.testName}"
`xcrun xcresulttool export attachments --test-id "#{details.testIdentifierURL}" --path "#{file}" --output-path "#{output_path}"`
# After exporting, read the manifest
manifest_path = "#{output_path}/manifest.json"
manifest = JSON.parse(File.read(manifest_path), object_class: OpenStruct)
manifest.first.attachments.each { |attachment|
file_name = attachment.exportedFileName
suggested_name = attachment.suggestedHumanReadableName
File.rename("#{output_path}/#{file_name}", "#{output_path}/#{suggested_name}")
}
end
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment