fastlane-plugin-xcresult_to_junit 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3b5b7dbfbecef6bff5d1feebb4666cbf6e9f62e9436d4a1fbaf6c4af168f5c97
4
- data.tar.gz: 7829c031a2ed03c0e6644115c0fa0431521ad85b3856e450bd1a55bd31108b91
3
+ metadata.gz: c185b9548c916b38b2ed3a08299517bc82a3694f53389bc5cd71ade036935755
4
+ data.tar.gz: 9503d30e4b60b7ae44920cc2d088086cfe605b56e70e80bc3b6c4687a282b152
5
5
  SHA512:
6
- metadata.gz: 5f929f35717b7605466d55ac47e6a39410ac7ce2294cdbaa34f5114309f21f1f714645e64c0f1a291ff8b00a4250f7e077f7cafa5a3c6ff7c5a9242ebc11f329
7
- data.tar.gz: 51dfb5a4e72904fe567a3a2442f9a2e9220c785b6286282ab14e77b9f8d3b5e3bfa05a605930751de12b0a63040ad6138ce33af0a16a11c514301045466ecff3
6
+ metadata.gz: f14cbe747d41187ba986958d91118e98fe6f6fd458eb5d9d30e6d518e964b4f88cbe4a8e5a6eca6dfe3e68fb4a8917b3aae531eea9b86b0c7010a1b8a004f4bb
7
+ data.tar.gz: 36c44c53cc8bece4598c77033ed0251e275cd0b407cba993161606e48397c656eafe1ab5ab4aeed1601534878924ce0f9c59805a1c5117012f3296f2543a47b6
@@ -9,75 +9,105 @@ module Fastlane
9
9
  UI.message("The xcresult_to_junit plugin has started!")
10
10
  all_results = Helper::XcresultToJunitHelper.load_results(params[:xcresult_path])['actions']['_values']
11
11
  all_results.each do |test_run|
12
- if test_run['actionResult']['testsRef'] # Skip if section has no testRef data as this means its not a test run
13
- map = {}
14
- junit_folder = Helper::XcresultToJunitHelper.save_device_details_to_file(params[:output_path], test_run['runDestination'])
15
- test_run_id = test_run['actionResult']['testsRef']['id']['_value']
16
- all_tests = Helper::XcresultToJunitHelper.load_object(params[:xcresult_path], test_run_id)['summaries']['_values'][0]['testableSummaries']['_values']
17
- test_suites = []
18
- all_tests.each do |target|
19
- target_name = target['targetName']['_value']
20
- unless target['tests']
21
- failure_summary = target['failureSummaries']['_values'][0]
22
- test_suites << { name: target_name, error: failure_summary['message']['_value'] }
23
- next
24
- end
12
+ next unless test_run['actionResult']['testsRef'] # Skip if section has no testRef data as this means its not a test run
13
+ map = {}
14
+ junit_folder = Helper::XcresultToJunitHelper.save_device_details_to_file(params[:output_path], test_run['runDestination'])
15
+ test_run_id = test_run['actionResult']['testsRef']['id']['_value']
16
+ all_tests = Helper::XcresultToJunitHelper.load_object(params[:xcresult_path], test_run_id)['summaries']['_values'][0]['testableSummaries']['_values']
17
+ test_suites = []
18
+ all_tests.each do |target|
19
+ target_name = target['targetName']['_value']
20
+ unless target['tests']
21
+ failure_summary = target['failureSummaries']['_values'][0]
22
+ test_suites << { name: target_name, error: failure_summary['message']['_value'] }
23
+ next
24
+ end
25
+ test_classes = []
26
+ if defined?(target['tests']['_values'][0]['subtests']['_values'][0]['subtests']['_values'])
25
27
  test_classes = target['tests']['_values'][0]['subtests']['_values'][0]['subtests']['_values']
