fastlane-plugin-xcresult_to_junit 0.2.5 → 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: f8ea55f58789c5cc56abd231d9ffeaa21e51ecddf242de33ad17bce1bf15c059
4
- data.tar.gz: 50b033dfc0caa9e5fe1eecc90d94afa342e4dfdc1466b0a157354cc500da4420
3
+ metadata.gz: c185b9548c916b38b2ed3a08299517bc82a3694f53389bc5cd71ade036935755
4
+ data.tar.gz: 9503d30e4b60b7ae44920cc2d088086cfe605b56e70e80bc3b6c4687a282b152
5
5
  SHA512:
6
- metadata.gz: 88a65b73cb50b3ac83b61b00734f0bbdfe85de3dd5761ca57ac10a81db5716e9ea9e5564b04a43847bfac65a3ded8fd9821ac7a8be117fe3fd66ce77ea520439
7
- data.tar.gz: 8d67362431ba0968263d54f1118dc9910278fc190440533b2c3aed8e22ed6eebe2fe2f84044b4d70bc3583ee042eae8154ec71f6b371dfa187953a89d8a694c0
6
+ metadata.gz: f14cbe747d41187ba986958d91118e98fe6f6fd458eb5d9d30e6d518e964b4f88cbe4a8e5a6eca6dfe3e68fb4a8917b3aae531eea9b86b0c7010a1b8a004f4bb
7
+ data.tar.gz: 36c44c53cc8bece4598c77033ed0251e275cd0b407cba993161606e48397c656eafe1ab5ab4aeed1601534878924ce0f9c59805a1c5117012f3296f2543a47b6
@@ -9,108 +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
25
- test_classes = []
26
- if defined?(target['tests']['_values'][0]['subtests']['_values'][0]['subtests']['_values'])
27
- test_classes = target['tests']['_values'][0]['subtests']['_values'][0]['subtests']['_values']
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}
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'])
27
+ test_classes = target['tests']['_values'][0]['subtests']['_values'][0]['subtests']['_values']
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 }
41
41
 
42
- if defined?(test['summaryRef']['id']['_value'])
43
- summaryRef = test['summaryRef']['id']['_value']
44
- ref = Helper::XcresultToJunitHelper.load_object(params[:xcresult_path], summaryRef)
45
- if defined?(ref['activitySummaries']['_values'])
46
- ref['activitySummaries']['_values'].each do |summary|
47
- if 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}", id)
55
- map[folder_name]['files'].push({'description' => name, 'mime-type' => 'image/png', 'path' => "#{folder_name}/#{filename}", 'timestamp' => timestamp})
56
- end
57
- 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 })
58
56
  end
59
57
  end
58
+ end
60
59
 
61
- if defined?(ref['performanceMetrics']['_value'])
62
- performancemetrics = ""
63
- ref['performanceMetrics']['_values'].each do |metric|
64
- metricname = metric['displayName']['_value']
65
- if defined?(metric['baselineAverage']['_value'])
66
- metricbaseline = metric['baselineAverage']['_value']
67
- else
68
- metricbaseline = 0
69
- end
70
- metricmaxdev = metric['maxPercentRelativeStandardDeviation']['_value']
71
- metricunit = metric['unitOfMeasurement']['_value']
72
- metricave = 0
73
- measurecount = 0
74
- metric['measurements']['_values'].each do |measure|
75
- metricave = metricave + measure['_value'].to_f
76
- measurecount += 1
77
- end
78
- metricave = (metricave/measurecount).round(2)
79
- if metricbaseline != 0
80
- metricresult = (((metricbaseline.to_f-metricave)/metricbaseline.to_f)*100).round(2)
81
- else
82
- metricresult = 0
83
- end
84
- performancemetric = "\nMetric: #{metricname}\nResult: #{metricresult}%\nAverage: #{metricave}#{metricunit}\nBaseline: #{metricbaseline}#{metricunit}\nMax Deviation: #{metricmaxdev}%\n\n"
85
- performancemetrics << performancemetric
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
86
76
  end