26
- test_classes.each do |test_class|
27
- suite_name = "#{target_name}.#{test_class['name']['_value']}"
28
- suite = { name: suite_name, cases: [] }
29
- if test_class['subtests']
30
- test_class['subtests']['_values'].each do |test|
31
- duration = 0
32
- duration = test['duration']['_value'] if test['duration']
33
- testcase_name = test['name']['_value'].tr('()', '')
34
- tags = testcase_name.split('_')[1..-1]
35
- testcase_name = testcase_name.split('_').first
36
- testcase = { name: testcase_name, time: duration }
37
- map["#{suite_name}.#{testcase_name}"] = {'files' => [], 'tags' => tags}
28
+ end
29
+ test_classes.each do |test_class|
30
+ suite_name = "#{target_name}.#{test_class['name']['_value']}"
31
+ suite = { name: suite_name, cases: [] }
32
+ if test_class['subtests']
33
+ test_class['subtests']['_values'].each do |test|
34
+ duration = 0
35
+ duration = test['duration']['_value'] if test['duration']
36
+ testcase_name = test['name']['_value'].tr('()', '')
37
+ tags = testcase_name.split('_')[1..-1]
38
+ testcase_name = testcase_name.split('_').first
39
+ testcase = { name: testcase_name, time: duration }
40
+ map["#{suite_name}.#{testcase_name}"] = { 'files' => [], 'tags' => tags }
38
41
 
39
- if defined?(test['summaryRef']['id']['_value'])
40
- summaryRef = test['summaryRef']['id']['_value']
41
- ref = Helper::XcresultToJunitHelper.load_object(params[:xcresult_path], summaryRef)
42
- if defined?(ref['activitySummaries']['_values'])
43
- ref['activitySummaries']['_values'].each do |summary|
44
- if summary['attachments']
45
- summary['attachments']['_values'].each do |attachment|
46
- timestamp = DateTime.parse(attachment['timestamp']['_value']).to_time.to_i
47
- name = attachment['name']['_value']
48
- folder_name = "#{suite_name}.#{testcase_name}"
49
- id = attachment['payloadRef']['id']['_value']
50
- Helper::XcresultToJunitHelper.fetch_screenshot(params[:xcresult_path], "#{junit_folder}/attachments/#{folder_name}", "#{id}.png", id)
51
- map[folder_name]['files'].push({'description' => name, 'mime-type' => 'image/png', 'path' => "#{folder_name}/#{id}.png", 'timestamp' => timestamp})
52
- end
53
- end
42
+ if defined?(test['summaryRef']['id']['_value'])
43
+ summary_ref = test['summaryRef']['id']['_value']
44
+ ref = Helper::XcresultToJunitHelper.load_object(params[:xcresult_path], summary_ref)
45
+ if defined?(ref['activitySummaries']['_values'])
46
+ ref['activitySummaries']['_values'].each do |summary|
47
+ next unless summary['attachments']
48
+ summary['attachments']['_values'].each do |attachment|
49
+ timestamp = DateTime.parse(attachment['timestamp']['_value']).to_time.to_i
50
+ filename = attachment['filename']['_value']
51
+ name = attachment['name']['_value']
52
+ folder_name = "#{suite_name}.#{testcase_name}"
53
+ id = attachment['payloadRef']['id']['_value']
54
+ Helper::XcresultToJunitHelper.fetch_screenshot(params[:xcresult_path], "#{junit_folder}/attachments/#{folder_name}", filename.to_s, id)
55
+ map[folder_name]['files'].push({ 'description' => name, 'mime-type' => 'image/png', 'path' => "#{folder_name}/#{filename}", 'timestamp' => timestamp })
54
56
  end
55
57
  end
56
58
  end
57
59
 
58
- if test['testStatus']['_value'] == 'Failure'
59
- failure = Helper::XcresultToJunitHelper.load_object(params[:xcresult_path], test['summaryRef']['id']['_value'])['failureSummaries']['_values'][0]
60
- filename = failure['fileName']['_value']
61
- message = failure['message']['_value']
62
- if filename == '<unknown>'
63
- testcase[:error] = message
64
- else
65
- testcase[:failure] = message
66
- testcase[:failure_location] = "#{filename}:#{failure['lineNumber']['_value']}"
60
+ if defined?(ref['performanceMetrics']['_value'])
61
+ performancemetrics = ""
62
+ ref['performanceMetrics']['_values'].each do |metric|
63
+ metricname = metric['displayName']['_value']
64
+ if defined?(metric['baselineAverage']['_value'])
65
+ metricbaseline = metric['baselineAverage']['_value']
66
+ else
67
+ metricbaseline = 0
68
+ end
69
+ metricmaxdev = metric['maxPercentRelativeStandardDeviation']['_value']
70
+ metricunit = metric['unitOfMeasurement']['_value']
71
+ metricave = 0
72
+ measurecount = 0
73
+ metric['measurements']['_values'].each do |measure|
74
+ metricave += measure['_value'].to_f
75
+ measurecount += 1
76
+ end
77
+ metricave = (metricave / measurecount).round(2)
78
+ if metricbaseline != 0
79
+ metricresult = (((metricbaseline.to_f - metricave) / metricbaseline.to_f) * 100).round(2)
80
+ else
81
+ metricresult = 0
82
+ end
83
+ performancemetric = "\nMetric: #{metricname}\nResult: #{metricresult}%\nAverage: #{metricave}#{metricunit}\nBaseline: #{metricbaseline}#{metricunit}\nMax Deviation: #{metricmaxdev}%\n\n"
84
+ performancemetrics << performancemetric
67
85
  end
86
+ testcase[:performance] = performancemetrics
87
+ end
88
+ end
89
+ if test['testStatus']['_value'] == 'Failure'
90
+ failure = Helper::XcresultToJunitHelper.load_object(params[:xcresult_path], test['summaryRef']['id']['_value'])['failureSummaries']['_values'][0]
91
+ filename = failure.dig('fileName', '_value')
92
+ message = failure['message']['_value']
93
+ if filename == '<unknown>' || filename.nil?
94
+ testcase[:error] = message
95
+ else
96
+ testcase[:failure] = message
97
+ testcase[:failure_location] = "#{filename}:#{failure['lineNumber']['_value']}"
68
98
  end
69
- suite[:cases] << testcase
70
99
  end
100
+ suite[:cases] << testcase
71
101
  end
72
- suite[:count] = suite[:cases].size
73
- suite[:failures] = suite[:cases].count { |testcase| testcase[:failure] }
74
- suite[:errors] = suite[:cases].count { |testcase| testcase[:error] }
75
- test_suites << suite
76
102
  end
103
+ suite[:count] = suite[:cases].size
104
+ suite[:failures] = suite[:cases].count { |testcase| testcase[:failure] }
105
+ suite[:errors] = suite[:cases].count { |testcase| testcase[:error] }
106
+ test_suites << suite
77
107
  end
78
- Helper::XcresultToJunitHelper.generate_junit(junit_folder, test_suites)
79
- Helper::XcresultToJunitHelper.save_screenshot_mapping(map, "#{junit_folder}/attachments/")
80
108
  end
109
+ Helper::XcresultToJunitHelper.generate_junit(junit_folder, test_suites)
110
+ Helper::XcresultToJunitHelper.save_screenshot_mapping(map, "#{junit_folder}/attachments/")
81
111
  end
82
112
  UI.message("The xcresult_to_junit plugin has finished!")
83
113
  end
@@ -105,17 +135,17 @@ module Fastlane
105
135
  description: "The path to the xcresult file",
106
136
  optional: false,
107
137
  type: String),
108
- FastlaneCore::ConfigItem.new(key: :output_path,
109
- env_name: "XCRESULT_TO_JUNIT_OUTPUT_PATH",
110
- description: "The path where the output will be placed",
111
- optional: false,
112
- type: String)
113
- ]
114
- end
115
-
116
- def self.is_supported?(platform)
117
- [:ios, :mac].include?(platform)
118
- end
119
- end
138
+ FastlaneCore::ConfigItem.new(key: :output_path,
139
+ env_name: "XCRESULT_TO_JUNIT_OUTPUT_PATH",
140
+ description: "The path where the output will be placed",
141
+ optional: false,
142
+ type: String)
143
+ ]
144
+ end
145
+
146
+ def self.is_supported?(platform)
147
+ [:ios, :mac].include?(platform)
120
148
  end