87
- testcase[:performance] = performancemetrics
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
88
85
  end
86
+ testcase[:performance] = performancemetrics
89
87
  end
90
-
91
- if test['testStatus']['_value'] == 'Failure'
92
- failure = Helper::XcresultToJunitHelper.load_object(params[:xcresult_path], test['summaryRef']['id']['_value'])['failureSummaries']['_values'][0]
93
- filename = failure['fileName']['_value']
94
- message = failure['message']['_value']
95
- if filename == '<unknown>'
96
- testcase[:error] = message
97
- else
98
- testcase[:failure] = message
99
- testcase[:failure_location] = "#{filename}:#{failure['lineNumber']['_value']}"
100
- 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']}"
101
98
  end
102
- suite[:cases] << testcase
103
99
  end
100
+ suite[:cases] << testcase
104
101
  end
105
- suite[:count] = suite[:cases].size
106
- suite[:failures] = suite[:cases].count { |testcase| testcase[:failure] }
107
- suite[:errors] = suite[:cases].count { |testcase| testcase[:error] }
108
- test_suites << suite
109
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
110
107
  end
111
- Helper::XcresultToJunitHelper.generate_junit(junit_folder, test_suites)
112
- Helper::XcresultToJunitHelper.save_screenshot_mapping(map, "#{junit_folder}/attachments/")
113
108
  end
109
+ Helper::XcresultToJunitHelper.generate_junit(junit_folder, test_suites)
110
+ Helper::XcresultToJunitHelper.save_screenshot_mapping(map, "#{junit_folder}/attachments/")
114
111
  end
115
112
  UI.message("The xcresult_to_junit plugin has finished!")
116
113
  end
@@ -138,17 +135,17 @@ module Fastlane
138
135
  description: "The path to the xcresult file",
139
136
  optional: false,
140
137
  type: String),
141
- FastlaneCore::ConfigItem.new(key: :output_path,
142
- env_name: "XCRESULT_TO_JUNIT_OUTPUT_PATH",
143
- description: "The path where the output will be placed",
144
- optional: false,
145
- type: String)
146
- ]
147
- end
148
-
149
- def self.is_supported?(platform)
150
- [:ios, :mac].include?(platform)
151
- end
152
- 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)
153
148
  end
154
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
74
  def self.junit_testcase_end
76
- puts '</testcase>'
75
+ puts('</testcase>')
77
76
  end
78
77
 
79
78
  def self.junit_testcase_failure(testcase)
80
- puts "<failure message=#{testcase[:failure].encode xml: :attr}>#{testcase[:failure_location].encode xml: :text}</failure>"
79
+ puts("<failure message=#{testcase[:failure].encode(xml: :attr)}>#{testcase[:failure_location].encode(xml: :text)}</failure>")
81
80
  end
82
81
 
83
82
  def self.junit_testcase_error(testcase)
84
- puts "<error>#{testcase[:error].encode xml: :text}</error>"
83
+ puts("<error>#{testcase[:error].encode(xml: :text)}</error>")
85
84
  end
86
85
 
87
86
  def self.junit_testcase_performance(testcase)
88
- puts "<system-out>#{testcase[:performance]}</system-out>"
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)
@@ -111,9 +110,9 @@ module Fastlane
111
110
  Helper::XcresultToJunitHelper.junit_testcase_end
112
111
  end
113
112
  end
114
- Helper::XcresultToJunitHelper.junit_suite_end()
113
+ Helper::XcresultToJunitHelper.junit_suite_end
115
114
  end
116
- Helper::XcresultToJunitHelper.junit_file_end()
115
+ Helper::XcresultToJunitHelper.junit_file_end
117
116
  $stdout = old_stdout
118
117
  end
119
118
  end
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module XcresultToJunit
3
- VERSION = "0.2.5"
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.5
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shane Birdsall
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-16 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