121
149
  end
150
+ end
151
+ end
@@ -8,18 +8,18 @@ module Fastlane
8
8
  module Helper
9
9
  class XcresultToJunitHelper
10
10
  def self.load_object(xcresult_path, id)
11
- JSON.load FastlaneCore::CommandExecutor.execute(command: "xcrun xcresulttool get --format json --path #{xcresult_path} --id #{id}")
11
+ JSON.parse(FastlaneCore::CommandExecutor.execute(command: "xcrun xcresulttool get --format json --path #{xcresult_path} --id #{id}"))
12
12
  end
13
13
 
14
14
  def self.load_results(xcresult_path)
15
- JSON.load FastlaneCore::CommandExecutor.execute(command: "xcrun xcresulttool get --format json --path #{xcresult_path}")
15
+ JSON.parse(FastlaneCore::CommandExecutor.execute(command: "xcrun xcresulttool get --format json --path #{xcresult_path}"))
16
16
  end
17
17
 
18
18
  def self.fetch_screenshot(xcresult_path, output_path, file_name, id)
19
- if !File.directory?(output_path)
20
- FileUtils.mkdir output_path
19
+ unless File.directory?(output_path)
20
+ FileUtils.mkdir(output_path)
21
21
  end
22
- JSON.load FastlaneCore::CommandExecutor.execute(command: "xcrun xcresulttool export --path #{xcresult_path} --output-path #{output_path}/#{file_name} --id #{id} --type file")
22
+ FastlaneCore::CommandExecutor.execute(command: "xcrun xcresulttool export --path #{xcresult_path} --output-path \"#{output_path}/#{file_name}\" --id #{id} --type file")
23
23
  end
24
24
 
25
25
  def self.save_screenshot_mapping(map_hash, output_path)
@@ -37,9 +37,8 @@ module Fastlane
37
37
  }.to_json
38
38
 
39
39
  junit_folder = "#{output_path}/ios-#{device_udid}.junit"
40
- FileUtils.rm_rf junit_folder
41
- FileUtils.mkdir junit_folder
42
- FileUtils.mkdir "#{junit_folder}/attachments"
40
+ FileUtils.rm_rf(junit_folder)
41
+ FileUtils.mkdir_p("#{junit_folder}/attachments")
43
42
  File.open("#{junit_folder}/device.json", 'w') do |f|
44
43
  f << device_details
45
44
  end
@@ -47,52 +46,52 @@ module Fastlane
47
46
  end
48
47
 
49
48
  def self.junit_file_start
50
- puts '<?xml version="1.0" encoding="UTF-8"?>'
51
- puts '<testsuites>'
49
+ puts('<?xml version="1.0" encoding="UTF-8"?>')
50
+ puts('<testsuites>')
52
51
  end
53
52
 
54
53
  def self.junit_file_end
55
- puts '</testsuites>'
54
+ puts('</testsuites>')
56
55
  end
57
56
 
58
57
  def self.junit_suite_error(suite)
59
- puts "<testsuite name=#{suite[:name].encode xml: :attr} errors='1'>"
60
- puts "<error>#{suite[:error].encode xml: :text}</error>"
58
+ puts("<testsuite name=#{suite[:name].encode(xml: :attr)} errors='1'>")
59
+ puts("<error>#{suite[:error].encode(xml: :text)}</error>")
61
60
  end
62
61
 
63
62
  def self.junit_suite_start(suite)
64
- puts "<testsuite name=#{suite[:name].encode xml: :attr} tests='#{suite[:count]}' failures='#{suite[:failures]}' errors='#{suite[:errors]}'>"
63
+ puts("<testsuite name=#{suite[:name].encode(xml: :attr)} tests='#{suite[:count]}' failures='#{suite[:failures]}' errors='#{suite[:errors]}'>")
65
64
  end
66
65
 
67
66
  def self.junit_suite_end
68
- puts '</testsuite>'
67
+ puts('</testsuite>')
69
68
  end
70
69
 
71
70
  def self.junit_testcase_start(suite, testcase)
72
- print "<testcase name=#{testcase[:name].encode xml: :attr} classname=#{suite[:name].encode xml: :attr} time='#{testcase[:time]}'"
71
+ print("<testcase name=#{testcase[:name].encode(xml: :attr)} classname=#{suite[:name].encode(xml: :attr)} time='#{testcase[:time]}'>")
73
72
  end
74
73
 
75
- def self.junit_testcase_success
76
- puts '/>'
74
+ def self.junit_testcase_end
75
+ puts('</testcase>')
77
76
  end
78
77
 
79
78
  def self.junit_testcase_failure(testcase)
80
- puts '>'
81
- puts "<failure message=#{testcase[:failure].encode xml: :attr}>#{testcase[:failure_location].encode xml: :text}</failure>"
82
- puts '</testcase>'
79
+ puts("<failure message=#{testcase[:failure].encode(xml: :attr)}>#{testcase[:failure_location].encode(xml: :text)}</failure>")
83
80
  end
84
81
 
85
82
  def self.junit_testcase_error(testcase)
86
- puts '>'
87
- puts "<error>#{testcase[:error].encode xml: :text}</error>"
88
- puts '</testcase>'
83
+ puts("<error>#{testcase[:error].encode(xml: :text)}</error>")
84
+ end
85
+
86
+ def self.junit_testcase_performance(testcase)
87
+ puts("<system-out>#{testcase[:performance]}</system-out>")
89
88
  end
90
89
 
91
90
  def self.generate_junit(junit_folder, test_suites)
92
91
  File.open("#{junit_folder}/results.xml", 'w') do |fo|
93
92
  old_stdout = $stdout
94
93
  $stdout = fo
95
- Helper::XcresultToJunitHelper.junit_file_start()
94
+ Helper::XcresultToJunitHelper.junit_file_start
96
95
  test_suites.each do |suite|
97
96
  if suite[:error]
98
97
  Helper::XcresultToJunitHelper.junit_suite_error(suite)
@@ -104,14 +103,16 @@ module Fastlane
104
103
  Helper::XcresultToJunitHelper.junit_testcase_failure(testcase)
105
104
  elsif testcase[:error]
106
105
  Helper::XcresultToJunitHelper.junit_testcase_error(testcase)
107
- else
108
- Helper::XcresultToJunitHelper.junit_testcase_success()
109
106
  end
107
+ if testcase[:performance]
108
+ Helper::XcresultToJunitHelper.junit_testcase_performance(testcase)
109
+ end
110
+ Helper::XcresultToJunitHelper.junit_testcase_end
110
111
  end
111
112
  end
112
- Helper::XcresultToJunitHelper.junit_suite_end()
113
+ Helper::XcresultToJunitHelper.junit_suite_end
113
114
  end
114
- Helper::XcresultToJunitHelper.junit_file_end()
115
+ Helper::XcresultToJunitHelper.junit_file_end
115
116
  $stdout = old_stdout
116
117
  end
117
118
  end
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module XcresultToJunit
3
- VERSION = "0.2.2"
3
+ VERSION = "0.3.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane-plugin-xcresult_to_junit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shane Birdsall
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-03 00:00:00.000000000 Z
11
+ date: 2021-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -136,7 +136,7 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: 2.134.0
139
- description:
139
+ description:
140
140
  email: shane.birdsall@fiserv.com
141
141
  executables: []
142
142
  extensions: []
@@ -152,7 +152,7 @@ homepage: https://github.com/zanizrules/fastlane-plugin-xcresult_to_junit
152
152
  licenses:
153
153
  - MIT
154
154
  metadata: {}
155
- post_install_message:
155
+ post_install_message:
156
156
  rdoc_options: []
157
157
  require_paths:
158
158
  - lib
@@ -167,9 +167,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
167
167
  - !ruby/object:Gem::Version
168
168
  version: '0'
169
169
  requirements: []
170
- rubyforge_project:
170
+ rubyforge_project:
171
171
  rubygems_version: 2.7.6.2
172
- signing_key:
172
+ signing_key:
173
173
  specification_version: 4
174
174
  summary: Produces junit xml files from Xcode 11+ xcresult files
175
175
  test_files: []